7

Tôi có các lớp sau:Thuộc tính lồng nhau có thể được sử dụng kết hợp với thừa kế không?

  • Dự án
  • Person
  • Person>Developer
  • Person>quản lý

Trong mô hình Project Tôi đã thêm những điều khoản sau đây:

has_and_belongs_to_many :people 
accepts_nested_attributes_for :people 

Và tất nhiên những điều khoản thích hợp trong lớp Person. Làm cách nào để thêm Developer vào một số Project thông qua phương thức nested_attributes? Sau đây không hoạt động:

@p.people_attributes = [{:name => "Epic Beard Man", :type => "Developer"}] 
@p.people 
=> [#<Person id: nil, name: "Epic Beard Man", type: nil>] 

Như bạn có thể thấy type thuộc tính được thiết lập để nil thay vì "Developer".

Trả lời

5

Tôi đã gặp sự cố tương tự vài ngày trước. Cột kế thừa (ví dụ: type) trong mô hình STI là thuộc tính được bảo vệ. Làm như sau để ghi đè bảo vệ mặc định trong lớp Person của bạn.

Rails 2,3

class Person < ActiveRecord::Base 

private 
    def attributes_protected_by_default 
    super - [self.class.inheritance_column] 
    end 
end 

Rails 3

Hãy tham khảo những gợi ý solution bởi @tokland.

Nên biết trước:

Bạn đang trọng hệ thống thuộc tính bảo vệ.

tham khảo:

SO Question on the topic

+0

lưu ý: thao tác này cho Rails 2.3, xem câu trả lời của tôi bên dưới cho Rails 3 – tokland

+0

@tokland, tôi đã không truy cập câu hỏi này trong một thời gian. Tôi đã cập nhật câu trả lời của mình với giải pháp Rails 3. –

+0

tuyệt vời. Tôi muốn viết một 'def self.attributes_protected_by_default' đơn giản, nhưng bất cứ điều gì. – tokland

4

Patches trên không làm việc cho tôi, nhưng điều này đã làm (Rails3):

class ActiveRecord::Reflection::AssociationReflection 
    def build_association(*options) 
    if options.first.is_a?(Hash) and options.first[:type].presence 
     options.first[:type].to_s.constantize.new(*options) 
    else 
     klass.new(*options) 
    end 
    end 
end 

Foo.bars.build (: type =>' Baz ').lớp == Baz Giải pháp

+0

Giải pháp này làm việc cho các hiệp hội, nhưng không phải cho đứng dọc theo xây dựng đối tượng STI. Tôi đã cập nhật câu trả lời của mình với giải pháp Rails 3 chung. –

7

cho Rails3: attributes_protected_by_default tại bây giờ là một đẳng cấp phương pháp:

class Person < ActiveRecord::Base 

    private 

    def self.attributes_protected_by_default 
    super - [inheritance_column] 
    end 
end 
+0

+1 đây là ngắn gọn .. –

+0

Lưu ý: Đảm bảo bạn đặt nó ở gần đầu lớp, * trước * mọi cuộc gọi đến 'attr_protected'. Cuộc gọi đầu tiên tới 'attr_protected' sẽ khiến nó gọi bất kỳ phiên bản' attribute_protected_by_default' nào hiện đang được định nghĩa, đây sẽ là phiên bản mặc định từ AR trừ khi bạn đã ghi đè nó theo thời điểm đó ... –

0

Đối với những người trong chúng ta sử dụng Mongoid, bạn sẽ cần phải thực hiện các _type lĩnh vực truy cập:

class Person 
    include Mongoid::Document 
    attr_accessible :_type 
end 
Các vấn đề liên quan