5

Tôi thấy lỗi lạ vì tôi đã chuyển từ Rails 3.0.11 sang 3.1.3. Dưới đây là một mã độc lập để sao chép các lỗi:find_or_initialize_by trên liên kết has_many gây ra lỗi trùng lặp

require 'active_record' 

ActiveRecord::Base.establish_connection(
    :adapter => 'mysql2', 
    :username => 'root', 
    :database => "some_development" 
) 

class User < ActiveRecord::Base 
    has_many :favorites 
end 

class Favorite < ActiveRecord::Base 
    belongs_to :user 
end 

u = User.create 

# f = u.favorites.find_or_create_by_site_id(123)  #=> pass 
f = u.favorites.find_or_initialize_by_site_id(123) #=> fail 
f.some_attr = 'foo' 
f.save! 

u.name = 'bar' 
u.save!    # ActiveRecord::RecordNotUnique will be thrown here! 

sẽ kết thúc ActiveRecord::RecordNotUnique cố gắng INSERT cùng một kỷ lục vào bảng favorites. (Lưu ý rằng với ví dụ này, cặp (user_id, site_id) phải là duy nhất trên mục yêu thích)

Điều thú vị là nếu tôi sử dụng find_or_create thay vì find_or_initialize thì không có ngoại lệ nào được nêu ra.

Trong theo dõi ngăn xếp, tôi nhận thấy autosave_association được gọi, không biết tại sao, nhưng thực tế has_many :favorites, :autosave => false thay vì has_many :favorites cũng xóa lỗi. Như tôi chưa bao giờ quan tâm về autosave, tôi thậm chí không chắc chắn nếu :autosave => false là một ý hay hay không.

Tôi đang làm gì sai hoặc là lỗi Rails? Bất cứ ai có thể cho tôi một con trỏ để xem xét?

+0

Liệu các mô hình tài khoản có một xác nhận cho tính độc đáo của một trường? Ngoài ra những gì là nhận xét ra dòng với '# => vượt qua' bên cạnh nó? Bạn đang cố tạo hai phiên bản yêu thích cùng một lúc hay gì đó? – Batkins

+0

Có, Mô hình người dùng có một loạt các xác thực bao gồm tính duy nhất, mặc dù tôi không chắc nó liên quan như thế nào. Nếu bạn bình luận trong dòng của find_or_create thay vì find_or_initialize, nó sẽ vượt qua mà không có lỗi, như được mô tả trong câu hỏi của tôi. – kenn

+0

Bạn có thể thử điều này: thay vì 'u.save!', Làm 'u.save' và sau đó' đặt u.errors' hoặc 'p u.errors'. Các lỗi là gì. Tôi có một cảm giác rằng đây là một vấn đề mà bạn đang tạo ra một người dùng không vượt qua một trong những xác nhận tính duy nhất (vì bạn đang sử dụng một 'User.create' chung không có thuộc tính đang được nạp vào). – Batkins

Trả lời

5

bạn đã thử gọi điện thoại f.save! chưa? u.save! sẽ lưu cả yêu thích và người dùng.

> f = u.favorites.find_or_initialize_by_site_id(123) 

> u.favorites.include?(f) 
==> false 

> f2 = u.favorites.build(:site_id => 123) 

> u.favorites.include?(f2) 
==> true 

Tôi nghĩ điều bạn thấy là yêu thích mới f bạn đã tạo là một đối tượng riêng biệt. Do đó bạn sẽ tiết kiệm f, trong khi có một yêu thích chưa được lưu khác quá trong u.favourites. Do đó, lỗi không phải duy nhất xảy ra khi bạn lưu u (cũng lưu các mục ưa thích)

Tôi không chắc đây có phải là lỗi mới được giới thiệu trong Rails 3.1 hay không. Nó có thể là cố ý.

Trong Rails 3.0 find_or_initialize_by không cư mảng

> f = u.favorites.find_or_initialize_by_site_id(123) 

> u.favorites 
==> [] 

Trông giống như một lỗi - xem https://github.com/rails/rails/pull/3610

+0

Nó phải ở đó vì 'u.save! 'Nằm ở một nơi xa trong mã từ' f.save! ', Và có khả năng' u' không bị bẩn và bỏ qua việc lưu. Tôi muốn biết lý do tại sao nó gây ra lỗi. – kenn

Các vấn đề liên quan