2016-08-24 26 views
0

我创建了一个叫做Collection从我的项目模型的所有对象的集合中持有的接口。我想要这个集合vs一个数组,因为我想要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

在模块中使用术语“摘要”真的会让人困惑。这有一个特定的含义,它与类有关,尽管Ruby没有真正使用这个术语,因为没有用于表示抽象基类的标准方法。此外,这里的问题还不清楚。 – tadman

+0

@tadman:对不起,我应该把它改成'class'? – chipmunk

+0

不,我的意思是说这是一个mixin模块,但称它为“抽象”是错误的。为什么不把它称为'Model :: CollectionMethods'或'Model :: CollectionValidations'或类似的东西? – tadman

回答

2

我看到你来自Java世界,我想你想使Java的泛型红宝石。但是,首先,为什么Java有泛型?让我们有一个历史课。

在Java的早期(1.5)之前,没有泛型类型,所以程序员编写代码是这样的:

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(); 

    // ... 
} 

这肯定是不干燥。为了减轻投射的痛苦,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和许多其他动态语言都遵循这种方式。 Rubyists称之为鸭子打字 - 如果某件东西像鸭子一样走路,鸭子像鸭子一样走,它就是一只鸭子。

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 

所以rubyists通常不会定义容器类,它们只是使用数组。如果应用类型限制,则只在将对象添加到数组时应用它。

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

另一个原因坚持阵列是阵列具有真棒文字像['foo', 'bar']%w(foo bar)%i(foo bar),其定制的容器类型没有。

+0

谢谢,这确实有助于清理很多概念! – chipmunk