我的Rails 4应用中有User
模型。它包含account_type
class User < ActiveRecord::Base
enum account_type: [manager: 0, contractor: 1, employee: 2]
end
目前account_type
用于修改多个操作的行为。但在将来,我需要引入几个属性,这些属性对于不同的帐户类型会有不同的值(例如某些API端点的速率限制或订阅价格)。
我该如何处理?
我可以添加新模型UserAccountType
模型,并在其与belongs_to
模型之间设置has_many
- User
关联链接,但我将失去对{{1}等方法的访问权限由manager?
方便地提供。此外,我将必须适当地播种相关表,这意味着我将不得不放置映射'帐户类型'&lt; - &gt; ActiveRecord
中的整数,并确保它为所有帐户类型创建记录,这些帐户类型也不是DRY。有没有办法更好地做到这一点?
答案 0 :(得分:3)
看起来你正在寻找一个简单的角色系统。 Rolify宝石非常适合:https://github.com/RolifyCommunity/rolify。除了包含的内容之外,还可以轻松添加其他便捷方法。
有足够的人试图解决这个问题,出现了一些模式。例如,您确定项目的生命周期中每个用户的单个角色是否足够?您可能需要数组类型(或一对多)而不是枚举。
如果您想自己实现它,如果您使用的是Postgres,则数组字段类型可能是存储和添加&#34;角色的好方法。至于方便的方法,你可以替换像is_manager这样的东西吗?几行。我不会让这阻止你创建一个更合适和可持续的数据模型。
示例:
def is_manager?
User.find(1).roles.include?('manager')
end
答案 1 :(得分:1)
当您提到要为enum
个对象添加额外属性时,您必须小心了解要添加的内容。
根据docs:
声明一个枚举属性,其中值映射到数据库中的整数,但可以按名称查询。
基本上,这意味着enum
属性的存储值将是一个数字; Rails会将这个数字“翻译”成冗长的形式。如果需要,可以使用单实例方法轻松实现。
因此,您提供给我们的用例无效:
请注意,使用数组时,从值到数据库整数的隐式映射是从值在数组中出现的顺序派生的。在示例中,:active映射为0,因为它是第一个元素,并且:archived映射到1.通常,第i个元素映射到数据库中的i-1。
Conversation.statuses[:active] # => 0
Conversation.statuses["archived"] # => 1
-
与您的问题的不同之处在于,如果您想将更多规范添加到enum
功能,那么您真正进入了另一个模型的领域。
如@errata
所述,如果您想使用您的示例,您可以更好地使用基于角色的功能。
您从大型项目中学到的最好的事情之一是需要具体了解功能。很容易说“我需要一个新模型”,非常不同,以了解它在功能层面上必须做什么。
因此,我建议的是看看你想要实现的目标完全。如果你想要“额外”属性等,你需要另一个模型。如果您只是使用单个值,请坚持使用enum
。
某些API端点或订阅价格的费率限制
我个人会使用以下内容:
#app/models/user.rb
class User < ActiveRecord::Base
belongs_to :account_type
delegate :rate_limit, to: :account_type #-> @user.rate_limit.speed
end
#app/models/account_type.rb
class AccountType < ActiveRecord::Base
has_many :users
belongs_to :rate_limit #-> maybe
end
这将允许您致电:
@user = User.find x
@user.rate_limit.throttle
可能会使用更灵活的东西,但上述情况应该没问题。