0

자기 참조 연결이있는 Option이라는 모델이 있습니다. 옵션에는 많은 하위 옵션이있을 수 있으며 하위 옵션에는 상위 옵션이있을 수 있습니다. 나는 또한 cocoon gem에 의해 중첩 된 속성을 사용하여 form_for 옵션에 여러 하위 옵션을 작성합니다. 양식에 옵션을 만들 때 동적으로 하위 옵션을 만들 수 있습니다.레일스 자체 참조 속성 상속

보기/옵션/_form.html.erb :

<%= form_for @option do |f| %> 

    <p> 
    <%= f.label :name %><br> 
    <%= f.text_field :name %><br> 
    <%= f.label :activity %><br> 
    <%= f.select :activity_id, options_for_select(activity_array, @option.activity_id)%><br> 
    </p> 

    <div> 
    <div id="suboptions"> 
     <%= f.fields_for :suboptions do |suboption| %> 
     <%= render 'suboption_fields', f: suboption %> 
     <% end %> 

     <div class="links"> 
     <%= link_to_add_association 'add suboption', f, :suboptions %> 
     </div> 
    </div> 
    </div> 

    <p> 
    <%= f.submit "Send" %> 
    </p> 
<% end %> 

모델/option.rb :

class Option < ApplicationRecord 
    belongs_to :activity 
    has_many :option_students 
    has_many :students, through: :option_students 
    has_many :suboptions, class_name: "Option", foreign_key: "option_id" 
    belongs_to :parent, class_name: "Option", optional: true, foreign_key: "option_id" 
    accepts_nested_attributes_for :suboptions, allow_destroy: true, 
    reject_if: ->(attrs) { attrs['name'].blank? } 

    validates :name, presence: true 

    after_initialize :set_defaults 
    before_update :set_defaults 


    def set_defaults 
     self.suboptions.each do |sbp| 
     sbp.activity_id = self.activity_id 
     end 
    end 

end 

에 Params는 :

def option_params 
    params.require(:option).permit(:name, :activity_id, :students_ids => [], suboptions_attributes: [:id, :name, activity_id, :_destroy]) 
    end 

내가 좋아하는 것 각 ​​하위 옵션을 상속 생성 및 업데이트시 부모의 activity_id 특성 모델에서 set_defaults 메소드를 사용하여이 방법을 시도했는데 새로운 중첩 된 서브 옵션으로 새 옵션에 대해 작업하고 상위의 activity_id를 업데이트하면 하위 옵션의 activity_id도 업데이트합니다. 그러나 업데이트 할 때 다른 하위 옵션을 만들면 상위의 특성을 새 하위 옵션으로 전달하지 않습니다.

답변

3

before_validation 콜백을 사용할 수 있습니다. 예를 들어,

테스트 코드

class Location < ApplicationRecord 
    has_many :children, class_name: 'Location', foreign_key: 'parent_id' 
    accepts_nested_attributes_for :children 
    before_validation :initialize_children 

    attr_accessor :activity 

    def initialize_children 
    children.each { |c| c.activity_id = self.activity_id } 
    end 
end 

레일 콘솔

irb(main):002:0> Location.create({name: "L10", activity_id: 200, :children_attributes => [{name: "L12"}]}) 
    (0.1ms) begin transaction 
    SQL (1.1ms) INSERT INTO "locations" ("name", "activity_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "L10"], ["activity_id", 200], ["created_at", 2017-01-11 04:07:26 UTC], ["updated_at", 2017-01-11 04:07:26 UTC]] 
    SQL (0.1ms) INSERT INTO "locations" ("name", "parent_id", "activity_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["name", "L12"], ["parent_id", "1"], ["activity_id", 200], ["created_at", 2017-01-11 04:07:26 UTC], ["updated_at", 2017-01-11 04:07:26 UTC]] 
    (3.7ms) commit transaction 
=> #<Location id: 1, name: "L10", parent_id: nil, activity_id: 200, created_at: "2017-01-11 04:07:26", updated_at: "2017-01-11 04:07:26"> 
irb(main):003:0> Location.all 
    Location Load (0.2ms) SELECT "locations".* FROM "locations" 
=> #<ActiveRecord::Relation [#<Location id: 1, name: "L10", parent_id: nil, activity_id: 200, created_at: "2017-01-11 04:07:26", updated_at: "2017-01-11 04:07:26">, #<Location id: 2, name: "L12", parent_id: "1", activity_id: 200, created_at: "2017-01-11 04:07:26", updated_at: "2017-01-11 04:07:26">]> 
irb(main):004:0> Location.last 
    Location Load (0.2ms) SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT ? [["LIMIT", 1]] 
=> #<Location id: 2, name: "L12", parent_id: "1", activity_id: 200, created_at: "2017-01-11 04:07:26", updated_at: "2017-01-11 04:07:26"> 
+0

하지만 그것은 내가 값을 업데이트하는 경우 그것은 작동하지 않습니다 아니라고 생각? –

+0

답변을 업데이트했습니다. 체크 아웃. – fossil

+0

이제 이전 자식에 대해서는 작동하지만 새 자식을 추가하면 작동하지 않습니다. 나는이 같은 일을 오전 : 'after_initialize : set_defaults before_update을 : 데프 self.suboptions.each 할 set_defaults set_defaults | SBP를 | sbp.activity_id = self.activity_id end ' –