2016-08-24 3 views
0

내 프로젝트 모델의 객체 컬렉션을 유지하기 위해 Collection이라는 인터페이스를 만들었습니다. 나는이 컬렉션과 배열을 다른 필드가 원하는대로 Collection 있습니다.Ruby 인터페이스, 객체 컬렉션

module Collection 
     def self.included(klass) 
     klass.attr_writer :list, type: Array 
     klass.attr_writer :class_type, type: Class 
     # Other fields go in here, along with their validations 
     klass.validate :validate_list 

     def validate_list 
      self.list.each { |o| 
      if(!o.instance_of? self.class_type) 
       klass.errors.add :list, 'Objects in list must be of the same type' 
       return 
      end 
      } 
     end 
     end 
    end 

나는 회사의 물체가 떨어져 다른 목록에서 내가 미래에 포트폴리오 모델에 추가합니다 :: 모델의 목록을 유지하기 위해이 Collection을 사용하고 싶습니다. 이 회사 목록은 포트폴리오 모델의 일부일뿐입니다.

class Portfolio 
    include Model::Collection 

    @schema = { 
     'type' => 'object', 
     'properties' => { 
      'id'      => { 'type' => 'string' }, 
      'title'     => { 'type' => 'string' }, 
      'description'    => { 'type' => 'string' }, 
      'companies_list'   => {'type' => '?'}, # 1. Should this be array or Collections? 
     } 
    } 
    @modelName  = 'portfolios' 
    @collectionName = 'portfolios' 


    store_in collection: 'portfolios' 

    field :title,      type: String 
    field :description,    type: String 
    field :companies_list,   type: Array # 2. Should this be array or array of Collections? 

    embeds_many :companies 

end 

도움을 주시면 감사하겠습니다.

+0

모듈에서 "초록"이라는 용어를 사용하면 실제로 사람들을 혼란스럽게합니다. 루비는 추상적 인 기본 클래스를 표현하기위한 표준 방법이 없기 때문에 루비는이 용어를 전혀 사용하지 않지만 구체적인 의미를 가지며 클래스와 관련이 있습니다. 또한 문제가 무엇인지 분명하지 않습니다. – tadman

+0

@tadman : 죄송합니다. 클래스로 변경해야합니까? – chipmunk

+0

아니요, 믹스 인 모듈이라고해도 괜찮습니다. 그러나 "초록"이라고 부르는 것은 잘못된 것입니다. 왜 그것을'Model :: CollectionMethods' 또는'Model :: CollectionValidations' 또는 이와 비슷한 이름으로 부르지 않습니까? – tadman

답변

2

나는 자바 세상에서 온 것을 보았고, 자바의 제네릭을 루비로 가져 오기를 원한다고 생각한다. 하지만, Java가 generics를 사용하는 이유는 무엇입니까? 역사 교훈을 얻도록하겠습니다.

List list = new ArrayList(); 
// add some strings to the list 
list.add("foo"); 
list.add("bar"); 

// we have to iterate over each element as an Object 
for (Object obj : list) { 
    // and then cast it to String 
    String str = (String) obj; 
    // in order to call String methods on it. 
    String uppercased = str.toUpperCase(); 

    // ... 
} 

이 확실히 DRY되지 않습니다 : 프로그래머는 다음과 같이 코드를 작성해야하므로

초기 자바 (1.5 이전), 더 일반적인 유형이 없습니다. 주조의 고통을 덜어주기 위해 Java 1.5에서는 제네릭을 소개합니다.

List<String> list = new ArrayList<String>(); 
// add some strings to the list 
list.add("foo"); 
list.add("bar"); 

// now we can iterate over the elements as strings 
for (String str : list) { 
    // no more casting, yay! 
    String uppercased = str.toUpperCase(); 

    // ... 
} 

하지만 제네릭이 아닌 버전은 어디에서 잘못 될까요?

Java에서 변수 유형은 개체 자체가 아니라 개체에서 호출 할 수있는 메서드를 결정합니다. 변수를보다 일반적인 유형 (예 : 수퍼 클래스)으로 선언하면 더 특수한 유형 (즉, 서브 클래스)에 속한 메소드를 호출 할 수 없습니다. 이러한 메서드를 호출하려면 캐스팅해야합니다.

하지만 개체 자체에서 호출 할 수있는 메서드를 결정할 수 있다면 어떻게 될까요? 갑자기 제네릭이 쓸모 없게됩니다. Ruby와 많은 다른 동적 언어들이이 방법을 따릅니다. 루비스트는 그것을 이라고 부르고, 오리는이라고 부른다. 오리와 같이 걷고 무언가 오리처럼 엎어지면 오리 다.

list = ['foo', 'bar'] 
list.each do |str| 
    # we don't care what type str is, 
    # as long as it has the method upcase. 
    str.upcase if str.respond_to?(:upcase) 
end 

그래서 루비스트는 일반적으로 컨테이너 클래스를 정의하지 않고 배열을 사용합니다. 형식 제한을 적용해야하는 경우 개체를 배열에 추가 할 때 형식 제한이 적용됩니다.

list = [] 
list << something if something.is_a? Portfolio 

배열에 충실하는 또 다른 이유는 배열은 사용자 정의 컨테이너 유형이없는 ['foo', 'bar']%w(foo bar)%i(foo bar) 같은 멋진 리터럴을 가지고있다.

+0

많은 개념을 정리하는 데 도움이되었습니다. – chipmunk