[英]Rails has_many and has_one with argument
I have a setup like the below: 我有如下设置:
user.rb user.rb
class User < ActiveRecord::Base
...
has_many :projects_users
has_many :projects, through: :projects_users
...
end
projects_users.rb projects_users.rb
class ProjectsUser < ActiveRecord::Base
belongs_to :project
belongs_to :user
has_one :projects_users_role
end
project.rb project.rb
class Project < ActiveRecord::Base
has_many :projects_users
has_many :users, through: :projects_users
end
Users are nested under Project in my routes file. 用户嵌套在我的路线文件中的Project下。
For some reason, I cannot seem to find a good way of accessing a single project for a user. 由于某种原因,我似乎找不到为用户访问单个项目的好方法。 Ideally I would like to create a
理想情况下,我想创建一个
has_one :project_user
association and then a 关联,然后
has_one :project, through: :project_user
and somehow pass and id for the project to the association (which I know is not possible). 并以某种方式将项目的ID和ID传递给关联(我知道这是不可能的)。 Any ideas for a good approach.
任何好的方法的想法。
I would then like to call a method similar to 然后,我想调用类似于
@user = User.includes(:project (project_id parameter).find(:id)
in my users controller. 在我的用户控制器中。
Any assistance is greatly appreciated. 非常感谢您的协助。
Thank you 谢谢
UPDATE UPDATE
I essentially have a role that is attached per project per user in the projects_users.rb (updated above and added below) 我本质上是在projects_users.rb中为每个用户的每个项目附加了一个角色(上面已更新,下面已添加)
projects_users.rb projects_users.rb
class ProjectsUser < ActiveRecord::Base
belongs_to :project
belongs_to :user
has_one :projects_users_role
end
projects_users_role.rb projects_users_role.rb
class ProjectsUsersRole < ActiveRecord::Base
belongs_to :projects_user
enum role: [...]
end
And my aim, which I should have stated previously is to be able to edit this role for the user on the given project via a route like 我的目标(我之前应该已经说过)是能够通过类似以下路线为给定项目中的用户编辑此角色
/projects/1/users/2/edit-roles
this would display the user, and allow me to assign the role to the projects_users_roles table, with the nested ids added ie the id from the project_users table. 这将显示用户,并允许我将角色分配给projects_users_roles表,并添加嵌套的ID,即project_users表中的ID。 Hence I would like (I think) to have a has_one to projects with an argument so that my nested form would be simpler.
因此,我希望(我认为)使用一个参数将has_one投影到项目中,以便嵌套形式更简单。
Update 2 更新2
I have stumbled across this 我偶然发现了这个
has_one :project_department, ->(department) { where department: department }, class_name: 'ProjectDepartment'
from here http://www.rojotek.com/blog/2014/05/16/cool-stuff-you-can-do-with-rails-has_one/ but cannot make it apply as replacing 'department' with 'project' does not use the project id in the join but the user id in my case. 从这里http://www.rojotek.com/blog/2014/05/16/cool-stuff-you-can-do-with-rails-has_one/,但是不能以将“部门”替换为“项目”来应用在联接中不使用项目ID,但在本例中为用户ID。
user.rb update user.rb 更新
...
has_one :project_user, -> (project) { where project: project}, class_name: 'ProjectsUser'
has_one :project, through: :project_user
...
From the console 从控制台
User.first.project_user(1)
User Load (0.2ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
ProjectsUser Load (0.1ms) SELECT `projects_users`.* FROM `projects_users` WHERE `projects_users`.`user_id` = 26 AND `projects_users`.`project_id` = 26 LIMIT 1
The project_id should be 1 in this case but it is using the user.id 26. Not sure why really. 在这种情况下,project_id应该为1,但它正在使用user.id26。不确定为什么。
Thanks again 再次感谢
That is correct, if you have a model User
, an argument which is passed to closure is the self
for called class instance, ie it will be an instance of User
. 没错,如果您有模型
User
,则传递给闭包的参数是被调用类实例的self
,即它将是User
的实例。 So in following code piece project
variable will have a user
value. 因此,在以下代码段中,
project
变量将具有user
值。
user.rb user.rb
has_one :project_user, -> (project) { where project: project}, class_name: 'ProjectsUser'
To pass into has_many/one
relation an additional argument use extending selector: 要将
has_many/one
关系传递给其他参数,请使用扩展选择器:
class User < ActiveRecord::Base
has_one :project_user, class_name: 'ProjectsUser' do
def for_project(project)
where(project: project)
end
end
end
customers.project_user.for_project(project)
The approach is described in Association Extension
head in Rails Association
page. 该方法在Rails
Association
页面的Association Extension
头中进行了描述。
One of various ways to produce your result in one SQL statement, would be with a left join: 在一个SQL语句中产生结果的多种方法之一是左连接:
@user=User.joins(:projects).
where("users.id = ? and projects.id = ?",
params[:id],
params[:project_id]).take # use take to get one row only
UPDATE UPDATE
The above statement will produce an extra SQL request if you want to get: 如果您希望获得上述声明,则会产生一个额外的SQL请求:
@user.projects.first.id
If you want no more statements for the project (of course you don't) you should combine the join with an include: 如果您不希望该项目有更多的语句(当然,您不希望这样做),则应将join和include结合使用:
@user=User.joins(:projects).includes(:projects).
where("users.id = ? and projects.id = ?",
params[:id],
params[:project_id]).take # use take to get one row only
So now 所以现在
@user.projects.first.id
will produce no extra SQL statements 不会产生额外的SQL语句
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.