【问题标题】:Rails has_many through with condition, build newRails has_many 通过条件,构建新
【发布时间】:2012-08-22 22:15:27
【问题描述】:

我的用户和组织具有加入模型 UsersOrganisation。用户可能是组织的管理员 - 如果是这样,is_admin 布尔值为真。

如果我在数据库中手动设置 is_admin 布尔值,Organisations.admins 会按我的预期工作。

在控制台中,我可以执行Organisation.first.users << User.first,它会按照我的预期创建一个 organizations_users 条目。

但是,如果我执行Organisation.first.admins << User.last,它会创建一个普通用户,而不是管理员,即连接表上的 is_admin 布尔值设置不正确。

除了直接在连接表中创建条目之外,还有其他好的方法吗?

class User < ActiveRecord::Base

  has_many :organisations_users
  has_many :organisations, :through => :organisations_users

end

class Organisation <  ActiveRecord::Base

  has_many :organisations_users
  has_many :users, :through => :organisations_users
  has_many :admins, :through => :organisations_users, :class_name => "User", 
            :source => :user, 
            :conditions => {:organisations_users => {:is_admin => true}}

end

class OrganisationsUser < ActiveRecord::Base

  belongs_to :organisation
  belongs_to :user

end

【问题讨论】:

  • 确保has_many :admins, :through =&gt; ... ... 确实适用于选择,而不是插入数据。所以当你在做Organisation.first.admin &lt;&lt; User.last 时,它只是在创建普通条目。但是,我想知道如何做到这一点。谢谢你的问题。

标签: ruby-on-rails ruby-on-rails-3 has-many-through


【解决方案1】:

has_many :through&lt;&lt; 运算符有一些变化。但是你可以像@Erez 的回答那样重载它。

我的方法是使用范围(我将 OrganisationsUsers 重命名为 Memberships):

class User < ActiveRecord::Base

  has_many :memberships
  has_many :organisations, :through => :memberships

end

class Organisation <  ActiveRecord::Base
  has_many :memberships
  has_many :members, :through => :memberships, :class_name => 'User', :source => :user

  # response to comment:
  def admins 
    memberships.admin
  end
end

class Memberships < ActiveRecord::Base

  belongs_to :organisation
  belongs_to :user

  scope :admin, where(:is_admin => true)
end

现在我像这样创建新管理员:

Organisation.first.memberships.admin.create(:user => User.first)

我喜欢范围的一点是,您可以在成员资格类中定义“成员资格类型”,而组织本身根本不需要关心成员资格类型。

更新

现在你可以做

Organisation.first.admins.create(:user =&gt; User.first)

【讨论】:

  • 有什么办法可以做到这一点Organisation.first.admins.create(:user =&gt; User.first)
  • 是的,如果您在组织模型中创建一个小别名(请参阅我编辑的答案)
  • 我最终为连接表制作了一个嵌套表单,但我接受了这个答案,因为它非常清楚地回答了我的问题。
【解决方案2】:

你总是可以覆盖

has_many :admins do

  def <<(user)
    user.is_admin = true
    self << user
  end

end

(代码未检查)

【讨论】:

    【解决方案3】:

    您可以尝试下面的组织模型代码。

    class Organisation < ActiveRecord::Base
    
      has_many :organisations_users
      has_many :organisations_admins, :class_name => "OrganisationsUser", :conditions => { :is_admin => true }
    
      has_many :users,  :through => :organisations_users
      has_many :admins, :through => :organisations_admins, :source => :user
    
    end
    

    【讨论】:

    • 更喜欢这种方法,因为它也解决了分配问题。
    猜你喜欢
    • 2011-10-27
    • 2017-10-09
    • 1970-01-01
    • 2011-10-25
    • 2017-01-24
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多