所以,自从我和人际关系玩起来已经有很长一段时间了,我想确保我做得对.
在我的客户模型中,我有:
class Client < ApplicationRecord
has_many :projects, dependent: :destroy
end
Run Code Online (Sandbox Code Playgroud)
在我的项目模型中,我有:
class Project < ApplicationRecord
belongs_to :client
end
Run Code Online (Sandbox Code Playgroud)
所以我知道那是设定的.然后抓住我放在项目控制器中的项目:
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
Run Code Online (Sandbox Code Playgroud)
我是否需要在我的节目中放一些同样的东西?
关系中我还缺少什么?
我会这样想:
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
Run Code Online (Sandbox Code Playgroud)
看起来更像是:
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
Run Code Online (Sandbox Code Playgroud)
注意
@project = @client.project.new(project_params)
Run Code Online (Sandbox Code Playgroud)
应该:
@project = @client.projects.new(project_params)
Run Code Online (Sandbox Code Playgroud)
正如Yechiel K所说,没有必要这样做:
@client.project << @project
Run Code Online (Sandbox Code Playgroud)
以来:
@project = @client.projects.new(project_params)
Run Code Online (Sandbox Code Playgroud)
将自动设置client_id为新的@project.顺便说一句,如果你想将添加project到client手动,然后它的:
@client.projects << @project
Run Code Online (Sandbox Code Playgroud)
(注意projects与project.)
如果没有clientwith 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
Run Code Online (Sandbox Code Playgroud)
而且,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
Run Code Online (Sandbox Code Playgroud)
这假设你的路线看起来像:
Rails.application.routes.draw do
resources :clients do
resources :projects
end
end
Run Code Online (Sandbox Code Playgroud)
在这种情况下,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
Run Code Online (Sandbox Code Playgroud)
更进一步,你可以这样做:
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
Run Code Online (Sandbox Code Playgroud)