2012-03-30 43 views
23

Tôi có một người sử dụng và lớp hồ sơ lồng nhau như sau:thuộc tính lồng nhau update_attributes sử dụng chèn chứ không phải cập nhật

class User < ActiveRecord::Base 
    has_one :profile 
    attr_accessible :profile_attributes 
    accepts_nested_attributes_for :profile 
end 

class Profile < ActiveRecord::Base 
    belongs_to :user 
    attr_accessible :name 
end 

user = User.find(1) 
user.profile.id # => 1 
user.update_attributes(profile_attributes: {name: 'some name'}) 
user.profile.id # => 2 

Tôi không hiểu tại sao đường ray được ném đi những hồ sơ cũ và tạo ra một cái mới.

Sử dụng

user.profile.update_attributes({name: 'some name'}) 

chỉ cập nhật hồ sơ cá nhân hiện hành như mong đợi. Nhưng trong trường hợp đó, tôi không tận dụng accept_nested_attributes_for

Có ai biết tại sao cập nhật xảy ra theo cách này không? Tôi không muốn kết thúc với một cơ sở dữ liệu của các hàng hồ sơ không được kết nối với bất kỳ người dùng nào.

+0

có thể là bạn có thể thử, 'user.update_attributes (profile_attributes: {: id => user.profile.id,: name: 'some name'})' –

Trả lời

17

tôi giải quyết vấn đề này bằng cách thêm tùy chọn update_only:

accepts_nested_attributes_for :profile, update_only: true 

Bây giờ một hồ sơ mới chỉ được tạo ra nếu một người không tồn tại.

+3

Tôi khá chắc chắn câu trả lời của @Winfield ist đúng – jones

+0

Tại sao tính năng này không hoạt động? chỉ cần tò mò .. – light24bulbs

+0

Bởi vì mặc định (update_only: false) hoạt động nếu bạn bao gồm id của đối tượng lồng nhau, và nó có ý nghĩa bởi vì nó là cách chính xác để lấy đối tượng lồng nhau từ cơ sở dữ liệu. Thông tin khác đọc http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for – lulalala

21

Nếu bạn kiểm tra biểu mẫu của mình, bạn cần đặt thuộc tính id trong băm thuộc tính lồng nhau cho đối tượng Tiểu sử của bạn. Nếu id không được thiết lập, ActiveRecord giả định đó là một đối tượng mới. Ví dụ: nếu bạn có biểu mẫu ERB xây dựng một tập hợp các tham số 'người dùng' với băm tham số 'profile_attributes' lồng nhau cho cấu hình lồng nhau trong người dùng, bạn có thể bao gồm giá trị ẩn cho id hồ sơ, như thế này :

<%= hidden_field "user[profile_attributes][id]", @profile.id %> 
+0

Làm thế nào để bạn đặt thuộc tính id trong thuộc tính lồng nhau cho đối tượng Profile? – Glide

+0

Đã thêm một số mã mẫu cho biết cách chèn giá trị biểu mẫu ẩn. – Winfield

+0

không phải là ý tưởng này không tốt sao? vì người dùng chỉ có thể gây rối với giá trị id. tham khảo cách sử dụng tùy chọn 'update_only: true' như @jason đã nói – davoclavo

31

Đối với tất cả những người có cùng một vấn đề trong Rails 4: fields_for đã thêm id cho các biểu mẫu lồng nhau của bạn nhưng bạn phải cho phép tham số: id. Tôi chỉ cho phép một tham số: object_name_id và vì điều này không ném bất kỳ lỗi nào tôi đã mất một thời gian cho đến khi tôi thấy điều này trong nhật ký máy chủ. Hy vọng rằng điều này giúp một người nào đó lãng phí thời gian ít hơn tôi về điều này :)

+0

có! cảm ơn bạn, điều này là khó khăn để gỡ lỗi, params mạnh mẽ ngu ngốc! ;-) – andy

+0

đó là nó! :) Cảm ơn – XeNoN

+5

Tôi thấy hữu ích khi thay đổi 'config.action_controller.action_on_unpermitted_parameters' thành': raise' thay vì mặc định, ': log'. Làm cho nó dễ dàng hơn nhiều để gỡ lỗi khi nó thổi lên trong khuôn mặt của bạn! https://github.com/rails/strong_parameters#handling-of-unpermitted-keys – styger

0

Tôi đã gặp phải điều này trong một phiên bản khác của Rails và tôi nghĩ mình sẽ mất trí. Trong khi thêm update_only => true được giải quyết nó, tôi nghĩ rằng đó là một lỗi ở đâu đó trong Rails.

Các triệu chứng trong trường hợp của tôi: Tôi sẽ nhận được liên kết với thuộc tính được xóa và đối tượng lồng nhau mới được tạo - cho đến lần đầu tiên tôi làm mới trang. Sau đó nó hoạt động chính xác.

Trong trường hợp của tôi, tôi đã thêm phương thức before_save vào lớp lồng nhau và in nội dung đã lưu. Tôi cũng đã in các thuộc tính trước khi gọi update_attributes. Họ đã đặt "parent_id" chính xác. Tôi cũng bao gồm trường id ẩn trong biểu mẫu, không thay đổi - điều này là bình thường vì nó đã được bao gồm bằng cách sử dụng fields_for ...

Bất ngờ: Tôi thấy một cuộc gọi cập nhật tạo hai cuộc gọi lưu. Lần lưu đầu tiên sẽ có id đối tượng lồng nhau nhưng null cho id thuộc_toặc. - do đó, điều này sẽ cập nhật bản ghi để đặt "parent_id" thành null. Lần lưu thứ hai sẽ có bộ "parent_id" nhưng nó sẽ có id đối tượng lồng nhau được đặt thành null.

Như tôi đã nói, tôi đã sửa nó bằng cách thêm update_only => true, nhưng tôi nghĩ nó vẫn là một lỗi.

Tôi muốn tìm hiểu xem các triệu chứng trên có áp dụng cho trường hợp của bạn không để xác nhận đây là lỗi.

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