2012-08-14 38 views
14

Phải, vì vậy tôi có một liên kết đa hình cho phép các loại đối tượng khác nhau được ưu tiên. Vì vậy, một người có thể yêu thích một sản phẩm, hoặc một người, hoặc bất cứ điều gì. Những gì tôi muốn làm là bảo vệ chống lại một người nào đó nhân bản một yêu thích bằng cách xác nhận tính duy nhất trong mô hình Yêu thích.Xác nhận tính độc đáo của phạm vi trong các mô hình liên kết đa hình

class Favorite < ActiveRecord::Base 
belongs_to :favoritable, :polymorphic => true 
belongs_to :user 

attr_accessible :user 

validates_presence_of :user 
validates :user_id, :uniqueness => { :scope => [:favoritable_type, :favoritable_id] } 
end 

Xác thực có vẻ đang hoạt động nhưng vì lý do gì đó hàng mới yêu thích vẫn được tạo với user_id khi cố gắng sao chép mục nhập.

enter image description here

Có cách nào để dừng lưu lần đầu này không?

Dường như Rails đang tạo ra sự xâm nhập DB và sau đó cập nhật nó với favoritable_id và favoritable_type như sau:

SQL (28.3ms) INSERT INTO "favorites" ("created_at", "favoritable_id", "favoritable_type", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Tue, 14 Aug 2012 10:26:31 UTC +00:00], ["favoritable_id", nil], ["favoritable_type", nil], ["updated_at", Tue, 14 Aug 2012 10:26:31 UTC +00:00], ["user_id", 23]] 
    (7.8ms) COMMIT 
    (0.1ms) BEGIN 
    Favorite Exists (0.3ms) SELECT 1 AS one FROM "favorites" WHERE ("favorites"."user_id" = 23 AND "favorites"."id" != 123 AND "favorites"."favoritable_type" = 'Style' AND "favorites"."favoritable_id" = 29) LIMIT 1 
    (0.2ms) UPDATE "favorites" SET "favoritable_id" = 29, "favoritable_type" = 'Style', "updated_at" = '2012-08-14 10:26:31.943937' WHERE "favorites"."id" = 123 
    (6.7ms) COMMIT 
    (0.1ms) BEGIN 
+0

Áp-ram: bạn đã bao giờ con số này ra? – MAckerman

Trả lời

21

Nếu bạn quan sát kỹ bạn có thể thấy rằng xác nhận tính độc đáo chỉ hoạt động tốt :)

validates :user_id, :uniqueness => { :scope => [:favoritable_type, :favoritable_id] } 

Nhìn vào hình ảnh dữ liệu bạn đã thêm. bên trong hình ảnh bạn có thể tìm thấy rằng kỷ lục thứ hai là không có favouritable trong khi đầu tiên có khác nhau do đó 2 hồ sơ là uniq và nó không phải vấn đề với uniqueness nhưng khoảng cách hợp lý của nó.

Nếu bạn nghiêm túc muốn tránh entry thứ hai sau đó giữ lĩnh vực favouritable như bắt buộc

validates :favoritable_type, :favoritable_id, :presence => true 
+0

Xin lỗi kết quả này trong Ưa thích tồn tại (0,4ms) CHỌN 1 NHƯ MỘT TỪ "yêu thích" WHERE ("yêu thích". "User_id" = 36 VÀ "yêu thích". "Favoritable_type" IS NULL VÀ "favorites". "Favoritable_id" IS NULL) LIMIT 1 (0.1ms) ROLLBACK Đã hoàn thành 500 lỗi máy chủ nội bộ trong 243ms ActiveRecord :: RecordInvalid (Xác thực không thành công: Loại ưa thích không được để trống, Không được để trống trường hợp ưa thích): – Abram

+1

Bạn cũng có thể thêm tính duy nhất ràng buộc với bảng của bạn thông qua di chuyển: 'add_index (: yêu thích, [: user_id,: favoritable_type,: favoritable_id],: unique => true,: name => 'allowed_one_favorite')' – Darme

0

Bạn có đi qua bưu điện tương tự

Rails 3 uniqueness validation with scope on polymorphic table

Dường add_index đó không thành vấn đề.

+0

Thật tuyệt vời, điều đó đã xảy ra. Sẽ cung cấp cho bạn đánh dấu trong một vài phút khi được cho phép. – Abram

+0

Argh. Tôi không lấy lại. Nó không hoạt động. Tôi đã thử add_index (: favorites, [: user_id,: favoritable_id,: favoritable_type],: unique => true,: name => 'cannot_duplicate_favorite') – Abram

+0

Như đã đề cập trong tài liệu tham khảo - nếu bạn đã có mô hình đó, bạn cần lập chỉ mục bằng tay bởi SQL. Thông thường chỉ mục sẽ được thêm vào thời điểm di chuyển. Kiểm tra một lần. – pdpMathi

5
class Favorite < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :favoritable, polymorphic: true 

    validates :user_id, :favoritable_id, presence: true, 
    numericality: { only_integer: true } 

    validates :favoritable_type, presence: true, 
    inclusion: { 
     in: %w(FirstModelName SecondModelName), 
     message: "%{value} is not a valid" 
    } 

    validates :user_id, uniqueness: { scope: [ :favoritable_type, :favoritable_id ] } 
end 
Các vấn đề liên quan