【问题标题】:Ruby-newbie Active Record query / model associationRuby-newbie Active Record 查询/模型关联
【发布时间】:2012-03-21 12:37:20
【问题描述】:

这大概是我所拥有的:

我有很多公司通过角色拥有很多用户:

class Company < ActiveRecord::Base
  has_many :roles, :dependent => :destroy
  has_many :users, :through => :roles
end

还有很多用户可以通过角色拥有很多公司:

class User < ActiveRecord::Base
  has_many :roles, :dependent => :destroy
  has_many :comapnies, :through => :roles
end

以及将两者结合在一起的许多角色:

class Role < ActiveRecord::Base
  belongs_to :user
  belongs_to :company
end

这里的想法是用户可以通过通用电子邮件用户名登录,然后将权限分配给每个公司。角色具有 user_id 和 company_id 键以及权限列“user_role”(即访客、用户、管理员等)。

这是 ruby​​ 新手让我失望的地方。当我的用户登录时,我想查询他们拥有哪些公司的权限,并使用下拉菜单即时切换。因此,他们登录并在“公司 A”中处于活动状态,然后他们可以切换到“公司 B”。当他们切换时,company_id 存储在会话变量中(我已经将他们的 user_id 存储在正常运行的身份验证系统中)。

查询此问题的最佳方法是什么?我有一个 user_id,我想检索 company_id、company_name、'user_role' 等列表。然后使用它生成一个弹出列表。

我一直在使用控制台尝试Role.Company.etc.etc,但似乎无法弄清楚这一点。当我在 PHP / MySQL 中执行此操作之前,它会是一个复杂的连接查询。我确信在我无法理解的 Rails 中更容易。 任何帮助将不胜感激。

谢谢,

【问题讨论】:

  • 你不能做类似for company in current_user.companies的事情来做一个列表。要测试您是否正确处理了范围,您可以在其中一个视图中输入&lt;% if current_user? %&gt; &lt;%= current_user.companies %&gt; &lt;% end %&gt;
  • 这当然假设您的身份验证在他们登录时使用 current_user。
  • @kobaltz 在视图中触发 SQL 查询是一种不好的形式,因此最好只显示如何在操作中检索公司。
  • 所以在你的控制器中,它会像@companies = current_user.companies
  • current_user 是我的用户 ID 的整数值还是实际的用户对象?我已经有一个获取会话存储用户 ID 的应用程序帮助方法 current_user。

标签: ruby-on-rails-3 activerecord


【解决方案1】:

您可以通过current_user.companies.uniq 获取用户有权访问的所有公司(对于任何角色)。 uniq 部分只是确保您在列表中没有重复的公司(如果用户对单个公司拥有多个角色)。

【讨论】:

  • 好的...我现在明白了。我运行控制台并设置 current_user current_user = User.find(1),然后运行 ​​current_user.companies,它得到了我想要的东西。实际上,我的一个模型关系中的“公司”拼写错误,这是问题的一半。
  • 现在...我的问题是如何将角色添加到结果中。例如Company A:Guest, Company B:Admin, etc.。我通过 for 循环运行我的 current_user.companies 结果以创建一个简单的列表,但似乎无法弄清楚第二部分。
  • @companies = @user.companies.include(:roles) 然后是 @companies.each { |company| "#{company.role.name} of #{company.name}" } — 但是,这开始违反 Demeter 法则(谷歌搜索),所以你会想开始将 company.role.name 重构为 company.role_name 通过委托(在公司模型中):delegate :name, :to =&gt; :role, :prefix =&gt; :role.
  • 您可以在@companies.each { |company| "#{company.role.name} of #{company.name}" } 上展开完整登录吗?这是我现在拥有的&lt;% current_user_companies.each do |company| %&gt; &lt;li&gt;&lt;a href="/companies/&lt;%= company.id %&gt;"&gt;&lt;% if company.id == 1 %&gt;&lt;i class="icon-ok"&gt;&lt;/i&gt;&lt;% end %&gt;&lt;%= company.name %&gt;&lt;/a&gt;&lt;/li&gt; &lt;% end %&gt; 我让它遍历一个列表并显示公司名称。我正在寻找公司名称和角色,即“Stackoverlow (Admin)”、“ABC Ltd. (Guest)”。当我添加包含()时,它在NoMethodError: undefined method roles'`上运行失败`
  • 你为什么要手动建立链接?您似乎缺少很多基本的 Rails 知识……回到指南之旅可能是值得的。
【解决方案2】:

感谢大家的反馈。这让我看到了包含并再次加入。最后我查看了http://railscasts.com/episodes/181-include-vs-joins 和 Rails API 文档,然后拼凑起来:

Role.includes(:company).where(:user_id =&gt; session[:user_id])

然后我遍历@role,我可以提取 role.role_name 和 role.company.name 等。使用 User.find(session[:user_id]) 开始查询会使它复杂化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多