我正在努力使我正在构建的Web应用程序的用户能够创建他们创建的对象列表。
例如,用户有一个对象列表,例如 groceries ,可以是从苹果到橙子到pop-tarts的任何东西。
我希望我能够返回用户添加到数据库中的所有杂货,并通过选择应该在他们的购物清单上的那些来创建列表。
最好是这样的样式,以便他们可以点击他们想要的复选框,然后点击保存以创建新列表。
我已经研究过belongs_to,has_many关系并试图创建一个包含许多杂货的列表对象,但我无法弄清楚这个策略的形式部分。我很感激任何/所有建议。谢谢!
这是我目前的代码,我最初省略它,因为我不认为我在正确的道路上,但这里无论如何只是以防万一/提供更多背景:
杂货店型号:
class Item < ApplicationRecord
belongs_to :list, optional: true
end
列表模型
class List < ApplicationRecord
has_many :items
end
列表控制器
class ListsController < ApplicationController
before_action :authenticate_user!
layout 'backend'
def index
@lists = List.where(user_id: current_user.id)
end
def show
end
def new
@list = List.new
end
def edit
end
def create
@list = List.new(list_params)
@list.user = current_user
if @list.save
redirect_to list_path(@list.id), notice: 'List was successfully created.'
else
redirect_to list_path(@list.id), notice: 'List was not created.'
end
end
def update
respond_to do |format|
if @list.update(list_params)
format.html { redirect_to @list, notice: 'List was successfully updated.' }
format.json { render :show, status: :ok, location: @list }
else
format.html { render :edit }
format.json { render json: @list.errors, status: :unprocessable_entity }
end
end
end
def destroy
@list.destroy
respond_to do |format|
format.html { redirect_to lists_url, notice: 'List was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Never trust parameters from the scary internet, only allow the white list through.
def list_params
params.require(:list).permit(:name, :items)
end
end
不确定如何处理表单 - 尝试了http://apidock.com/rails/ActionView/Helpers/FormHelper/check_box
的内容答案 0 :(得分:2)
我会通过实施第三个模型来解决这个问题,该模型可以保持杂货和清单之间的关联。然后,您可以使用:accepts_nested_attributes_for
在表单中处理它。
举一个例子,这是我如何构建模型:
class List < ApplicationRecord
has_many :list_items, inverse_of: :list
has_many :items, through: :list_items
# This allows ListItems to be created at the same time as the List,
# but will only create it if the :item_id attribute is present
accepts_nested_attributes_for :list_items, reject_if: proc { |attr| attr[:item_id].blank? }
end
class Item < ApplicationRecord
has_many :list_items
has_many :lists, through: :list_items
end
class ListItem < ApplicationRecord
belongs_to :list, inverse_of: :list_items
belongs_to :item
end
使用该模型结构,以下是创建新List的视图示例。
<h1>New List</h1>
<%= form_for @list do |f| %>
<% @items.each_with_index do |item, i| %>
<%= f.fields_for :list_items, ListItem.new, child_index: i do |list_item_form| %>
<p>
<%= list_item_form.check_box :item_id, {}, item.id, "" %> <%= item.name %>
</p>
<% end %>
<% end %>
<p>
<%= f.submit 'Create List' %>
</p>
<% end %>
为了解释这里发生的事情,@items
是一个预加载变量,包含可以添加到列表中的所有项目。我遍历每个Item,然后手动将它传递给FormBuilder方法fields_for
。
因为我手动执行此操作,所以我必须同时指定:child_index
,否则每个复选框将获得与上一项相同的名称属性(即name="list[list_item_attributes][0][item_id]"
),并且它们将覆盖每个其他人在提交给服务器时会有价值。
FormBuilder方法check_box
具有以下声明:
def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
因此,在上面的表单中,我替换了这些默认值,以便在选中复选框时,它具有item.id
的值,如果未选中,则该值为空。将此与List模型中的accepts_nested_attributes_for
声明相结合,我们说如果:item_id
为空,则应该拒绝它,并且我们得到的结果是只为已检查的Items创建ListItem。
使这项工作的最后一件事是允许控制器中的嵌套属性,如下所示:
def allowed_params
params.require(:list).permit(list_items_attributes: [:item_id])
end
答案 1 :(得分:0)
所以我找到了以下问题并使用它以便能够完成我想要的任务。
Display a checkbox list instead of multiple select
我只是实现了以下
<% form_for @list do |f| %>
<% Item.all.each do |item|
<%= f.check_box(:items, { :multiple => true }, item.id) %>
<% end %>
<% end %>
此时我遇到的错误是没有分配list_id。我进行了一次迁移,以便为Item模型添加attirbute“list_id”,并修复了它,并且所有工作都按照我想要的方式进行。
有什么问题吗?