2013-09-24 1 views
0

:루비 클래스 I 루비의 비 데이터베이스 기반 클래스가

나는 국가가 단순히 ISO 국가 코드 (US, GB, CA, AU 등)의 배열 할
class User 
    attr_accessor :countries 
end 

나는 각각을 보유 할 분리 된 모델을 만들고 싶지 않다. :countries이 배열이고 그에 따라 처리한다는 Ruby의 이해를 돕는 마법의 방법이 있습니까? 아니면 countriescountries= 메서드를 작성해야합니까?

나는 국가 배열을 user.countries = [ 'US']로 설정하려고했지만 NoMethodError가 발생했습니다.

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가 수정 방지 :

+5

접근 자입니다. 그것은 * 유형 *이 중요하지 않습니다. –

+0

'attr_accessor'를 사용하면'countries'와'countries =':)를 무료로 얻을 수 있습니다 :) –

+0

클래스는'user.countries = [: gb , : au]'? – Gareth

답변

3

유형의 다음 users 테이블처럼 보이는 Ruby에서는 변수가 중요하지 않습니다.

attr_accessor은 인스턴스 변수를 설정하고 반환하는 getter 및 setter 메서드를 만듭니다. 이 경우 @countries. 당신은 당신의 배열에 인스턴스 변수를 설정하거나 세터 사용할 수 있습니다 : 나는 self.xxx 대신 인스턴스 변수를 사용하여 선호 개인적으로

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. 비트를 잊어 버리기가 너무 쉽고 로컬 변수를 설정하고 인스턴스 변수 nil을 남겨 둡니다. 나는 또한 추악하다고 생각한다.

국가간에 인스턴스가 변경되지 않는 이유는 무엇입니까?

편집은/해명

Tadman의 포인트는, this diatribe on state는, 예를 들어, 잘 촬영됩니다. 내가 신경 쓰지 않는 상황은 작고 자제력이 있고 독립된 수업으로 제한됩니다. 그러한 가정을 할 때 내재 된 위험이 있으며, 그러한 위험의 수준은 프로젝트에 따라 다릅니다.

+0

'attr_accessor'를 가질 때 인스턴스 변수를 사용하면 getter 또는 setter 메소드 중 하나를 재정의 한 경우 일부 슬립이 발생할 수 있습니다. 'this'가 절대적으로 필요한 자바 스크립트를 많이한다면,'self'를 추가하는 것에 대해 훈련받는 것은 큰 문제가 아닙니다. – tadman

+0

@ tadman 수정. 만약 당신이'attr_accessor'를 사용하고 있고 다른 것을 오버라이드한다면, 당신이 잘못하고 있다고 말할 수 있습니다. IMO'attr_accessor'는 다른 논리를 수행하는 메소드가 아니라 접근 자임을 전달합니다. –

+0

글쎄, 그것은 서브 클래스에서는 무시 될 수 있지만 부모 클래스에서는 오버라이드 될 수 있습니다. 가정을하는 것은 위험합니다. 어떤 종류의 접근자를 선언하는 경우 인스턴스 변수가 * 아마 * 같다하더라도 사용하는 것이 좋습니다. – tadman

3

은 일정해야 countries 것 같은데

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

업데이트를

여기서 문제는 국가의 배열이 어떻게 든 유지해야한다는 것이다 . has_many을 언급하고 있으므로 Rails가 관련되어있는 것 같습니다. 그래서,

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

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

이가 내부적으로 YAML에서 변환됩니다 :이 객체로 데이터베이스에 countries 속성을 저장하고 등을 검색합니다

class User < ActiveRecord::Base 
    serialize :countries 
end 

: 당신은 ActiveRecordserialize 방법을 사용할 수 있습니다

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) 
+1

클래스 메소드가이를 마무리 할 수도있다 :'def self.countries; 국가; 끝 '. 이것은 무의미한 것처럼 보일 수 있지만 필요할 경우 하위 클래스가 해당 메서드를 재정의하고 배열에 액세스해야하는 코드의 다른 부분에이 상수의 구조가 노출되는 것을 방지합니다. – tadman

+0

위의 주석을 참조하십시오. 사용자는 실제로 전체 ISO 코드 목록의 하위 집합에 대한 소유권을 가져야합니다. Has_many는 내 응용 프로그램에 과도 함입니다. –

+0

@kid_drew 답변을 업데이트했습니다. – Stefan