与 Rails 的双向 many-to-many 关联:如何从双向创建?
Bidirectional many-to-many association with Rails : how to create from both ways?
我对 Rails 上 Ruby 中的 many-to-many 关联有疑问。
我的应用程序中有 3 个模型:与 manu-to-many 关联关联的主题、会议和待办事项。
class Todo < ApplicationRecord
belongs_to :topic
belongs_to :meeting
end
然后
class Meeting < ApplicationRecord
has_many :todos
end
和
class Topic < ApplicationRecord
has_many :todos
end
我让我的路线和控制器能够通过会议创建新的待办事项:
Rails.application.routes.draw do
resources :meetings, only: [:index, :show, :new, :create, :edit, :update] do
resources :todos, only: [:index, :new, :create]
end
resources :todos, only: [:index, :show, :edit, :update, :destroy]
end
和
class TodosController < ApplicationController
def new
@topic = Topic.find(params[:topic_id])
@todo = Todo.new
end
def create
@todo = Todo.new(todo_params)
@meeting = Meeting.find(params[:meeting_id])
@todo.meeting = @meeting
@todo.save
redirect_to meeting_path(@meeting)
end
private
def todo_params
params.require(:todo).permit(:topic_id, :meeting_id, :note, :deadline, :title)
end
end
我的观点:
<h3><%= @meeting.date %></h3>
<%= simple_form_for [@meeting, @todo] do |f| %>
<%= f.input :title %>
<%= f.input :note %>
<%= f.date_field :deadline %>
<%= f.association :topic, label_method: :nom, value_method: :id %>
<%= f.submit "Add a todo" %>
<% end %>
我的问题是我希望能够通过主题创建待办事项以及添加路由时:
resources :topics, only: [:index, :show, :new, :create] do
resources :todos, only: [:index, :new, :create]
end
当我试图完成我的控制器并对其进行测试时,它似乎很棘手。如果我添加:
@topic = Topic.find(params[:topic_id])
然后它告诉我它需要开会...
有什么想法吗?
您可以创建不同的路线:
resources :meetings do
resources :todos, only: [:index, :new, :create]
end
resources :topics do
resources :todos, only: [:index, :new, :create]
end
您可以通过使用路由问题来避免重复:
concerns :todoable do
resources :todos, only: [:index, :new, :create]
end
resources :topics, concerns: :todoable
resources :meetings, concerns: :todoable
在您的控制器中,您可以检查是否存在 meeting_id
或 topic_id
参数:
class TodosController < ApplicationController
before_action :set_parent
def new
@todo = Todo.new
end
def create
@todo = @parent.todos.new(todo_params)
if @todo.save
redirect_to @parent
else
render :new
end
end
private
def parent_class
@parent_class ||= if params[:meeting_id].present?
Meeting
else if params[:topic_id].present?
Topic
else
# raise an error?
end
end
def set_parent
id = params["#{parent_class.model_name.param_key}_id"]
@parent = parent_class.find(id)
end
def todo_params
params.require(:todo)
.permit(:topic_id, :meeting_id, :note, :deadline, :title)
end
end
<%= simple_form_for [@parent, @todo] do |f| %>
<%= f.input :title %>
<%= f.input :note %>
<%= f.date_field :deadline %>
<%= f.association :topic, label_method: :nom, value_method: :id if @parent.is_a?(Meeting) %>
<%= f.association :meeting, label_method: :nom, value_method: :id if @parent.is_a?(Topic) %>
<%= f.submit "Add a todo" %>
<% end %>
我对 Rails 上 Ruby 中的 many-to-many 关联有疑问。
我的应用程序中有 3 个模型:与 manu-to-many 关联关联的主题、会议和待办事项。
class Todo < ApplicationRecord
belongs_to :topic
belongs_to :meeting
end
然后
class Meeting < ApplicationRecord
has_many :todos
end
和
class Topic < ApplicationRecord
has_many :todos
end
我让我的路线和控制器能够通过会议创建新的待办事项:
Rails.application.routes.draw do
resources :meetings, only: [:index, :show, :new, :create, :edit, :update] do
resources :todos, only: [:index, :new, :create]
end
resources :todos, only: [:index, :show, :edit, :update, :destroy]
end
和
class TodosController < ApplicationController
def new
@topic = Topic.find(params[:topic_id])
@todo = Todo.new
end
def create
@todo = Todo.new(todo_params)
@meeting = Meeting.find(params[:meeting_id])
@todo.meeting = @meeting
@todo.save
redirect_to meeting_path(@meeting)
end
private
def todo_params
params.require(:todo).permit(:topic_id, :meeting_id, :note, :deadline, :title)
end
end
我的观点:
<h3><%= @meeting.date %></h3>
<%= simple_form_for [@meeting, @todo] do |f| %>
<%= f.input :title %>
<%= f.input :note %>
<%= f.date_field :deadline %>
<%= f.association :topic, label_method: :nom, value_method: :id %>
<%= f.submit "Add a todo" %>
<% end %>
我的问题是我希望能够通过主题创建待办事项以及添加路由时:
resources :topics, only: [:index, :show, :new, :create] do
resources :todos, only: [:index, :new, :create]
end
当我试图完成我的控制器并对其进行测试时,它似乎很棘手。如果我添加:
@topic = Topic.find(params[:topic_id])
然后它告诉我它需要开会...
有什么想法吗?
您可以创建不同的路线:
resources :meetings do
resources :todos, only: [:index, :new, :create]
end
resources :topics do
resources :todos, only: [:index, :new, :create]
end
您可以通过使用路由问题来避免重复:
concerns :todoable do
resources :todos, only: [:index, :new, :create]
end
resources :topics, concerns: :todoable
resources :meetings, concerns: :todoable
在您的控制器中,您可以检查是否存在 meeting_id
或 topic_id
参数:
class TodosController < ApplicationController
before_action :set_parent
def new
@todo = Todo.new
end
def create
@todo = @parent.todos.new(todo_params)
if @todo.save
redirect_to @parent
else
render :new
end
end
private
def parent_class
@parent_class ||= if params[:meeting_id].present?
Meeting
else if params[:topic_id].present?
Topic
else
# raise an error?
end
end
def set_parent
id = params["#{parent_class.model_name.param_key}_id"]
@parent = parent_class.find(id)
end
def todo_params
params.require(:todo)
.permit(:topic_id, :meeting_id, :note, :deadline, :title)
end
end
<%= simple_form_for [@parent, @todo] do |f| %>
<%= f.input :title %>
<%= f.input :note %>
<%= f.date_field :deadline %>
<%= f.association :topic, label_method: :nom, value_method: :id if @parent.is_a?(Meeting) %>
<%= f.association :meeting, label_method: :nom, value_method: :id if @parent.is_a?(Topic) %>
<%= f.submit "Add a todo" %>
<% end %>