Rails模型:您将如何创建预定义的属性集?

And*_*rew 38 activerecord attributes model ruby-on-rails ruby-on-rails-3

我正在试图找出设计导轨模型的最佳方法.出于示例的目的,假设我正在构建一个字符数据库,这可能有几个不同的固定属性.例如:

Character
- Morality (may be "Good" or "Evil")
- Genre (may be "Action", "Suspense", or "Western")
- Hair Color (may be "Blond", "Brown", or "Black")
Run Code Online (Sandbox Code Playgroud)

... 等等.

因此,对于Character模型,有几个属性,我希望基本上有一个固定的可能选择列表.

我希望用户能够创建一个角色,并希望他们从每个可用选项中选择一个.我还希望能够让用户使用这些属性中的每一个进行搜索...(即,"显示'好'中的字符',来自'悬疑'类型,并且具有'棕色'头发".

我可以想到几种方法来做到这一点......


1:为每个属性创建一个字符串并验证有限的输入.

在这种情况下,我将在字符表上定义一个字符串列"Morality",然后使用其中指定的选项具有类常量,然后针对该类常量进行验证.

找到好的角色就好Character.where(:morality=>'Good').

这很简单,缺点是如果我想为属性添加更多细节,例如描述"Good"和"Evil",以及用户可以查看给定道德的所有字符的页面.

2:为每个属性创建一个模型

在这种情况下Character belongs_to Morality,会有一个Morality模型和一个moralities包含两个记录的表:Morality id:1, name:Good等等.

找到好的角色就像Morality.find_by_name('Good').characters......或者 Character.where(:morality=> Morality.find(1).

这样可以正常工作,但这意味着您有几个表只存在少量预定义属性.

3:为属性创建STI模型

在这种情况下,我可以像#2一样,除了创建一个通用的"CharacterAttributes"表,然后将其子类化为"MoralityAttribute"和"GenreAttribute"等.这使得只有一个表用于许多属性,否则它看起来大致相同作为想法#2.


所以,这些是我能想到解决这个问题的三种方式.

我的问题是,你将如何实现这一点,为什么?

你会使用上面的方法之一,如果是这样的话?你会做些不同的事吗?我特别有兴趣听听您将采取的方法的性能考虑因素.我知道这是一个广泛的问题,谢谢你的任何意见.

编辑: 我在这个问题上添加了250的赏金(超过我的声誉的10%!!),因为我可以真正使用一些更多关于利弊/选项的扩展讨论.如果有人能给我一个非常可靠的例子说明他们采取了哪种方法以及为什么它值得+250,那么我会放弃给那些有建设性的东西的人投票.

我真的很痛苦我的应用程序的这方面的设计,现在是时候实现它.在此先感谢任何有益的讨论!!


最后注意:

谢谢大家的深思熟虑和有趣的答案,所有这些都很好,对我很有帮助.最后(在赏金到期之前就来了!)我非常感谢Blackbird07的回答.虽然每个人都提出了很好的建议,但就我个人来说,他是最有用的.我之前并没有真正意识到枚举的想法,因此我发现它解决了我在应用程序中遇到的许多问题.我会鼓励发现这个问题的每个人阅读所有的答案,提供了许多好的方法.

edg*_*ner 23

我假设您将拥有多个这些多选属性,并希望保持整洁.

只有当你想在运行时修改选择时,我才建议将它存储在数据库方法中,否则它很快就会成为性能损失; 如果模型具有三个这样的属性,则需要四个数据库调用而不是一个来进行检索.

将选择硬编码到验证中是一种快速的方法,但维护变得乏味.您必须确保每个类似的验证器和下拉列表等使用匹配值.如果列表变长,它变得相当困难和麻烦.只有2-5个选项确实不会发生太大变化,例如,这是唯一可行的male, female, unspecified

建议您使用配置YAML文件.这样,您可以为所有选择提供一个整洁的文档

# config/choices.yml

morality:
  - Good
  - Evil
genre:
  - Action
  - Suspense
  - Western
hair_color:
  - Blond
  - Brown
  - Black
Run Code Online (Sandbox Code Playgroud)

然后你可以将这个文件加载到一个常量中 Hash

# config/initializers/load_choices.rb

Choices = YAML.load_file("#{Rails.root}/config/choices.yml")
Run Code Online (Sandbox Code Playgroud)

在你的模特中使用它;

# app/models/character.rb

class Character < ActiveRecord::Base
  validates_inclusion_of :morality, in: Choices['morality']
  validates_inclusion_of :genre, in: Choices['genre']
  # etc…
end
Run Code Online (Sandbox Code Playgroud)

在视图中使用它们;

<%= select @character, :genre, Choices['genre'] %>
Run Code Online (Sandbox Code Playgroud)

等等…


emr*_*ass 11

简而言之,您正在询问如何枚举ActiveRecord属性.在网络上有很多讨论,甚至在SO上都有关于在rails应用程序中使用枚举的讨论,例如这里,这里这里仅举几个例子.

我从来没有使用过许多宝石中的一个用于枚举,active_enum宝石听起来特别适合你的用例.它没有activerecord支持的属性集的缺点,并使属性值的维护变得轻而易举.它甚至还带有用于formtastic或简单形式的表单助手(我假设它可以帮助你在角色搜索中进行属性选择).