Rails has_many和has_one带有参数

时间:2015-05-09 20:58:31

标签: ruby-on-rails associations has-many has-one

我有如下设置:

user.rb

class User < ActiveRecord::Base
  ...

  has_many :projects_users
  has_many :projects, through: :projects_users  

  ...

end

projects_users.rb

class ProjectsUser < ActiveRecord::Base
  belongs_to :project
  belongs_to :user

  has_one :projects_users_role  
end

project.rb

class Project < ActiveRecord::Base
  has_many :projects_users
  has_many :users, through: :projects_users
end

用户嵌套在我的路线文件中的Project下。

出于某种原因,我似乎找不到为用户访问单个项目的好方法。理想情况下,我想创建一个

 has_one :project_user

关联,然后是

has_one :project, through: :project_user 

以某种方式将项目的传递和id传递给关联(我知道这是不可能的)。任何有关良好方法的想法。

然后我想调用类似于

的方法
   @user = User.includes(:project (project_id parameter).find(:id) 

在我的用户控制器中。

非常感谢任何帮助。

谢谢

更新

我基本上有一个角色,每个项目都附加在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

  class ProjectsUsersRole < ActiveRecord::Base
    belongs_to :projects_user
    enum role: [...]
  end

我之前应该说明的目标是能够通过像

这样的路线为给定项目的用户编辑这个角色。
  /projects/1/users/2/edit-roles

这会显示用户,并允许我将该角色分配给projects_users_roles表,添加嵌套的id,即project_users表中的id。因此,我希望(我认为)有一个带有参数的项目的has_one,这样我的嵌套表单就会更简单。

更新2

我偶然发现了这个

 has_one :project_department, ->(department) { where department: department }, class_name: 'ProjectDepartment'  

从这里http://www.rojotek.com/blog/2014/05/16/cool-stuff-you-can-do-with-rails-has_one/但不能使它适用于将'department'替换为'project'不会在连接中使用项目ID,而在我的情况下不使用用户ID。

user.rb 更新

...
has_one :project_user, -> (project) { where project: project},    class_name: 'ProjectsUser'
has_one :project, through: :project_user  
...

从控制台

 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

在这种情况下,project_id应为1,但它使用的是user.id 26.不确定原因。

再次感谢

2 个答案:

答案 0 :(得分:2)

这是正确的,如果你有一个模型User,传递给closure的参数是被调用类实例的self,即它将是User的一个实例。因此,在下面的代码片project中,变量将具有user值。

<强> user.rb

has_one :project_user, -> (project) { where project: project}, class_name: 'ProjectsUser'

要将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)

该方法在Association Extension负责Rails Association页面中进行了描述。

答案 1 :(得分:0)

在一个SQL语句中生成结果的各种方法之一是使用左连接:

@user=User.joins(:projects).
     where("users.id = ? and projects.id = ?", 
            params[:id], 
            params[:project_id]).take # use take to get one row only

<强>更新
如果你想获得:

,上面的语句将产生一个额外的SQL请求
@user.projects.first.id

如果您不想再为该项目发表任何声明(当然您不会),您应该将联接与包含结合起来:

@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

所以现在

@user.projects.first.id

不会产生额外的SQL语句