0

関連するレコードを同じフォームで作成しようとしていますが、関連するレコードがfind_or_create_byを使用するようにしたいと思います。時間はすでに存在するでしょう)。私は最後の2日間、この記事に関連するすべての記事と記事を掘り下げてこれを動作させようとしましたが、私のフォームは既存のものを検索するのではなく、新しいオブジェクトのみを作成しようとしています。Rails 5 - find_or_create_byネストされた属性を持つ

モデル

#order.rb 
has_many :order_owners, dependent: :destroy, inverse_of: :order 
has_many :owners, through: :order_owners 

accepts_nested_attributes_for :order_owners 

#owner.rb 
has_many :order_owners, dependent: :destroy 
has_many :orders, through: :order_owners 
validates :name, presence: true, uniqueness: { case_sensitive: false } 

#order_owner.rb 
belongs_to :owner 
belongs_to :order 

accepts_nested_attributes_for :owner 

orders/new.html.erb

<%= bootstrap_form_for(@orders, layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-6") do |f| %> 
    <%= render 'shared/error_messages', object: f.object %> 

    ... 

    <%= f.fields_for :order_owners do |orderowner| %> 

    <%= render 'orders/new_order_owners', f: orderowner, render_partial: 'orders/new_order_owners' %> 

    <% end %> 

    ... 

    <%= f.form_group do %> 
    <%= f.submit "Create Order", class: "btn btn-primary" %> 
    <%= link_to_add_association fa_icon("plus", text: "Add Owner"), f, :order_owners, 
            class: "btn btn-outline pull-right #{orderBtnDisable(@properties)}", partial: "orders/new_order_owners", id: "newOrderOwnerAdd" %> 
    <% end %> 
<% end %> 

orders/new_order_owners部分フォーム

<div class="m-t-md m-b-md border-bottom form-horizontal nested-fields"> 

    <%= link_to_remove_association(fa_icon("remove", text: ""), f, { class: "btn btn-danger btn-outline pull-right" }) %> 

    <% f.object.build_owner unless f.object.owner %> 

    <%= f.fields_for :owner do |owner| %> 
    <%= owner.select :name, options_from_collection_for_select(@owners, "name", "name"), 
       { label: "Name:", include_blank: true }, { id: "orderPropOwnerSelect", data: { placeholder: "Select an existing Owner or type a new one.."} } %> 
    <% end %> 

</div> 

コントローラ

orders/new

def new 
    @order = Order.new 
    @order.build_property 
    @order.order_owners.build.build_owner 
    @properties = Property.find_by_id(params[:property_id]) 
    if @properties 
    @owners = @properties.owners 
    else 
    @owners = [] 
    end 
    respond_to do |format| 
    format.html 
    format.js 
    end 
end 

orders/create

def create 
    @properties = Property.find(params[:order][:property_id]) 
    @order = @properties.orders.create(order_params) 
    respond_to do |format| 
    format.html { if @order.save 
        if params[:order][:owners_attributes] 
         order_prop_owner_check(@order, @properties) 
        end 
        flash[:success] = "Order created successfully!" 
        redirect_to property_order_path(@properties, @order) 
        else 
        @properties 
        @owner = @properties.owner 
        render 'new' 
        end 
    } 
    format.js { 
        if @order.save 
        flash.now[:success] = "Order Updated Successfully!" 
        else 
        flash.now[:danger] = @order.errors.full_messages.join(", ") 
        end 
    } 
    end 
end 

newアクションで見ることができるように、私は新しいOrderをインスタンス化し、関連するプロパティ(Orderが属するもの)を構築し、新しいorder_owner関係を構築し、その関係のオーナーを構築します。その後、submitを実行すると、@ properties.orders.create(order_params)を介してオーダーが作成されます。

エラーは「オーダー所有者の名前が既に存在します」です。それは明らかにその名前で所有者を見ていない。 私が試してみました:

  • は両方belongs_toのとhas_manyのバリエーションを使用して、order.rbとorder_owner.rbでautosave_associated_records_for_ownerの再定義、しかし、彼らは私が何か間違ったことしなければならないと呼ばれることはありません飽きないように思えます。 (私はSO上で見つけることができるほとんどすべての回答のバリエーションを試しました)
  • before_add: callback on has_many :owners, through: :order_ownershas_many :order_owners order.rb。
  • order.rbでhas_many :ownershas_many :owners, through: :order_ownersを拡張するだけでなく、order_order.rbでbelongs_to :owner

また、私はちょうど何かを誤解されなければならないので、フォーム内の団体や、そのようなを呼び出すのさまざまなバリエーションを試してみました。また、ネストされたフォームを管理するためにCocoonも使用していますが、関連のない問題については著者に話しました。コクーンは本質的にネストされたフォームのビューヘルパーなので、ソリューションはモデル/コントローラ内の何かでなければなりません。

すべてのアイデアを歓迎します。前もって感謝します。

p.s.私はこの正確なポストに関係しているかもしれないコントローラのアクションにコードを残しましたが、完全性のためにアクション全体を表示したかったのです。重要な場合は、別のフィールドでプロパティが選択されたときにAJAX経由でオーナーを手動で設定します。基本的には、プロパティを検索し、既存の所有者を所有者に追加します。

+0

確認するには、JoinOwnerテーブルが結合テーブルであることを確認しますか?つまり、実際にはIDの所有者とIDの所有者だけがありますか?さらに、ルートを追加できますか? – inveterateliterate

+0

また、私がここで密集している場合は申し訳ありませんが、どの時点で正確に '.find_or_create_by'を呼び出していますか? – inveterateliterate

+0

ちょっと、応答の遅れのために謝罪、一日中旅行を費やした。はい 'OrderOwner'は' order_id'と 'owner_id'だけを持つ結合テーブル/モデルです。現在、私は 'find_or_create_by'を呼び出せません。なぜなら、私はそれを動作させることができないからです。理想的には、オーダーのネストされた属性を使用してオーナーが作成されたときに呼び出すことができます。私が見つけたものすべてから、OrderOwnerテーブルの 'autosave_associated_records_for_owner'(私はそう思う)が私のチケットでなければならないと思うが、それを動作させることはできない。投稿するルートはどれですか?注文? –

答えて

1

オーナーは注文内にネストされています。したがって、order.saveを呼び出すと、すべての検証(所有者を含む)が実行されます。 find_or_create_byを使用する場合は、before_saveの内部で行う必要があるため、検証がヒットする前にオーナーに変更を加えることができます。

#order.rb 

before_save :find_or_create_owner 

def find_or_create_owner 
    self.order_owners.each do |order_owner| 
    order_owner.owner = Owner.find_or_create_by(name: final_owner.name) 
    end 
end 

フォームやビジネスロジックによっては、さらにカスタマイズする必要がありますが、これが主な概念です。

関連する問題