"NoMethodError" 试图在对象上使用 "build_association" 方法时在我的控制器中? Rails 4

"NoMethodError" in my controller when trying to use "build_association" method on object? Rails 4

所以我有三个 tables:位置、项目和成分,它们之间具有以下关系:

查看项目时(在 show.html.haml),我希望能够在页面上添加它包含的成分,同时使用 AJAX remote: true形式。但是,一旦我进入 IngredientsControllercreate 操作,我就无法执行此操作:

@ingredient = item.build_ingredient(:name => ingredient_params[:name], etc..)

要点是,控制器一直为 build_ingredientcreate_ingredientcreate 等抛出 NoMethodError。没有任何效果。但是 LocationItems 之间的关系工作得很好。

不过,对我来说奇怪的是,这有效:

@ingredient = Ingredient.new
@ingredient.build_item(hashes for an Item object here, etc..)

我对Rails还是有点陌生​​,我每天都在练习。通常我最终会通过 Google 在网上找到一个解决方案,但是这个让我特别难过,在阅读了关于关联的 Rails documentation 之后,我仍然没有遇到任何直接解决某种“3 -模型之间的分层"关联。

这就是我所拥有的:

成分控制器

class IngredientsController < ApplicationController
  def create

    # This works
    location = Location.find_by(:location_id => ingredient_params[:id])

    # This also works
    item = location.items.where(:item_id => ingredient_params[:menu_item_id])

    # This does not work
    @ingredient = item.build_ingredient(:name => ingredient_params[:name], :unit => ingredient_params[:unit], :value => ingredient_params[:value])

    respond_to do |format|
      format.js { render nothing: true }
    end
  end

  private def ingredient_params
    params.require(:ingredient).permit(:id, :menu_item_id, :name, :unit, :value)
  end
end

show.html.haml (项目)

.panel.panel-default
  = form_for @ingredient, remote: true do |f|
    .panel-heading
      New Ingredient
    .panel-body
      = f.hidden_field :id, :value => params[:id]
      = f.hidden_field :menu_item_id, :value => params[:menu_item_id]
      = f.select :name, options_from_collection_for_select(Supplylist.all, "id", "item"), { :prompt => "Select..." }, :class => "form-control ingredient-select"
      %br
      = f.text_field :value, :class => "form-control"
      %br
      = f.select :unit, options_from_collection_for_select(UnitType.all, "id", "name"), { :prompt => "Select..." }, :class => "form-control ingredient-select"
    .panel-footer
      = f.submit "Add", :class => "btn btn-success"

位置模型

class Location < ActiveRecord::Base
  has_many :items

  @url

  def getResponse
      response = RestClient.get(
        @url,
        {:content_type => :json, :'Api-Key' => '000000000000000000000'})

      return response
  end

  def setURL(url)
      @url = url
  end

  def getJSON
      return getResponse()
  end

  def getData(url)
      self.setURL(url)
      return JSON.parse(getJSON())
  end
end

物品型号

class Item < ActiveRecord::Base
  belongs_to :location
  has_many :ingredients
end

成分型号

class Ingredient < ActiveRecord::Base
  belongs_to :item
end

此外,请注意:

这两列都是在模型创建过程中使用 location:belongs_toitem:belongs_to 创建的。

首先item不包含单个项目。将您的项目查询更改为:

item = location.items.where(:item_id => ingredient_params[:menu_item_id]).first

那么你可以使用:

item.ingredients.build(:name => ingredient_params[:name], etc..)

build_<association_name> 仅对 belongs_to 或 has_one 关联有效。