关于ruby:无法正确渲染集合中的部分模板

Rails partial template with collection not rendering correctly

我已经对这个错误进行了数小时的故障排除,而且我不知道自己在做什么错。我只是无法让项目集合正确显示给单个用户。每个项目属于一个用户,每个用户有多个项目。目前,我的局部视图尚未呈现在用户的显示视图上。

如果我更改<%= render partial:"/users/item", collection: @user.items %>
<%= render partial:"/users/item", collection: @items %>,则呈现部分模板,但是无论它们属于哪个用户,都将显示所有项目。在检查数据库之后,每个项目条目都使用外键user_id进行了正确存储,因此不存在问题。

如何为每个用户显示正确的项目?我之前已经使用了partials几次,并且可以交叉引用旧代码和新代码。我看不到有什么区别,我迷失了方向。我已经搜索了一般的Internet,堆栈溢出,并查看了《 Rails布局和渲染指南》。我已经在下面发布了相关代码,并乐意发布其他任何内容。请帮忙!

views / users / _item.html.erb

1
2
  <h4>ITEM: <%= item.title %></h4>
  <p class="item"><%= item.cost %></p>

views / users / show.html.erb

1
2
3
4
5
6
7
8
9
Users#show
<p>Find me in app/views/users/show.html.erb</p>

<%= @user.first_name %>

My List
<%= render partial:"/users/item", collection: @user.items %>

<span>ADD ITEM<%= link_to image_tag("Plus-50.png"), new_user_item_path(@user), class:"items-nved" %> </span>

controllers / users_controller.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class UsersController < ApplicationController

  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def index
    @users = User.all
    render :index
  end

  def show
    @user = User.find(params[:id])
    # @item = Item.find(params[:id])
    @items = Item.all
    @item = Item.new
    @item.user_id = @user.id
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to new_session_path, method: :get
    else
      render"new"
   end
  end

  def edit
  end

  def update
  end

  def destroy
  end

  private
  def set_user
   @user = User.find(params[:id])
  end

  def user_params
    params.require(:user).permit(:first_name, :last_name, :birthday, :city, :state, :email, :password, :password_confirmation)
  end
end

controllers / items_controller.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class ItemsController < ApplicationController

  include ItemsHelper

  before_filter :require_login, only: [:new, :create, :update, :destroy]

  def index
    @current_user = current_user
    @items = Item.all
  end

  def show
    @user = current_user
    @item = Item.find(params[:id])
  end

  def new
    @user = current_user
    @item = Item.new
  end

  def create
    @user = current_user
    @item = Item.new(item_params)
    @item.user_id = params[:user_id] # set user_id param from database to current_user id
    @item.save

    redirect_to user_item_path(@user, @item)
  end

  def edit
    @user = current_user
    @item = Item.find(params[:id])
  end

  def update
   @user = current_user
   @item = Item.find(params[:id])
   @item.update(item_params)
   redirect_to user_path(@user)
  end

  def destroy
    @user = User.find params[:user_id]
    @item = Item.find(params[:id])
    @item.destroy
    redirect_to user_path(@user)
  end
end

private
  def user_params
    params.require(:user).permit(:first_name, :last_name, :birthday, :city, :state, :email, :password, :password_confirmation)
  end

  def require_login
    unless logged_in?
      flash[:error] ="You must be logged in to access this section"
      redirect_to new_login_url # halts request cycle
    end
  end


通过在命令行上运行gem install byebug或通过将Byebug放入Gemfile中(然后运行bundle install)来安装byebug gem。

在用户控制器中@user声明之后放置byebug,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
class UsersController < ApplicationController

  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def index
    @users = User.all
    render :index
  end

  def show
    @user = User.find(params[:id])
    byebug

然后启动本地服务器,并在浏览器中进入用户show视图。该页面将无法呈现,因为当它命中byebug时,服务器会暂停。

发生这种情况时,请返回到您的终端并查看您的服务器日志。它将等待您的命令。键入@user,然后按Enter。它返回什么?

也尝试@user.inspect。它返回User对象吗?

然后执行@user.items。那会返回什么?如果@user.items返回预期的项目集合,则您将其传递给视图的方式或在视图中对其进行的操作都存在问题。

如果@user.items没有返回项目集合,则这就是为什么它不在您的视图中显示的原因!在这种情况下,可能与您的ActiveRecord关联和/或您的迁移有关。

另一种可能性是,数据库中的当前项可能是在建立关联设置之前创建的,因此它们将没有user_id。您可以在Rails控制台中进行检查。确保数据库中的项目具有与current_user相同的user_id。

在rails控制台中要做的另一件事是将一个您认为有一些Item的用户分配给一个变量,例如user = User.first,然后执行user.items。那行得通吗?

我还建议至少在模型级别编写一些RSpec测试,以测试是否存在正确的关联。 Shouldaruby对此非常有用。

在这里评论您的发现。


您期望模板渲染比它更聪明-它正在渲染所有项目,因为这就是@items中的内容-它不知道您只想要给定用户的项目。原始代码没什么问题

1
render partial:"/users/item", collection: @user.item


尝试像这样渲染它:

1
<%= render partial:"/users/item", locals: {user_items: @user.items} %>

并将其循环到_partial文件中:

1
2
3
<% user_items.each do |item| %>
...
<% end %>