[英]Rails Relationship (has_many/belongs_to) Completed
所以,自从我和人际关系玩起来已经有很长一段时间了,我想确保我做得对。
在我的客户模型中,我有:
class Client < ApplicationRecord
has_many :projects, dependent: :destroy
end
在我的项目模型中,我有:
class Project < ApplicationRecord
belongs_to :client
end
所以我知道那是设定的。 然后抓住我放在项目控制器中的项目:
def create
@client = Client.find(params[:client_id])
@project = @client.project.new(project_params)
flash[:notice] = "Project created successfully" if @client.project << @project
respond with @project, location: admin_project_path
end
我是否需要在我的节目中放一些同样的东西?
关系中我还缺少什么?
我会这样想:
def create
@client = Client.find(params[:client_id])
@project = @client.project.new(project_params)
flash[:notice] = "Project created successfully" if @client.project << @project
respond with @project, location: admin_project_path
end
看起来更像是:
def create
@client = Client.find(params[:client_id])
@project = @client.projects.new(project_params)
if @project.save
# do success stuff
else
# do failure stuff
end
end
注意
@project = @client.project.new(project_params)
应该:
@project = @client.projects.new(project_params)
正如Yechiel K所说,没有必要这样做:
@client.project << @project
以来:
@project = @client.projects.new(project_params)
将自动在新的@project
上设置client_id
。 顺便说一句,如果你想手动将project
添加到client
,那么它是:
@client.projects << @project
(注意projects
与project
。)
如果没有client
使用params[:client_id]
,那么@client = Client.find(params[:client_id])
将抛出错误。 你可能应该包括一个救援区。 或者,我更喜欢:
def create
if @client = Client.find_by(id: params[:client_id])
@project = @client.projects.new(project_params)
if @project.save
# do success stuff
else
# do failure stuff
end
else
# do something when client not found
end
end
此外, respond with
不是一件事。 respond_with
是一件事。 (我相信它已被转移到一个单独的宝石, responders
。)从你的代码中不清楚你是否需要不同的响应,比如, html
和js
。 如果没有,那么我认为它更像是:
def create
if @client = Client.find_by(id: params[:client_id])
@project = @client.projects.new(project_params)
if @project.save
flash[:notice] = "Project created successfully"
redirect_to [@client, @project]
else
# do failure stuff
end
else
# do something when client not found
end
end
这假设你的路线看起来像:
Rails.application.routes.draw do
resources :clients do
resources :projects
end
end
在这种情况下,rails会将[@client, @project]
解析为正确的路由/路径。
正如DaveMongoose所提到的,你可以将@client = Client.find_by(id: params[:client_id])
到before_action
。 这很常见。 这里有一个关于为什么不这样做的讨论。 就个人而言,我曾经像这样使用before_action
,但是不再这样了。 作为替代方案,您可以:
class ProjectsController < ApplicationController
...
def create
if client
@project = client.projects.new(project_params)
if @project.save
flash[:notice] = "Project created successfully"
redirect_to [client, @project]
else
# do failure stuff
end
else
# do something when client not found
end
end
private
def client
@client ||= Client.find_by(id: params[:client_id])
end
end
更进一步,你可以这样做:
class ProjectsController < ApplicationController
...
def create
if client
if new_project.save
flash[:notice] = "Project created successfully"
redirect_to [client, new_project]
else
# do failure stuff
end
else
# do something when client not found
end
end
private
def client
@client ||= Client.find_by(id: params[:client_id])
end
def new_project
@new_project ||= client.projects.new(project_params)
end
end
我会替换这一行:
flash[:notice] = "Project created successfully" if @client.project << @project
有:
flash[:notice] = "Project created successfully" if @project.save
无需手动将@project
添加到@client.projects
,当您使用@client.projects.new
创建它时会自动添加它,您唯一遗漏的是使用.new
创建内容并不会将其保留在DB中,通过调用@project.save
完成。
对于你的节目动作,我不确定你是指客户的节目页面还是项目的,但在任何一种情况下,你都会使用params[:id]
检索它(除非你使用了一些嵌套路由)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.