1

私は次のモデルを持っています:

class MealPlan < ActiveRecord::Base
  has_many :food_contents
  has_many :foods,:through => :food_contents
  accepts_nested_attributes_for :food_contents
  attr_accessible :food_contents_attributes,:name
end

class Food < ActiveRecord::Base
  validates_presence_of :name,:protein,:carbs,:fats,:calories
  validates_numericality_of :protein,:carbs,:fats,:calories
end

class FoodContent < ActiveRecord::Base
  belongs_to :meal_plan
  belongs_to :food

  attr_accessible :food_id, :how_much,:meal_plan_id
  validates_presence_of :food,:meal_plan
end

食事プランコントローラーに次のコードがあります。

  def new
    @meal_plan = MealPlan.new
    3.times { @meal_plan.food_contents.build }
  end


def create
  @meal_plan = MealPlan.new(params[:meal_plan])
end

および食事プランの次のフォーム:

<%= form_for(@meal_plan) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <%= f.fields_for :food_contents do |b| %>
    <fieldset>
      <legend>New food</legend>
      <%= b.collection_select :food_id,Food.all,:id,:name,{},{:class => "food_id_selector"} %><br/>
      <%= b.text_field :how_much,:class => "how_much_input" %><br/>
      <%= content_tag(:p,nil,:class => "food_acumulator") %>
    </fieldset>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

ただし、モデルの保存に常に失敗すると、次のエラーが発生します。

> #<ActiveModel::Errors:0xb34212e8
 @base=#<MealPlan id: nil, name: "Sample", created_at: nil, updated_at: nil>,
 @messages={:"food_contents.meal_plan"=>["can't be blank"]}>

私がデバッグしたものから、犯人はvalidates_presence_of :meal_plan次のとおりです。

class FoodContent < ActiveRecord::Base
  ...
  ...
  validates_presence_of :food,:meal_plan
end

一方では、ネストされたモデルを保存できない理由を理解できますが (食事プランにはまだ ID がないため)、もう一方の側では、自分が行っていることが正しいことを確認したいと考えています。

4

2 に答える 2

3

少しいじってみたところ、meal_plan の検証をスキップして 3 つのモデルを保存できる方法を見つけました。

mp = MealPlan.new
fc = mp.food_contents.build
f = fc.build_food
f.save
mp.save(validate: false)
fc.save

fc が保存されたときに再度検証されるため、これは問題にならないはずです。これは次の方法で確認できます。

mp = MealPlan.new
fc = mp.food_contents.build
f = fc.build_food
f.save
mp.save(validate: false)
fc.food = nil
fc.save
于 2012-07-29T20:54:25.390 に答える
0

これはすでに回答されていることは知っていますが、検証なしで保存せずにこれを行うより簡単な方法は、単純に id = 1 を設定することです。この方法では、id の検証に合格し、レコードがデータベースに書き込まれると、id正しいもので上書きされます。

したがって、次のようなことが簡単にできます。

@mp = MealPlan.new(your_strong_param_access_function) # all ur nested stuff should then be automatically pulled into mp including your associations.
@mp.food_contents.each do |fc|
  fc.meal_plan_id = 1
end
@mp.save

それでおしまい。food_plan_id が 1 に設定されているため、検証は失敗しません。また、アクティブなレコードがすべてを保存すると、meal_plan_id が正しい値に更新されます。そして、他のすべての検証はまだアクティブに機能しています:)

于 2013-08-15T23:31:03.140 に答える