복붙노트

[RUBY-ON-RAILS] 다형성 belongs_to와 accepts_nested_attributes_for

RUBY-ON-RAILS

다형성 belongs_to와 accepts_nested_attributes_for

나는 accepts_nested_attributes_for와 다형성의 관계를 설정하고 싶습니다. 여기에 코드입니다 :

class Contact <ActiveRecord::Base
  has_many :jobs, :as=>:client
end

class Job <ActiveRecord::Base
  belongs_to :client, :polymorphic=>:true
  accepts_nested_attributes_for :client
end

내가 액세스 Job.create (을하려고 할 때 ..., : client_attributes => {...} 나에게 나가서 설명하자면 NameError을 제공 : 초기화되지 않은 일정 작업을 :: 클라이언트

해결법

  1. ==============================

    1.나는 또한 문제 했어 "하면 ArgumentError :. 협회 MODEL_NAME을 구축 할 수 없습니다 당신이 다형성 one-to-one 연관 구축을 위해 노력하고 있습니까?"

    나는 또한 문제 했어 "하면 ArgumentError :. 협회 MODEL_NAME을 구축 할 수 없습니다 당신이 다형성 one-to-one 연관 구축을 위해 노력하고 있습니까?"

    그리고 나는 이런 종류의 문제에 대한 더 나은 솔루션을 발견했다. 당신은 기본 방법을 사용할 수 있습니다. Rails3 내부 nested_attributes 구현에 모습을 수 있습니다 :

    elsif !reject_new_record?(association_name, attributes)
      method = "build_#{association_name}"
      if respond_to?(method)
        send(method, attributes.except(*UNASSIGNABLE_KEYS))
      else
        raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?"
      end
    end
    

    그래서 실제로 우리는 여기에 어떻게해야합니까? 우리의 모델 내부 빌드 # {협회 이름을} 만드는 것입니다. 난 완전히 바닥에 예를 들어 작업 않았다했습니다 :

    class Job <ActiveRecord::Base
      CLIENT_TYPES = %w(Contact)
    
      attr_accessible :client_type, :client_attributes
    
      belongs_to :client, :polymorphic => :true
    
      accepts_nested_attributes_for :client
    
      protected
    
      def build_client(params, assignment_options)
        raise "Unknown client_type: #{client_type}" unless CLIENT_TYPES.include?(client_type)
        self.client = client_type.constantize.new(params)
      end
    end
    
  2. ==============================

    2.드디어 레일 4.x를 사용한 일이있어 이것은 그들에게 너무 +1, 드미트리 / ScotterC의 대답의 기반으로한다.

    드디어 레일 4.x를 사용한 일이있어 이것은 그들에게 너무 +1, 드미트리 / ScotterC의 대답의 기반으로한다.

    STEP 1. 여기 다형성 협회와 전체 모델이며, 시작하려면 :

    # app/models/polymorph.rb
    class Polymorph < ActiveRecord::Base
      belongs_to :associable, polymorphic: true
    
      accepts_nested_attributes_for :associable
    
      def build_associable(params)
        self.associable = associable_type.constantize.new(params)
      end
    end
    
    # For the sake of example:
    # app/models/chicken.rb
    class Chicken < ActiveRecord::Base
      has_many: :polymorphs, as: :associable
    end
    

    예,의 아무것도 정말 새로운 것을. 그러나 어디 polymorph_type에서 온 않습니다 궁금 할 방법과 그 값의 집합이다? 다형성 협회가 테이블에 _id와 _type 열을 추가 이후는 기본 데이터베이스 레코드의 부분입니다. 약자로, 때 build_associable이 실행의 _type의 값은 전무하다.

    STEP 2. 패스와 아동 유형을 수락

    양식보기는 전형적인 형태의 데이터와 함께 CHILD_TYPE를 보낼 수 있고, 강력한 매개 변수 확인에 컨트롤러를 허용해야합니다.

    # app/views/polymorph/_form.html.erb
    <%= form_for(@polymorph) do |form| %>
      # Pass in the child_type - This one has been turned into a chicken!
      <%= form.hidden_field(:polymorph_type, value: 'Chicken' %>
      ...
      # Form values for Chicken
      <%= form.fields_for(:chicken) do |chicken_form| %>
        <%= chicken_form.text_field(:hunger_level) %>
        <%= chicken_form.text_field(:poop_level) %>
        ...etc...
      <% end %>
    <% end %>
    
    # app/controllers/polymorph_controllers.erb
    ...
    private
      def polymorph_params
        params.require(:polymorph).permit(:id, :polymorph_id, :polymorph_type)
      end
    

    물론,보기 (들) '유추'입니다 모델의 다른 유형을 처리해야하지만이 하나를 보여줍니다.

    이 사람을 도움이 밖으로 바랍니다. (왜 어쨌든 다형성 닭을해야합니까?)

  3. ==============================

    3.위의 대답은 훌륭하지만 같은 설정으로 작동하지 않습니다. 그것은 나에게 영감을하고 내가 작업 솔루션을 구축 할 수 있었다 :

    위의 대답은 훌륭하지만 같은 설정으로 작동하지 않습니다. 그것은 나에게 영감을하고 내가 작업 솔루션을 구축 할 수 있었다 :

    생성 및 업데이트 작동

    class Job <ActiveRecord::Base
      belongs_to :client, :polymorphic=>:true
      attr_accessible :client_attributes
      accepts_nested_attributes_for :client
    
      def attributes=(attributes = {})
        self.client_type = attributes[:client_type]
        super
      end
    
      def client_attributes=(attributes)
        some_client = self.client_type.constantize.find_or_initilize_by_id(self.client_id)
        some_client.attributes = attributes
        self.client = some_client
      end
    end
    
  4. ==============================

    4.그냥 나는 다음과 같은 해결 방법을 함께했다 있도록 레일 행동의이 종류를 지원하지 않는다는 것을 알아 냈 :

    그냥 나는 다음과 같은 해결 방법을 함께했다 있도록 레일 행동의이 종류를 지원하지 않는다는 것을 알아 냈 :

    class Job <ActiveRecord::Base
      belongs_to :client, :polymorphic=>:true, :autosave=>true
      accepts_nested_attributes_for :client
    
      def attributes=(attributes = {})
        self.client_type = attributes[:client_type]
        super
      end
    
      def client_attributes=(attributes)
        self.client = type.constantize.find_or_initialize_by_id(attributes.delete(:client_id)) if client_type.valid?
      end
    end
    

    이 같은 내 양식을 설정하는 저를 준다 :

    <%= f.select :client_type %>
    <%= f.fields_for :client do |client|%>
      <%= client.text_field :name %>
    <% end %>
    

    생각하지만 정확한 솔루션은 중요하다.

  5. from https://stackoverflow.com/questions/3969025/accepts-nested-attributes-for-with-belongs-to-polymorphic by cc-by-sa and MIT license