如何添加 has_many :through 详细信息到表单 RoR

发布于 2024-12-12 06:03:53 字数 2942 浏览 0 评论 0原文

我正在做一个看似常见的 Ruby on Rails 学习应用程序,即菜谱应用程序。具体来说,以 has_many :through 关系的形式处理食谱和配料。通过查看一百万个示例和问题,我已经实现了多对多关系设置和多模型表单的工作,但我想添加一个额外的字段,但无法使其工作。感觉我已经接近了解这个东西是如何工作的了。以下是快速详细信息:

模型:

class Ingredient < ActiveRecord::Base
  has_many :recipe_ingredients
  has_many :recipes, :through => :recipe_ingredients
end

class RecipeIngredient < ActiveRecord::Base
  belongs_to :recipe
  belongs_to :ingredient
end

class Recipe < ActiveRecord::Base
  has_many :recipe_ingredients
  has_many :ingredients, :through => :recipe_ingredients
  accepts_nested_attributes_for :ingredients, :recipe_ingredients

  def new_recipe_ingredient_attributes=(recipe_ingredient_attributes)
    recipe_ingredient_attributes.each do |attributes|
      recipe_ingredients.build(attributes)
    end
  end

  def existing_recipe_ingredient_attributes=(recipe_ingredient_attributes)
    recipe_ingredients.reject(&:new_record?).each do |recipe_ingredient|
      attributes = recipe_ingredient_attributes[recipe_ingredient.id.to_s]
      if attributes
        recipe_ingredient.attributes = attributes
      else
        recipe_ingredient.delete(recipe_ingredient)
      end
    end
  end

  def save_recipe_ingredients
    recipe_ingredients.each do |recipe_ingredient|
      recipe_ingredient.save(false)
    end
  end
end

控制器:

def create
   @recipe = Recipe.new(params[:recipe])
   if @recipe.save
         redirect_to :action => 'show', :id => @recipe
         flash[:notice] = "Your record has been saved."
   else
         render :action => 'new'
   end
end

def update
   params[:recipe][:existing_recipe_ingredient_attributes] ||= {}
   @recipe = Recipe.find(params[:id])
   if @recipe.update_attributes(params[:recipe])
      redirect_to :action => 'show', :id => @recipe
      flash[:notice] = "Your changes have been saved."
   else
      render :action => 'edit'
   end
end  

视图:

<% form_for(@recipe) do |f| %>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
etc.....
    Ingredients:
    <div id="recipe_ingredients">
      <div class="recipe_ingredient">
      <% new_or_existing = recipe_ingredient.new_record? ? 'new' : 'existing' %>
      <% prefix = "recipe[#{new_or_existing}_recipe_ingredient_attributes][]" %>
      <% fields_for prefix, recipe_ingredient do |ri_form| %>
        <p>
          <%= ri_form.collection_select(:id, Ingredient.find(:all), :id, :name, :include_blank => true) %>
          <%= ri_form.text_field :amount %>
        </p>
      <% end %>
      </div>
    </div>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

抱歉,代码墙很长,希望它有意义。我不明白的是为什么“金额”文本字段不起作用。我已经尝试了一百万种不同的方法,但无法使其发挥作用。在这种情况下,我得到的错误是“# 的未定义方法`amount'”

我在这里缺少什么关键连接?谢谢。

I'm doing what appears to be a common learning app for Ruby on Rails, the recipe app. Specifically, working on recipes and ingredients as a has_many :through relationship. Through looking at a million examples and questions, I've got my many-to-many relationship setup and my multi-model form working, but I'd like to add an additional field and can't get it working. Feels like I'm close to understanding how this stuff works. Here are the quick details:

Models:

class Ingredient < ActiveRecord::Base
  has_many :recipe_ingredients
  has_many :recipes, :through => :recipe_ingredients
end

class RecipeIngredient < ActiveRecord::Base
  belongs_to :recipe
  belongs_to :ingredient
end

class Recipe < ActiveRecord::Base
  has_many :recipe_ingredients
  has_many :ingredients, :through => :recipe_ingredients
  accepts_nested_attributes_for :ingredients, :recipe_ingredients

  def new_recipe_ingredient_attributes=(recipe_ingredient_attributes)
    recipe_ingredient_attributes.each do |attributes|
      recipe_ingredients.build(attributes)
    end
  end

  def existing_recipe_ingredient_attributes=(recipe_ingredient_attributes)
    recipe_ingredients.reject(&:new_record?).each do |recipe_ingredient|
      attributes = recipe_ingredient_attributes[recipe_ingredient.id.to_s]
      if attributes
        recipe_ingredient.attributes = attributes
      else
        recipe_ingredient.delete(recipe_ingredient)
      end
    end
  end

  def save_recipe_ingredients
    recipe_ingredients.each do |recipe_ingredient|
      recipe_ingredient.save(false)
    end
  end
end

Controller:

def create
   @recipe = Recipe.new(params[:recipe])
   if @recipe.save
         redirect_to :action => 'show', :id => @recipe
         flash[:notice] = "Your record has been saved."
   else
         render :action => 'new'
   end
end

def update
   params[:recipe][:existing_recipe_ingredient_attributes] ||= {}
   @recipe = Recipe.find(params[:id])
   if @recipe.update_attributes(params[:recipe])
      redirect_to :action => 'show', :id => @recipe
      flash[:notice] = "Your changes have been saved."
   else
      render :action => 'edit'
   end
end  

View:

<% form_for(@recipe) do |f| %>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
etc.....
    Ingredients:
    <div id="recipe_ingredients">
      <div class="recipe_ingredient">
      <% new_or_existing = recipe_ingredient.new_record? ? 'new' : 'existing' %>
      <% prefix = "recipe[#{new_or_existing}_recipe_ingredient_attributes][]" %>
      <% fields_for prefix, recipe_ingredient do |ri_form| %>
        <p>
          <%= ri_form.collection_select(:id, Ingredient.find(:all), :id, :name, :include_blank => true) %>
          <%= ri_form.text_field :amount %>
        </p>
      <% end %>
      </div>
    </div>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

Sorry for the wall of code, hopefully it makes sense. The thing I can't understand is why the "amount" text field doesn't work. I've tried a million different ways, but can't get it working. In this case, the error I get is "undefined method `amount' for #"

What key connection am I missing here? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沉睡月亮 2024-12-19 06:03:53

乍一看,您应该简单地将:替换

      <% fields_for prefix, recipe_ingredient do |ri_form| %>

为:

      <%= fields_for prefix, recipe_ingredient do |ri_form| %>

At first glance it appears you should simply replace:

      <% fields_for prefix, recipe_ingredient do |ri_form| %>

with:

      <%= fields_for prefix, recipe_ingredient do |ri_form| %>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文