【问题标题】:"NoMethodError" in my controller when trying to use "build_association" method on object? Rails 4尝试在对象上使用“build_association”方法时,控制器中的“NoMethodError”?导轨 4
【发布时间】:2015-04-03 22:06:47
【问题描述】:

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

  • 一个Location 有很多Items
  • 一个Item属于一个Location,并且有很多Ingredients
  • Ingredient 属于 Item

查看项目时(在 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 还是很陌生,我每天都在练习。通常我最终会通过谷歌在网上找到一个解决方案,但是这个让我特别难过,在阅读了关于关联的Rails documentation 之后,我仍然没有遇到任何直接解决模型之间“三层”关联的东西.

这就是我所拥有的:

配料控制器

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

另外,请注意:

  • 我的数据库中的items 表确实有一个location_id 外键列。
  • 我数据库中的ingredients 表有一个item_id 外键列。

这两列都是在模型创建期间使用location:belongs_toitem:belongs_to 创建的。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 activerecord associations


    【解决方案1】:

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

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

    那么你可以使用:

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

    build_&lt;association_name&gt; 仅对belongs_to 或has_one 关联有效。

    【讨论】:

    • 刚刚尝试过,但它返回以下错误:NoMethodError in IngredientsController#create undefined method ingredients' for #<:activerecord_associationrelation:0x007fb07c229118>`。
    • 您确定 Item 模型定义了 has_many :ingredients 关联吗?
    • 我非常肯定它确实如此。如果您想查看迁移文件,我可以发布它们。
    • 是的,我有上面列出的项目模型。
    • 问题在于item 不是Item 模型的实例。你有一个#&lt;Item::ActiveRecord_AssociationRelation:0x007fb07c229118&gt;,它告诉我它是一个项目集合而不是单个项目。我也更新了我的答案以及如何解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多