首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Rails模型:您将如何创建一组预定义的属性?

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

Stack Overflow用户
提问于 2011-06-30 14:40:42
回答 5查看 9.2K关注 0票数 39

我试图找出设计rails模型的最佳方法。就示例而言,假设我正在构建一个字符数据库,该数据库可能有几个不同的固定属性。例如:

代码语言:javascript
运行
复制
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的回答。虽然每个人都提出了很好的建议,但对我个人来说,他的建议是最有用的。我以前并没有真正意识到枚举的概念,自从研究它之后,我发现它解决了我在应用程序中遇到的许多问题。我鼓励每一个发现这个问题的人阅读所有的答案,有很多很好的方法。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-07-20 18:53:06

简单地说,您是在问如何枚举ActiveRecord属性。关于在rails应用程序中使用枚举,有很多关于网络的讨论,例如这里这里这里等等。

我从未使用过许多用于枚举的宝石,,但是 活动的 听起来特别适合您的用例。它没有activerecord支持的属性集的缺点,因此对属性值的维护是小菜一碟。它甚至还附带表单帮助器,用于表单或简单表单(我认为它可以帮助您在字符搜索中进行属性选择)。

票数 11
EN

Stack Overflow用户

发布于 2011-07-14 18:52:19

我假设您将拥有更多的这些多选项属性,并希望保持整洁。

我建议将其存储在数据库 approach 中,如果您希望在运行时修改选择,则只使用,否则会很快影响性能;如果模型有三个这样的属性,则需要四个数据库调用,而不是一个。

将选项硬编码为验证是一种快速的方法,但它变成了乏味的来维护。您必须确保每个类似的验证器和下拉列表等都使用匹配值。如果列表变得很长,就会变得非常困难和麻烦。只有当你有2-5个真正不会改变的选择的时候,才是实用的,比如male, female, unspecified

推荐的是使用配置的YAML文件。这样,您就可以拥有一个整洁的文档供您选择。

代码语言:javascript
运行
复制
# config/choices.yml

morality:
  - Good
  - Evil
genre:
  - Action
  - Suspense
  - Western
hair_color:
  - Blond
  - Brown
  - Black

然后,您可以将该文件作为Hash加载到常量中。

代码语言:javascript
运行
复制
# config/initializers/load_choices.rb

Choices = YAML.load_file("#{Rails.root}/config/choices.yml")

在你的模型中使用它;

代码语言:javascript
运行
复制
# app/models/character.rb

class Character < ActiveRecord::Base
  validates_inclusion_of :morality, in: Choices['morality']
  validates_inclusion_of :genre, in: Choices['genre']
  # etc…
end

在视图中使用它们;

代码语言:javascript
运行
复制
<%= select @character, :genre, Choices['genre'] %>

etc…

票数 25
EN

Stack Overflow用户

发布于 2011-06-30 15:14:31

如果这些属性中的任何一个更改都与代码中的更改紧密关联(即:当引入新的头发颜色时,将创建一个新的页面或实现一个新的操作),那么我会将它们添加为字符串哈希(选项1)。您可以将它们存储在字符模型中,作为与其他元数据的最终散列。

代码语言:javascript
运行
复制
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'}, ...

代码语言:javascript
运行
复制
- 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]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6536527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档