两层has_many/belongs_to
Two layers of has_many/belongs_to
enter image description here我正在编写一个待办事项列表应用程序。每个用户可以有多个列表分类,每个列表分类可以包含多个列表项:
class User < ApplicationRecord
has_many :list_categories, dependent: :destroy
has_many :list_items, through: :list_categories
class ListCategory < ApplicationRecord
belongs_to :user
has_many :list_items, dependent: :destroy
class ListItem < ApplicationRecord
belongs_to :list_category
在 list_category 控制器的索引视图中,我有一个类别列表和一个用于创建新类别的表单,效果很好。
索引视图中的每个类别都有一个 link 到该类别的显示操作。在显示视图中,我有一个用于为该类别创建新列表项的表单(以便显示页面有效地充当列表项的 'new' 页面)和用于显示已创建的列表项的代码,但我没有都无法正常工作。
在 list_categories 控制器中我有:
def show
@list_category = current_user.list_categories.find(params[:id])
@list_item = @list_category.list_items.build
@list_items = @list_category.list_items
end
在 list_items 控制器中:
def create
@list_category = current_user.list_categories.find(params[:id])
@list_item = @list_category.list_items.build(list_item_params)
redirect_to list_category_path(@list_category)
end
private
def list_item_params
params.require(:list_item).permit(:content)
end
我尝试使用的表格是:
<%= form_for(@list_item) do |f| %>
<%= f.text_field :content %>
<%= f.submit "Add", class: "btn btn-primary" %>
<% end %>
以及显示列表类别中每个列表项的代码:
<% @list_items.each do |item| %>
<%= item.content %>
<% end %>
当我尝试在 show 操作中提交表单中的列表项时,我在 list_items 控制器的创建操作中收到此错误:
Couldn't find ListCategory without an ID
因为线路
@list_category = current_user.list_categories.find(params[:id])
我认为包括@list_item 是否正确,因为form_for 参数会自动将表单映射到list_item 创建操作?即使当我在错误行中手动输入一个 id 号并尝试创建一个列表项时,当我在 rrelevant 类别上调用 list_items 方法时,它说它不包含任何 list_items,所以for 仍然不起作用。
这是服务器日志:
Started POST "/list_items" for 127.0.0.1 at 2017-08-12 13:33:24 +0100
Processing by ListItemsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"F9kqlwQryyCFsddetAWF4WcI8g2x3c2hMCfaHGWad8QT1OHeHmdvzIFtEoqB8iYyE7vi0CWN+BChFZrpc1VcYw==", "list_item"=>{"content"=>"task"}, "commit"=>"Add"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Completed 404 Not Found in 3ms (ActiveRecord: 0.1ms)
ActiveRecord::RecordNotFound (Couldn't find ListCategory without an ID):
Couldn't find ListCategory without an ID
@list_category = current_user.list_categories.find(params[:id])
您使用 params[:id]
获取 list_category
,考虑到 params
,这是错误的。您应该在表单中有一个 hidden_field
来存储 @list_category
<%= form_for(@list_item) do |f| %>
<%= f.text_field :content %>
<%= f.hidden_field :list_category_id, value: @list_category.id %>
<%= f.submit "Add", class: "btn btn-primary" %>
<% end %>
并在 list_items#create
操作中使用 params[:list_item][:list_category_id]
访问它
@list_category = current_user.list_categories.find(params[:list_item][:list_category_id]).
此外,您没有保存 list_items
。您应该将 create
操作调整为低于
def create
@list_category = current_user.list_categories.find(params[:list_item][:list_category_id])
@list_item = @list_category.list_items.build(list_item_params)
if @list_item.save
redirect_to list_category_path(@list_category)
else
# your code for failed creation
end
end
这工作了一点,但是当我重新启动服务器等时,它开始不让我通过隐藏字段,因为 category_id 和 user_id 不在强参数中。但是,每个项目都需要一个 category_id 才能与正确的类别相关联,并且还需要一个 user_id(我打算在主页上显示所有用户的项目,无论类别如何)。
出于安全原因,我无法将 user_id 添加到强参数中,而且 category_id 也可能不好,因为它可能导致一个用户访问另一个用户的类别。如果我从表单中删除隐藏字段,它也不会工作,因为模型验证将失败。我一直在尝试使用嵌套路由来工作:
resources :users
resources :categories, only: [:create, :destroy, :index, :show] do
resources :items, only: [:create, :destroy]
end
形式为:
<%= form_for(@item, url: category_items_path(@category)) do |f| %>
物品型号:
class Item < ApplicationRecord
belongs_to :category
belongs_to :user
default_scope -> { order(:deadline) }
validates :category_id, presence: true
validates :user_id, presence: true
编辑 ---
嵌套路由是正确的方法,我按照以下 2 个视频中的说明获得了代码:
https://www.youtube.com/watch?v=HVuawlZTLBw
https://www.youtube.com/watch?v=WdaO0-DvjJw
enter image description here我正在编写一个待办事项列表应用程序。每个用户可以有多个列表分类,每个列表分类可以包含多个列表项:
class User < ApplicationRecord
has_many :list_categories, dependent: :destroy
has_many :list_items, through: :list_categories
class ListCategory < ApplicationRecord
belongs_to :user
has_many :list_items, dependent: :destroy
class ListItem < ApplicationRecord
belongs_to :list_category
在 list_category 控制器的索引视图中,我有一个类别列表和一个用于创建新类别的表单,效果很好。
索引视图中的每个类别都有一个 link 到该类别的显示操作。在显示视图中,我有一个用于为该类别创建新列表项的表单(以便显示页面有效地充当列表项的 'new' 页面)和用于显示已创建的列表项的代码,但我没有都无法正常工作。
在 list_categories 控制器中我有:
def show
@list_category = current_user.list_categories.find(params[:id])
@list_item = @list_category.list_items.build
@list_items = @list_category.list_items
end
在 list_items 控制器中:
def create
@list_category = current_user.list_categories.find(params[:id])
@list_item = @list_category.list_items.build(list_item_params)
redirect_to list_category_path(@list_category)
end
private
def list_item_params
params.require(:list_item).permit(:content)
end
我尝试使用的表格是:
<%= form_for(@list_item) do |f| %>
<%= f.text_field :content %>
<%= f.submit "Add", class: "btn btn-primary" %>
<% end %>
以及显示列表类别中每个列表项的代码:
<% @list_items.each do |item| %>
<%= item.content %>
<% end %>
当我尝试在 show 操作中提交表单中的列表项时,我在 list_items 控制器的创建操作中收到此错误:
Couldn't find ListCategory without an ID
因为线路
@list_category = current_user.list_categories.find(params[:id])
我认为包括@list_item 是否正确,因为form_for 参数会自动将表单映射到list_item 创建操作?即使当我在错误行中手动输入一个 id 号并尝试创建一个列表项时,当我在 rrelevant 类别上调用 list_items 方法时,它说它不包含任何 list_items,所以for 仍然不起作用。
这是服务器日志:
Started POST "/list_items" for 127.0.0.1 at 2017-08-12 13:33:24 +0100
Processing by ListItemsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"F9kqlwQryyCFsddetAWF4WcI8g2x3c2hMCfaHGWad8QT1OHeHmdvzIFtEoqB8iYyE7vi0CWN+BChFZrpc1VcYw==", "list_item"=>{"content"=>"task"}, "commit"=>"Add"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Completed 404 Not Found in 3ms (ActiveRecord: 0.1ms)
ActiveRecord::RecordNotFound (Couldn't find ListCategory without an ID):
Couldn't find ListCategory without an ID
@list_category = current_user.list_categories.find(params[:id])
您使用 params[:id]
获取 list_category
,考虑到 params
,这是错误的。您应该在表单中有一个 hidden_field
来存储 @list_category
<%= form_for(@list_item) do |f| %>
<%= f.text_field :content %>
<%= f.hidden_field :list_category_id, value: @list_category.id %>
<%= f.submit "Add", class: "btn btn-primary" %>
<% end %>
并在 list_items#create
操作中使用 params[:list_item][:list_category_id]
访问它
@list_category = current_user.list_categories.find(params[:list_item][:list_category_id]).
此外,您没有保存 list_items
。您应该将 create
操作调整为低于
def create
@list_category = current_user.list_categories.find(params[:list_item][:list_category_id])
@list_item = @list_category.list_items.build(list_item_params)
if @list_item.save
redirect_to list_category_path(@list_category)
else
# your code for failed creation
end
end
这工作了一点,但是当我重新启动服务器等时,它开始不让我通过隐藏字段,因为 category_id 和 user_id 不在强参数中。但是,每个项目都需要一个 category_id 才能与正确的类别相关联,并且还需要一个 user_id(我打算在主页上显示所有用户的项目,无论类别如何)。
出于安全原因,我无法将 user_id 添加到强参数中,而且 category_id 也可能不好,因为它可能导致一个用户访问另一个用户的类别。如果我从表单中删除隐藏字段,它也不会工作,因为模型验证将失败。我一直在尝试使用嵌套路由来工作:
resources :users
resources :categories, only: [:create, :destroy, :index, :show] do
resources :items, only: [:create, :destroy]
end
形式为:
<%= form_for(@item, url: category_items_path(@category)) do |f| %>
物品型号:
class Item < ApplicationRecord
belongs_to :category
belongs_to :user
default_scope -> { order(:deadline) }
validates :category_id, presence: true
validates :user_id, presence: true
编辑 ---
嵌套路由是正确的方法,我按照以下 2 个视频中的说明获得了代码:
https://www.youtube.com/watch?v=HVuawlZTLBw https://www.youtube.com/watch?v=WdaO0-DvjJw