2

我在 Ruby 中有一个非数据库支持的类:

class User
  attr_accessor :countries
end

我希望国家/地区只是一系列 ISO 国家/地区代码(美国、英国、加拿大、澳大利亚等),我不想建立一个单独的模型来保存每个国家/地区代码。有没有一种神奇的方法可以让 Ruby 理解它:countries是一个数组并相应地对待它,还是我需要编写countriesandcountries=方法?

我尝试使用 user.countries = ['US'] 设置国家/地区数组,但我得到了 NoMethodError。

4

2 回答 2

6

在 Ruby 中,变量的类型并不重要。

attr_accessor只创建设置和返回实例变量的 getter 和 setter 方法;@countries在这种情况下。您可以将实例变量设置为数组,或使用 setter:

class User
  attr_accessor :countries

  def initialize
    @countries = %w[Foo Bar Baz]
    # Or...
    self.countries = %w[Foo Bar Baz]
  end
end

> puts User.new.countries
=> ["Foo", "Bar", "Baz"]

我个人更喜欢使用实例变量而不是self.xxx; 这太容易忘记了self.,你最终设置了一个局部变量,留下了实例变量nil。我也觉得丑

如果这些国家不会在实例之间发生变化,为什么不是一个常数?

编辑/澄清

Tadman 的观点得到了很好的理解,例如,这种对 state 的谩骂。我不关心的情况仅限于小型的、自我控制的、独立的班级。做出这些假设存在固有风险,这些风险的水平取决于项目。

于 2013-09-24T15:52:13.427 回答
4

看起来countries应该是一个常数:

class User
  COUNTRIES = %w(
    AF AX AL DZ AS AD AO AI AQ AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM
    BT BO BQ BA BW BV BR IO BN BG BF BI KH CM CA CV KY CF TD CL CN CX CC CO KM
    CG CD CK CR CI HR CU CW CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI
    FR GF PF TF GA GM GE DE GH GI GR GL GD GP GU GT GG GN GW GY HT HM VA HN HK
    HU IS IN ID IR IQ IE IM IL IT JM JP JE JO KZ KE KI KP KR KW KG LA LV LB LS
    LR LY LI LT LU MO MK MG MW MY MV ML MT MH MQ MR MU YT MX FM MD MC MN ME MS
    MA MZ MM NA NR NP NL NC NZ NI NE NG NU NF MP NO OM PK PW PS PA PG PY PE PH
    PN PL PT PR QA RE RO RU RW BL SH KN LC MF PM VC WS SM ST SA SN RS SC SL SG
    SX SK SI SB SO ZA GS SS ES LK SD SR SJ SZ SE CH SY TW TJ TZ TH TL TG TK TO
    TT TN TR TM TC TV UG UA AE GB US UM UY UZ VU VE VN VG VI WF EH YE ZM ZW
  ).freeze
end

User::COUNTRIES.include? "US" #=> true

freeze防止修改:

User::COUNTRIES.delete "US"   #=> RuntimeError: can't modify frozen Array

更新

这里的问题是您的国家/地区数组必须以某种方式持续存在。您提到has_many的是 Rails 似乎参与其中。您可以使用ActiveRecord'sserialize方法:

class User < ActiveRecord::Base
  serialize :countries
end

这会将countries属性作为对象保存到数据库并按如下方式检索它:

u = User.new
u.countries = ["US", "CA"]
u.save

u = User.last
u.countries
#=> ["US", "CA"]

它在内部与 YAML 相互转换,因此该users表如下所示:

mysql> SELECT * FROM users;
+----+-------------------+---------------------+---------------------+
| id | countries         | created_at          | updated_at          |
+----+-------------------+---------------------+---------------------+
|  1 | ---\n- US\n- CA\n | 2013-09-24 18:24:03 | 2013-09-24 18:24:03 |
+----+-------------------+---------------------+---------------------+
1 row in set (0,00 sec)
于 2013-09-24T15:52:12.343 回答