0

这个错误困扰了我好几个星期。当我尝试Item从指定的Userand构建 an 时ListItem会创建 ,但Wish不会创建关联。

如果我尝试这样做@item.lists.first.name,则会返回错误:

undefined method 'name' for nil:NilClass

我对 Rails 很陌生,所以我确定有些东西我错过或误解了。非常感谢任何帮助!

我有四个模型:

class User < ActiveRecord::Base
  has_many :lists, dependent: :destroy
  has_many :wishes, through: :lists
  has_many :items, through: :wishes

class List < ActiveRecord::Base
  belongs_to :user
  has_many :wishes, dependent: :destroy
  has_many :items, through: :wishes

class Wish < ActiveRecord::Base
  belongs_to :list
  belongs_to :item

class Item < ActiveRecord::Base
  has_many :wishes
  has_many :lists, through: :wishes

我想Itemlists_controller.rb显示操作创建一个新的:

class ListsController < ApplicationController
  def show
    @user = User.find(params[:user_id])
    @list = @user.lists.find(params[:id])
    @item = @list.items.build if current_user?(@user)
    @items = @list.items
  end

class ItemsController < ApplicationController
    def create
        @list = current_user.lists.find(params[:list_id])
        @item = @list.items.build(params[:item])
    if @item.save
      flash[:success] = "Item created!"
      redirect_to @item
    else
      render 'new'
    end
end

我的路由文件如下所示:

Wishlist::Application.routes.draw do
  resources :users do
    resources :lists, only: [:show, :create, :destroy]
  end
  resources :items, only: [:show, :new, :create, :destroy]

表格lists/show.html.erb

   <div class="modal-body">
     <%= form_for(@item, html: { multipart: true }) do |f| %>
  <div class="field">
        <%= render 'items/fields', f: f %>
         <%= hidden_field_tag :list_id, @list.id %>
  </div>
   </div>

items/fields

<%= render 'shared/error_messages', object: f.object %>

<%= f.label :image %>
<%= f.file_field :image %>

<%= f.label :remote_image_url, "or image URL" %>
<%= f.text_field :remote_image_url %>

<%= f.label :title %>
<%= f.text_field :title %>

<%= f.label :link %>
<%= f.text_field :link %>

更新

从日志:

Processing by ItemsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"pcDVdaDzZz4M17Kwjx8mKw6tTF9MjUvx1woTzaKRWJY=", "item"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007fecdd1fd890 @original_filename="profile.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"item[image]\"; filename=\"profile.jpg\"\r\nContent-Type: image/jpeg\r\n", @tempfile=#<File:/var/folders/6y/j8zfcgmd02x5s439c0np8fjh0000gn/T/RackMultipart20130216-8413-3vzjuj>>, "remote_image_url"=>"", "title"=>"YES", "link"=>"SDFs"}, "list_id"=>"1", "commit"=>"Add"}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."remember_token" = '5AXS8-7-YRyLyGDKYHIZRg' LIMIT 1
  List Load (0.2ms)  SELECT "lists".* FROM "lists" WHERE "lists"."user_id" = 1 AND "lists"."id" = ? LIMIT 1  [["id", "1"]]
   (0.1ms)  begin transaction
  SQL (0.7ms)  INSERT INTO "items" ("created_at", "image", "link", "title", "updated_at") VALUES (?, ?, ?, ?, ?)  [["created_at", Sat, 16 Feb 2013 20:57:10 UTC +00:00], ["image", "profile.jpg"], ["link", "SDFs"], ["title", "YES"], ["updated_at", Sat, 16 Feb 2013 20:57:10 UTC +00:00]]
   (2.7ms)  commit transaction
Redirected to http://localhost:3000/items/1
Completed 302 Found in 830ms (ActiveRecord: 4.0ms)
4

3 回答 3

0

让我首先尝试总结一下:您有用户,他们有列表,其中包含与一个特定项目相关的愿望。

那么我们先来看下面这行代码:

@item.lists.first.name

所以发生的事情是,rails 获取该项目,遍历包含该项目的所有列表的愿望,获取第一个列表并查找列表名称。当项目通过愿望与任何列表无关时,您看到的问题就会发生(例如,因为您的项目的创建方法没有将新项目连接到愿望,因此也缺少与列表的连接):所以该项目没有关系到一个列表,结果@item.lists是一个空列表。好吧,first空列表的元素什么都不是(nil),当然nil也没有名字。

结果是,你所看到的:

undefined method 'name' for nil:NilClass

解决此问题的一种方法是try()仅在可用时使用 which 执行相关方法:

@item.lists.first.try(:name)

您所说的另一个问题是,当您从用户构建项目时,不会产生任何愿望。我认为你必须明确地建立愿望。我不是 100% 确定,但我认为,:through在模型中声明 -relations 仅用于查询,而不用于生成/构建。

在您的项目控制器中尝试以下操作(想法是首先明确构建愿望,然后为愿望构建项目):

@wish = @list.wishes.build()
@wish.save
@item = @wish.item.build(params[:item])
于 2013-02-16T22:18:50.027 回答
0

buildhas_many :through. _ 您需要将关联更改为itemsonList以包含inverse_of.

class List < ActiveRecord::Base
  belongs_to :user
  has_many :wishes, dependent: :destroy
  has_many :items, through: :wishes, inverse_of: :wishes
end

然后它应该为您正确构建连接Wish对象。

有关更多信息,请参阅此相关问题:https ://github.com/rails/rails/pull/7661#issuecomment-8614206

于 2013-02-17T04:21:06.687 回答
0

经过大量的谷歌搜索和反复试验,我发现我必须明确地构建 Wish。创建操作最终看起来像这样:

def create
    @list = current_user.lists.find(params[:list_id])
    @item = Item.create!(params[:item])
    @item.wishes.build(list_id: @list.id)
    if @item.save
      flash[:success] = "Item created!"
      redirect_to @item
    else
      render 'new'
    end
end
于 2013-02-22T10:30:00.493 回答