我在Event,Meeting和TaskList之间建立了一个多态关联,以便:
这可行,我可以从这些模型的视图中创建task_lists。但是我的问题是我希望能够将TaskItem添加到每个TaskList中,以便:
我无法路由表单来创建任务项。我为此创建了一个“_form.html.erb”,并从task_item的视图中呈现它。我正在使用下面的表格,目前从事件视图,它显示表单正常,但抛出路由错误“没有路由匹配[POST]”/events/3/task_lists/new.3 < / strong>“点击提交时。
_form.html.erb
<%= form_for TaskItem.new, url: new_polymorphic_path([@listable, @task_list, @task_item]) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
我也试过像下面这样设置它甚至不显示抛出错误的表单“表格中的第一个参数不能包含nil或为空”
<%= form_for @task_item do %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
模型
class TaskList
belongs_to :listable, polymorphic: true
has_many :task_items
end
class TaskItem
belongs_to :task_list
end
class Event
has_many :task_lists, as: :listable
end
class Meeting
has_many :task_lists, as: :listable
end
路由(添加:show to task_lists,only :,因为我的链接不起作用。)
concern :has_task_lists do
resources :task_lists, only: [:new, :index, :create, :show]
end
resources :events, :meetings, concerns: [:has_task_lists]
resources :task_lists, except: [:new, :index, :create] do
resources :task_items
end
task_items_controller(希望它重定向到从中创建的页面项,这是task_list的show view)
def create
@task_item = @task_list.task_items.new(task_item_params)
if @task_item.save
redirect_to @task_list, notice: "Task Item Created"
else
render :new
end
端
task_lists_controller
before_action :load_listable
def show
@task_list = @listable.task_lists.find(params[:id])
end
def load_listable
klass = [Event, Meeting].detect { |c| params["#{c.name.underscore}_id"]}
@listable = klass.find(params["#{klass.name.underscore}_id"])
end
答案 0 :(得分:0)
这里的一个关键问题是task_items
嵌套的级别太深。
经验法则:资源不应嵌套超过1级 深。集合可能需要由其父级确定范围,但需要具体 成员总是可以通过id直接访问,而不应该需要 作用域。
- Jamis Buck
所以为了解决这个问题,我们会声明这样的路线:
concern :has_task_lists do
resources :task_lists, only: [:new, :index, :create]
end
resources :events, :meetings, concerns: [:has_task_lists]
resources :task_lists, except: [:new, :index, :create] do
resources :task_items
end
routing concern让我们重新使用嵌套路线。
因为我们已经摆脱了额外的&#34;父母&#34;我们可以简化表格:
form_for([ @task_list, @task_item || @task_list.task_items.new ])
如果您将表单嵌入另一个控制器/操作中, @task_item || @task_list.task_items.new
将阻止错误。
您实际上必须创建作用于父级的资源。只做form_for([@a, @b])
不会自动关联记录 - 它只是生成url并设置表单方法(POST或PATCH)。
class TaskItemsController < ApplicationController
before_action :set_task_list
def new
@task_item = @task_list.task_items.new
end
def create
@task_item = @task_list.task_items.new(task_item_params)
if @task_item.save
redirect_to task_list_path(@task_list), notice: "Task Item Created"
else
render :new
end
end
private
def set_task_list
@task_list = TaskList.find(params[:task_list_id])
end
# ...
end
当您致电@task_list.task_items.new
时,您正在调用集合上的.new
方法 - 因此新的TaskItem将设置task_list_id
列。
请注意,您也可以编写redirect_to @task_list
并且rails会将剩下的内容写出来。如果您需要重定向到嵌套资源,例如新创建的项目,您将执行以下操作:
redirect_to [@task_list, @task_item]