1

Rails ポリモーフィック アソシエーションとネストされたフォームを使用して、in_prices と out_prices (国ごとに 1 つ) を保持する記事を作成しようとしています。

次のようなデータモデルがあります。

# app/models/article.rb
class Article < ActiveRecord::Base
    has_many :out_prices, :class_name => "Price", :as => :priceable
    has_many :in_prices, :class_name => "Price", :as => :priceable
end

# app/models/price.rb
class Price < ActiveRecord::Base
    belongs_to :priceable, :polymorphic => true
end

# db.schema for prices
create_table "prices", :force => true do |t|
    t.integer  "value"
    t.integer  "country_id"
    t.integer  "priceable_id"
    t.string   "priceable_type"
end

記事とその関連付けは、次のようなネストされたフォームを使用して作成されます。

# app/views/articles/_article_form.html.erb
<%= form_for setup_article(@article) do |f| %>
    <%= f.fields_for :in_prices do |ff| %>
        <%= ff.text_field :value %>
    <% end %>
    <%= f.fields_for :out_prices do |ff| %>
        <%= ff.text_field :value %>
    <% end %>
<% end %>

setup_article メソッドは、関連付けを構築するためのヘルパー メソッドです。

# app/helpers/articles_helper.rb
def setup_article(article)
    if article.in_prices.nil?
        # Setup one in price for each country
        Country.all.each do |country|
            article.in_prices.build(:value => 0, :country_id => country.id)
        end
    end
    if article.out_prices.nil?
        # Setup one out price for each country
        Country.all.each do |country|
            article.out_prices.build(:value => 0, :country_id => country.id)
        end
    end
    article
end

setup_article は、新しい記事を作成するときに空の価格フォーム フィールド (国ごとに 1 つ) が表示されるようにするために必要です。

では実際の問題に移ります。作成済みの記事 (in_prices と out_prices が関連付けられている) を編集すると、Rails はこれらのさまざまな種類のポリモーフィックな関連付け (in_prices と out_prices) を区別できなくなります。このため、両方のネストされたフォーム ヘルパーは、関連するすべての価格のフォーム フィールドをレンダリングしますが、これは望ましい動作ではありません。ネストされたフォームの 1 つに in_prices をリストし、もう 1 つに out_prices をリストしたいだけです。

Rails が 2 つの異なるネストされたフォーム ヘルパーで in_prices と out_prices の関連付けを区別できるようにするには、これらの関連付けをどのように構成する必要がありますか?

編集解決済み

私の友人は、価格表にさらに別のフィールドを追加して、価格のタイプを示す必要があると指摘しました。このフィールドを price_type と呼び、db.schema は次のようになりました。

# db.schema for prices
create_table "prices", :force => true do |t|
    t.integer  "value"
    t.integer  "price_type"
    t.integer  "country_id"
    t.integer  "priceable_id"
    t.string   "priceable_type"
end

注: これは予約済みの名前であるため、このフィールドに「type」という名前を付けないでください。

「price_type」フィールドは、ネストされたフォームに非表示フィールドを追加する (安全性が低い) か、記事とその関連データを保存する前にコントローラーで処理することによって入力できます。次のような非表示のパラメーターとして追加することにしました。

# app/views/articles/_article_form.html.erb
<%= form_for setup_article(@article) do |f| %>
    <%= f.fields_for :in_prices do |ff| %>
        <%= ff.text_field :value %>
        <%= ff.text_field :price_type, :value => "in" %>
    <% end %>
    <%= f.fields_for :out_prices do |ff| %>
        <%= ff.text_field :value %>
        <%= ff.text_field :price_type, :value => "out" %>
    <% end %>
<% end %>

アソシエーションが正しくフィルタリングされるようにするには、次のように「:conditions」タグで宣言する必要があります。

# app/models/article.rb
class Article < ActiveRecord::Base
    has_many :out_prices, :class_name => "Price", :as => :priceable, :conditions => { :price_type => "in" } 
    has_many :in_prices, :class_name => "Price", :as => :priceable, :conditions => { :price_type => "out" }
end

..そして今、すべてが期待どおりに機能します。乾杯!

4

0 に答える 0