0

所以在我的 Rails 应用程序中,我正在创建一个用户表,在该表中我有诸如“电子邮件、密码和图像”之类的列。我想添加一个用户可以关联的具体国籍列表。

所以,我创建了一个用户模型: rails g model 用户邮箱密码 image:string

现在我想要一个国籍数组......所以我没有创建一个数组,而是为国籍创建了一个单独的模型,并希望将它与我的用户相关联。假设一个人可以有多个国籍,我这样设置:

rails g model 国籍名称:字符串

所以在 user.rb 我写道: has_many :nationalities

在nationality.rb中我写道:belongs_to :user

当用户注册时,我将有一个列表供他们选择:美国、加拿大、法国等...我的直觉告诉我这可能是一种反模式,因为用户永远不会在列表中添加新国籍...仅选择,但管理员始终可以添加更多国籍。

我没有收到任何错误,但它也对我不利。我是否正确设置了它,还是应该只使用一个数组并将其存储在用户表中名为“国籍”的列下?

4

3 回答 3

0

这实际上更像是一个数据库设计问题,而不是 Rails 问题,但我只是将Nationality表用作下拉列表的源,但User表只是有一个nationality列。我认为不需要额外的加入。当然,nationality列中的值将来自用户从Nationality表格填充的下拉列表中的选择。

不过,您的需求可能会有所不同。如果需要多个国籍,请坚持加入。正如Knuth所说,“过早的优化是万恶之源。”

于 2013-10-13T00:20:42.953 回答
0

你在使用 Rails 4 吗?Postgresql 是您的数据库吗?如果是这样,此组合允许您在用户模型上存储数组。

基本上你会修改你的迁移看起来像这样:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name # or whatever attributes you've already defined

      t.string :nationalities, array: true, default: []
      t.timestamps
    end
  end
end

您的 ActiveRecord 模型将包含以下内容:

class User < ActiveRecord::Base
  attr_accessible :nationalities
end

这将允许您像这样创建国籍列表:

user = User.create(name: 'Bob', nationalities: ['English', 'Australian', 'French'])

并且显然像这样提取它们:

user.nationalities
=> ['English', 'Australian', 'French']

尽管如此,关于在用户上建立关联或列的决定超出了在表单中创建具有国籍的用户的难易程度。真正的问题是“国籍将在应用程序中扮演什么角色”?意思是,国籍是否有其他数据可以保证它是自己的模型?或者,可以全部放在用户表中吗?

如果国籍具有与用户名一样多的功能,则它可以保留在用户身上。但是,如果国籍可以具有其他属性,例如“date_aquired”,则它可能必须是它自己的模型。

于 2013-10-13T00:39:10.157 回答
0

编辑:哎呀,我没有解决拥有多个国籍的部分。您可能要考虑使用acts_as_taggable_on

https://github.com/mbleigh/acts-as-taggable-on

它很好地处理了带有一些内置便利的标记的多对多行为。

我认为现在对 Nationalities 使用某种全局数组(在命名空间中)很好,因为正如您正确指出的那样,Nationalities 的类型不会改变。

但是,我认为事情会比直接数组复杂一点...您说您会给出诸如American, Canadian, French...之类的选择,这很好,但是如果视图的上下文需要使用U.S., Canada, France呢?然后你的 Array 变成了一个 Hash...我怀疑它会变得复杂到需要一个完整的 Rails 模型。一个简单的哈希应该涵盖大多数这些用例。

我发现在这种情况下创建一个单独的类或模块很有帮助。例如,对于 Gender,绝对不值得创建一个单独的数据库表……然而,即使我在用户gender列中存储的所有内容都是“M”、“F”、“O”(对于其他,或者可能不是指定),我将创建一个Gender可以处理该域逻辑的模块:

class Gender

   # better to make this private so that
   # only the factory constructor is exposed 
   def initialize(g)
     @g = g 
   end 

   def to_s  # and equivalent methods for serializing Gender into a M/F for database 
     return @g.to_s
   end 

   def pronoun 
     case @g
     when :M
       'he' 
     when :F
       'she'
     else
       'they'
   end 

end

def Gender(str) 
    case str
    when /^(?:m|male|man|boy)$/i
     Gender.new(:M)
    when /^(?:f|female|woman|girl)$/i
     Gender.new(:F)
    else 
     Gender.new(:O)
    end 
end
于 2013-10-13T00:40:01.317 回答