因此,我和人际关系玩了很长时间,我想确保我做得对。
在我的客户模型中,我有:
interleaveColumns = function(v) {
c(1, unlist(split(2:length(v), 1:((length(v)-1)/2)), use.names = FALSE))
}
df = tibble(val1 = 5:10, val2 = 10:15, val3 = 15:20, val4 = 25:30, val5 = 1:6);
# mutate_at can be given a named list to create a new column
# for each existing columnt (appended to the end => we need
# to reorder the columns and interleave the new columns with
# the old columns using the interleaveColumns function)
df %>%
mutate_at(vars(-1), list(rel = function(v) v/.[[1]])) %>%
select(interleaveColumns(.))
# A tibble: 6 x 9
val1 val2 val2_rel val3 val3_rel val4 val4_rel val5 val5_rel
<int> <int> <dbl> <int> <dbl> <int> <dbl> <int> <dbl>
1 5 10 2.00 15 3.00 25 5.00 1 0.200
2 6 11 1.83 16 2.67 26 4.33 2 0.333
3 7 12 1.71 17 2.43 27 3.86 3 0.429
4 8 13 1.62 18 2.25 28 3.50 4 0.500
5 9 14 1.56 19 2.11 29 3.22 5 0.556
6 10 15 1.50 20 2.00 30 3.00 6 0.600
在我的项目模型中,我有:
class Client < ApplicationRecord
has_many :projects, dependent: :destroy
end
所以我知道那是设定的。然后抓住我放在项目控制器中的项目:
class Project < ApplicationRecord
belongs_to :client
end
我是否需要在我的节目中放一些同样的东西?
我为关系而遗漏的其他东西?
答案 0 :(得分:5)
我会这么想:
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)
会自动在新client_id
上设置@project
。顺便说一句,如果你想手动向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
。这很常见。 Here's讨论为什么不这样做。就个人而言,我过去常常使用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
答案 1 :(得分:2)
我会替换这一行:
flash[:notice] = "Project created successfully" if @client.project << @project
使用:
flash[:notice] = "Project created successfully" if @project.save
无需手动将@project
添加到@client.projects
,当您使用@client.projects.new
创建时,它会自动添加,您唯一遗漏的是使用.new
创建内容并不会将其保留在数据库中,而是通过调用@project.save
来完成。
对于您的展示操作,我不确定您是指客户的展示页面还是项目,但在任何一种情况下,您都会使用params[:id]
检索它(除非你使用一些嵌套路由。)