【问题标题】:Rails create form for model with many to many relationRails 为具有多对多关系的模型创建表单
【发布时间】:2013-03-04 07:12:14
【问题描述】:

我有两个模型,RecipeTag,具有 has_and_belongs_to_many 关系。对于这种关系,我有一个简单的连接表,RecipesTags

食谱:

has_and_belongs_to_many :tags

标签:

has_and_belongs_to_many :recipes

现在,在创建新食谱后,用户可以以复选框的形式填写食谱所属的类别,例如“肉类”、“鱼”等。这些类别实际上只是数据库中的标签。

问题:食谱没有保存任何标签。

配方 newcreate 控制器方法:

    def new
    @recipe = Recipe.new
    @ingredients = Ingredient.all
    @tags = Tag.all

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @recipe }
    end
  end



  # POST /recipes
  # POST /recipes.json
  def create
    @recipe = Recipe.new(params[:recipe])
    if (params[:tags])
      @recipe.tags << params[:tags]
    end

    respond_to do |format|
      if @recipe.save
        format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
        format.json { render json: @recipe, status: :created, location: @recipe }
      else
        format.html { render action: "new" }
        format.json { render json: @recipe.errors, status: :unprocessable_entity }
      end
    end
  end

观点:

<%= form_for(@recipe, :html => {:multipart => true}) do |f| %>
  <% if @recipe.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>

# [ fields that get's saved for the recipe and works fine ]

<% @tags.each do |t| %>
      <%= f.label t.name  %>
      <%= f.check_box :tags, t.name  %>
      <br />
    <% end %>

<%= f.submit 'Submit recipe', :class => 'btn btn-primary' %>

<% end %>

目前,我收到一条错误消息: “Meat”的未定义方法“合并”:字符串

“肉类”是标签名称。

那么,我在这里做错了什么?

【问题讨论】:

  • 您的表单工作正常吗?当您收到此错误时?
  • 我在下面发布了一个答案,但为了将来参考,提供更多错误消息通常会有所帮助,例如引发的异常(通常是粗体标题的第一部分)页面,即NoMethodError),以及引发异常的位置(在您的情况下,这可能类似于app/controllers/recipes_controller.rb:21:in 'create'),它准确地告诉您哪个文件中的哪一行导致了异常。这非常有帮助,因为它为我们提供了一个起点来找出代码的哪一部分有问题。

标签: ruby-on-rails join model many-to-many


【解决方案1】:

我认为问题在于@recipe.tags &lt;&lt; params[:tags] 这一行。 您使用&lt;&lt; 调用的关联方法需要一个对象(在这种情况下需要一个标签对象),但在这种情况下,您可能会传递一个字符串。

有关更多信息,此链接http://guides.rubyonrails.org/association_basics.html#has_and_belongs_to_many-association-reference 可能会有所帮助,尤其是在它引用collection&lt;&lt;(object, …) 的地方。


在您的控制器中,您需要执行 @recipe.tags &lt;&lt; tag 之类的操作,其中 tag 是特定的标记对象。

那么,试试这个:

在你的控制器中

params[:tags].each do |k,v|
   @recipe.tags << Tag.find(k)
end

在你看来

<% @tags.each do |t| %>
  <%= f.label t.name  %>
  <%= f.check_box "tags[#{t.id}]"  %>
  <br />
<% end %>

【讨论】:

  • 验证错误后重定向回显示后检查保存如何?
【解决方案2】:

试试这个:

  def create
    @recipe = Recipe.new(params[:recipe])
    params[:tags].each do |tag|
      @recipe.tags << Tag.find_by_name(tag)
    end

    respond_to do |format|
      if @recipe.save
        format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
        format.json { render json: @recipe, status: :created, location: @recipe }
      else
        format.html { render action: "new" }
        format.json { render json: @recipe.errors, status: :unprocessable_entity }
      end
    end
  end

在视图中:

<% @tags.each do |t| %>
  <%= label_tag t.name  %>
  <%= check_box_tag "tags[#{t.name}]", t.name  %>
  <br />
<% end %>

【讨论】:

    猜你喜欢
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 2021-01-18
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多