【问题标题】:Rails model that has both 'has_one' and 'has_many' but with some constraintsRails 模型同时具有“has_one”和“has_many”但有一些限制
【发布时间】:2012-03-11 00:37:35
【问题描述】:

我正在映射 2 个模型:

User
Account

class Account 
  has_many :users


class User
  has_one :account

user表作为account_id在里面。

现在在帐户模型上,我想创建一个“主要用户”,一个帐户只有 1 个折扣。 用户表有一个布尔标志:is_primary,我如何在帐户端为映射了 is_primary 和 account_id 的用户创建一个 has_one。

所以 SQL 看起来像:

SELECT * FROM users where account_id=123 and is_primary = 1

所以我想要:

用户有一个帐户。 一个帐户有很多用户,也有一个主用户。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    方法 1 - 添加新关联

    添加与 where lambda 的 has_one 关联。这允许您在当前模式中工作。

    class Account 
      has_many :users
      has_one  :primary_user, -> { where(is_primary: true) }, :class_name=> "User"
    end
    

    现在:

    account.users #returns all users associated with the account
    account.primary_user #returns the primary user associated with the account
    # creates a user with is_primary set to true
    account.build_primary_user(name: 'foo bar', email: 'bar@foo.com')
    

    方法 2 - 添加关联方法

    class Account 
      has_many :users do
        def primary
          where(:is_primary => true).first
        end
      end
    end
    

    现在:

    account.users.primary # returns the primary account
    

    【讨论】:

    • 会感谢您的 cmets,因为它是相关的:stackoverflow.com/questions/9365068/…
    • 漂亮干净的方法。您介意使用方法 1 解释如何使用所有用户的 (collection_)select 更新 account#update 表单中的 primary_user 吗?谢谢
    • @Patient55 你试过用accepts_nested_attributes_for吗?
    【解决方案2】:

    将primary_user_id 字段添加到Account 并为primary_user 添加“has_one”关联可能会更简单:

    class Account
      has_many :users
      has_one :primary_user, :class_name => "User"
    end
    
    class User
      has_one :account
    end
    

    如果您必须使用现有架构(带有 :is_primary 布尔标志),您可以添加这样的范围:

    class User
      has_one :account
      scope :primary, where(:is_primary => true)
    end
    

    然后将范围链接到用户查找:

    account = Account.find(1)
    primary_user = account.users.primary.first
    

    【讨论】:

    • +1 表示第一种方法。虽然account.users.primaryaccount.users.primary.first 更具表现力
    • 非常正确,因为命名约定不流畅。但这很容易通过调用作用域primaries 来纠正,并将类方法定义为def self.primary; primaries.first; end。现在您可以使用通用范围primaries 或方法primary 来引用单个记录(此处只需要1 个)
    • -1 帐户没有存储用户信息的业务。最简洁的方法是引入 AccountPrimaryUser 绑定模型,并在 account_primary_users.account_id 列上进行唯一性验证,以确保只有一个主要用户。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 2012-12-09
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多