Rails 包含集合的部分模板未正确呈现
Rails partial template with collection not rendering correctly
我已经解决这个错误几个小时了,但我不知道我做错了什么。我根本无法让项目集合为单个用户正确显示。每个项目属于一个用户,每个用户有很多项目。现在,我的部分未在用户显示视图上呈现。
如果我改变<%= render partial: "/users/item", collection: @user.items %>
到 <%= render partial: "/users/item", collection: @items %>
然后呈现部分模板,但显示所有项目,无论它们属于哪个用户。检查数据库后,每个项目条目都使用外键 user_id 正确存储,所以这不是问题。
我如何为每个用户显示正确的项目?我以前使用过几次局部,并且交叉引用了新旧代码。我看不出有什么区别,我正在失去理智。我搜索了一般互联网、Stack Overflow,并查看了 Rails Guides for Layouts and Rendering。我已经 post 编辑了下面的相关代码,并且很乐意 post 任何其他内容。请帮忙!
views/users/_item.html.erb
<div>
<h4>ITEM: <%= item.title %></h4>
<p class="item"><%= item.cost %></p>
</div>
views/users/show.html.erb
<h1>Users#show</h1>
<p>Find me in app/views/users/show.html.erb</p>
<div><%= @user.first_name %></div>
<h3>My List</h3>
<%= 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
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
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
尝试这样渲染:
<%= render partial: "/users/item", locals: {user_items: @user.items} %>
并在 _partial 文件中循环:
<% user_items.each do |item| %>
...
<% end %>
您期望模板呈现比它更智能 - 它正在呈现所有项目,因为那是 @items
中的内容 - 它不知道您只需要给定用户的项目。原代码没有错
render partial: "/users/item", collection: @user.item
安装 byebug gem,通过在命令行上 运行ning gem install byebug
或将 byebug 放入 Gemfile(然后 运行 bundle install
).
将 byebug
放在 UsersController 中的 @user 声明之后,如下所示:
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
然后启动本地服务器并在浏览器中转到用户显示视图。页面不会呈现,因为当它到达 byebug
时服务器暂停。
发生这种情况时,请返回您的终端并查看您的服务器日志。它将等待您的命令。输入 @user
并按 Enter。它是什么 return?
也试试 @user.inspect
。它 return 是一个用户对象吗?
然后@user.items
。 return 是什么意思?如果 @user.items
return 是预期的项目集合,那么您将其传递给视图的方式或您在视图中对其进行的操作存在问题。
如果 @user.items
不是 return 项目集合,那么这就是它没有显示在您的视图中的原因!在这种情况下,它可能与您的 ActiveRecord 关联有关 and/or 您的迁移。
另一种可能性是您数据库中的当前项目可能是在您设置关联之前创建的,因此它们不会有 user_id。您可以在 rails 控制台中查看。确保您的数据库中的项目与您的 current_user.
具有相同的 user_id
在您的 rails 控制台中做的另一件好事是将您认为有一些项目的用户分配给一个变量,例如 user = User.first
,然后执行 user.items
.这行得通吗?
我还建议编写一些 RSpec 测试,至少在模型级别测试是否存在正确的关联。 shoulda gem 非常适合这个。
在这里评论你的发现。
我已经解决这个错误几个小时了,但我不知道我做错了什么。我根本无法让项目集合为单个用户正确显示。每个项目属于一个用户,每个用户有很多项目。现在,我的部分未在用户显示视图上呈现。
如果我改变<%= render partial: "/users/item", collection: @user.items %>
到 <%= render partial: "/users/item", collection: @items %>
然后呈现部分模板,但显示所有项目,无论它们属于哪个用户。检查数据库后,每个项目条目都使用外键 user_id 正确存储,所以这不是问题。
我如何为每个用户显示正确的项目?我以前使用过几次局部,并且交叉引用了新旧代码。我看不出有什么区别,我正在失去理智。我搜索了一般互联网、Stack Overflow,并查看了 Rails Guides for Layouts and Rendering。我已经 post 编辑了下面的相关代码,并且很乐意 post 任何其他内容。请帮忙!
views/users/_item.html.erb
<div>
<h4>ITEM: <%= item.title %></h4>
<p class="item"><%= item.cost %></p>
</div>
views/users/show.html.erb
<h1>Users#show</h1>
<p>Find me in app/views/users/show.html.erb</p>
<div><%= @user.first_name %></div>
<h3>My List</h3>
<%= 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
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
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
尝试这样渲染:
<%= render partial: "/users/item", locals: {user_items: @user.items} %>
并在 _partial 文件中循环:
<% user_items.each do |item| %>
...
<% end %>
您期望模板呈现比它更智能 - 它正在呈现所有项目,因为那是 @items
中的内容 - 它不知道您只需要给定用户的项目。原代码没有错
render partial: "/users/item", collection: @user.item
安装 byebug gem,通过在命令行上 运行ning gem install byebug
或将 byebug 放入 Gemfile(然后 运行 bundle install
).
将 byebug
放在 UsersController 中的 @user 声明之后,如下所示:
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
然后启动本地服务器并在浏览器中转到用户显示视图。页面不会呈现,因为当它到达 byebug
时服务器暂停。
发生这种情况时,请返回您的终端并查看您的服务器日志。它将等待您的命令。输入 @user
并按 Enter。它是什么 return?
也试试 @user.inspect
。它 return 是一个用户对象吗?
然后@user.items
。 return 是什么意思?如果 @user.items
return 是预期的项目集合,那么您将其传递给视图的方式或您在视图中对其进行的操作存在问题。
如果 @user.items
不是 return 项目集合,那么这就是它没有显示在您的视图中的原因!在这种情况下,它可能与您的 ActiveRecord 关联有关 and/or 您的迁移。
另一种可能性是您数据库中的当前项目可能是在您设置关联之前创建的,因此它们不会有 user_id。您可以在 rails 控制台中查看。确保您的数据库中的项目与您的 current_user.
具有相同的 user_id在您的 rails 控制台中做的另一件好事是将您认为有一些项目的用户分配给一个变量,例如 user = User.first
,然后执行 user.items
.这行得通吗?
我还建议编写一些 RSpec 测试,至少在模型级别测试是否存在正确的关联。 shoulda gem 非常适合这个。
在这里评论你的发现。