我试图找出设计rails模型的最佳方法。就示例而言,假设我正在构建一个字符数据库,该数据库可能有几个不同的固定属性。例如:
Character
- Morality (may be "Good" or "Evil")
- Genre (may be "Action", "Suspense", or "Western")
- Hair Color (may be "Blond", "Brown", or "Black")
..。诸若此类。
因此,对于字符模型,有几个属性,我想基本上有一个固定的列表,可能的选择。
我希望用户能够创建一个字符,我希望他们从每个可用选项中选择一个字符。我还想让用户使用这些属性中的每一个进行搜索.(即“给我看那些‘好’的人物,从‘悬疑’类型,并有‘棕色’的头发)。
我可以想出几种方法.
1:为每个属性创建一个字符串并验证有限的输入.
在这种情况下,我将在字符表上定义一个字符串列“道德”,然后有一个带有其中指定的选项的类常量,然后根据该类常量进行验证。
找到好的角色就像Character.where(:morality=>'Good')
一样。
这很好,也很简单,缺点是如果我想给属性添加更多的细节,例如,有一个描述“好”和“邪恶”的页面,以及一个页面,用户可以在该页面中查看给定道德规范的所有字符。
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“等将其子类化。这只为多个属性创建了一个表,否则它似乎与idea #2类似。
所以,这是我能想到的解决这个问题的三种方法。
我的问题是,你将如何实现这一点,为什么?
你会使用上述的方法之一吗?如果是,哪一种?你会做些不同的事吗?我特别想听听您将采用的方法的性能考虑。我知道这是一个广泛的问题,谢谢你的意见。
编辑:,我正在添加250个Bounty (超过我名誉的10%!)在这个问题上,因为我真的需要对利弊/选项进行更深入的讨论。如果有人能给我一个很好的例子,说明他们采取哪种方法,以及为什么它会值+250,我会把它交给任何一个有建设性的人。
我真的在为我的应用程序的这个方面的设计而苦恼,现在是时候实现它了。提前感谢任何有帮助的讨论!!
最后注:
谢谢大家的周到和有趣的回答,所有这些都是好的,并对我很有帮助。最后(在赏金到期之前进来!)我真的很感激布莱克伯德07的回答。虽然每个人都提出了很好的建议,但对我个人来说,他的建议是最有用的。我以前并没有真正意识到枚举的概念,自从研究它之后,我发现它解决了我在应用程序中遇到的许多问题。我鼓励每一个发现这个问题的人阅读所有的答案,有很多很好的方法。
发布于 2011-07-20 10:53:06
发布于 2011-07-14 10:52:19
我假设您将拥有更多的这些多选项属性,并希望保持整洁。
我建议将其存储在数据库 approach 中,如果您希望在运行时修改选择,则只使用,否则会很快影响性能;如果模型有三个这样的属性,则需要四个数据库调用,而不是一个。
将选项硬编码为验证是一种快速的方法,但它变成了乏味的来维护。您必须确保每个类似的验证器和下拉列表等都使用匹配值。如果列表变得很长,就会变得非常困难和麻烦。只有当你有2-5个真正不会改变的选择的时候,才是实用的,比如male, female, unspecified
。
推荐的是使用配置的YAML文件。这样,您就可以拥有一个整洁的文档供您选择。
# config/choices.yml
morality:
- Good
- Evil
genre:
- Action
- Suspense
- Western
hair_color:
- Blond
- Brown
- Black
然后,您可以将该文件作为Hash
加载到常量中。
# config/initializers/load_choices.rb
Choices = YAML.load_file("#{Rails.root}/config/choices.yml")
在你的模型中使用它;
# app/models/character.rb
class Character < ActiveRecord::Base
validates_inclusion_of :morality, in: Choices['morality']
validates_inclusion_of :genre, in: Choices['genre']
# etc…
end
在视图中使用它们;
<%= select @character, :genre, Choices['genre'] %>
etc…
发布于 2011-06-30 07:14:31
如果这些属性中的任何一个更改都与代码中的更改紧密关联(即:当引入新的头发颜色时,将创建一个新的页面或实现一个新的操作),那么我会将它们添加为字符串哈希(选项1)。您可以将它们存储在字符模型中,作为与其他元数据的最终散列。
class Character < ActiveRecord::Base
MORALITY = {:good => ['Good' => 'Person is being good'], :evil => ['Evil' => 'Person is being Evil']}
...
end
Character.where(:morality => Character::MORALITY[:good][0])
编辑以添加注释中的代码:
给定Character::MORALITY = {:good => {:name => 'Good', :icon => 'good.png'}, ...
- Character::MORALITY.each do |k,v|
= check_box_tag('morality', k.to_s)
= image_tag(v[:icon], :title => v[:name])
= Character::MORALITY[@a_character.morality.to_sym][:name]
https://stackoverflow.com/questions/6536527
复制