Ruby 接口,对象集合
Ruby Interface, Collection of Objects
我创建了一个名为 Collection
的接口来保存我项目模型中的任何对象的集合。我想要这个集合与数组,因为我想要 Collection
.
中的其他字段
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
来保存 Models::Company 对象的列表,除了我将来添加到投资组合模型的其他列表。我希望这份公司列表只是投资组合模型的一部分。
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
感谢任何帮助。
我看到你来自Java世界,我猜你想把Java的泛型带到Ruby。但是,首先,为什么 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 和许多其他动态语言都遵循这种方式。 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
所以 rubyists 通常不定义容器 类,他们只是使用数组。如果应该应用类型限制,他们只是在将对象添加到数组时应用它。
list = []
list << something if something.is_a? Portfolio
坚持使用数组的另一个原因是数组具有很棒的文字,如 ['foo', 'bar']
和 %w(foo bar)
和 %i(foo bar)
,自定义容器类型没有。
我创建了一个名为 Collection
的接口来保存我项目模型中的任何对象的集合。我想要这个集合与数组,因为我想要 Collection
.
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
来保存 Models::Company 对象的列表,除了我将来添加到投资组合模型的其他列表。我希望这份公司列表只是投资组合模型的一部分。
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
感谢任何帮助。
我看到你来自Java世界,我猜你想把Java的泛型带到Ruby。但是,首先,为什么 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 和许多其他动态语言都遵循这种方式。 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
所以 rubyists 通常不定义容器 类,他们只是使用数组。如果应该应用类型限制,他们只是在将对象添加到数组时应用它。
list = []
list << something if something.is_a? Portfolio
坚持使用数组的另一个原因是数组具有很棒的文字,如 ['foo', 'bar']
和 %w(foo bar)
和 %i(foo bar)
,自定义容器类型没有。