[英]ruby object array… or hash
I have an object now: 我现在有一个对象:
class Items
attr_accessor :item_id, :name, :description, :rating
def initialize(options = {})
options.each {
|k,v|
self.send( "#{k.to_s}=".intern, v)
}
end
end
I have it being assigned as individual objects into an array... 我把它作为单个对象分配到一个数组中......
@result = []
some loop>>
@result << Items.new(options[:name] => 'name', options[:description] => 'blah')
end loop>>
But instead of assigning my singular object to an array... how could I make the object itself a collection? 但不是将我的单个对象分配给数组......我怎样才能使对象本身成为一个集合?
Basically want to have the object in such a way so that I can define methods such as 基本上想要以这样的方式拥有对象,以便我可以定义诸如的方法
def self.names
@items.each do |item|
item.name
end
end
I hope that makes sense, possibly I am overlooking some grand scheme that would make my life infinitely easier in 2 lines. 我希望这是有道理的,可能我忽视了一些宏伟的计划,这将使我的生活在两行中变得无比轻松。
A few observations before I post an example of how to rework that. 在我发布一个如何重做的例子之前的一些观察。
One way to approach your problem is to make a custom collection class specifically for Item objects where it can give you the information you need on names and such. 解决问题的一种方法是专门为Item对象创建一个自定义集合类,它可以为您提供名称等所需的信息。 For example: 例如:
class Item
attr_accessor :item_id, :name, :description, :rating
def initialize(options = { })
options.each do |k,v|
method = :"#{k}="
# Check that the method call is valid before making it
if (respond_to?(method))
self.send(method, v)
else
# If not, produce a meaningful error
raise "Unknown attribute #{k}"
end
end
end
end
class ItemsCollection < Array
# This collection does everything an Array does, plus
# you can add utility methods like names.
def names
collect do |i|
i.name
end
end
end
# Example
# Create a custom collection
items = ItemsCollection.new
# Build a few basic examples
[
{
:item_id => 1,
:name => 'Fastball',
:description => 'Faster than a slowball',
:rating => 2
},
{
:item_id => 2,
:name => 'Jack of Nines',
:description => 'Hypothetical playing card',
:rating => 3
},
{
:item_id => 3,
:name => 'Ruby Book',
:description => 'A book made entirely of precious gems',
:rating => 1
}
].each do |example|
items << Item.new(example)
end
puts items.names.join(', ')
# => Fastball, Jack of Nines, Ruby Book
Do you know the Ruby key word yield ? 你知道Ruby关键词的产量吗?
I'm not quite sure what exactly you want to do. 我不太确定你到底想做什么。 I have two interpretations of your intentions, so I give an example that makes two completely different things, one of them hopefully answering your question: 我对你的意图有两种解释,所以我给出了一个例子,它使两个完全不同的东西,其中一个希望回答你的问题:
class Items
@items = []
class << self
attr_accessor :items
end
attr_accessor :name, :description
def self.each(&args)
@items.each(&args)
end
def initialize(name, description)
@name, @description = name, description
Items.items << self
end
def each(&block)
yield name
yield description
end
end
a = Items.new('mug', 'a big cup')
b = Items.new('cup', 'a small mug')
Items.each {|x| puts x.name}
puts
a.each {|x| puts x}
This outputs 这输出
mug
cup
mug
a big cup
Did you ask for something like Items.each or a.each or for something completely different? 您是否要求像Items.each或a.each这样的东西或者完全不同的东西?
Answering just the additional question you asked in your comment to tadman's solution: If you replace in tadman's code the definition of the method names in the class ItemsCollection by 回答你在评论中对tadman解决方案提出的其他问题:如果你在tadman的代码中替换了类ItemsCollection中方法名称的定义
def method_missing(symbol_s, *arguments)
symbol, s = symbol_s.to_s[0..-2], symbol_s.to_s[-1..-1]
if s == 's' and arguments.empty?
select do |i|
i.respond_to?(symbol) && i.instance_variables.include?("@#{symbol}")
end.map {|i| i.send(symbol)}
else
super
end
end
For his example data you will get following outputs: 对于他的示例数据,您将获得以下输出:
puts items.names.join(', ')
# => Fastball, Jack of Nines, Ruby Book
puts items.descriptions.join(', ')
# => Faster than a slowball, Hypothetical playing card, A book made entirely of precious gems
As I don't know about any way to check if a method name comes from an attribute or from another method (except you redefine attr_accessor, attr, etc in the class Module) I added some sanity checks: I test if the corresponding method and an instance variable of this name exist. 因为我不知道有什么方法来检查一个方法名是来自一个属性还是来自另一个方法(除了你在类Module中重新定义attr_accessor,attr等)我添加了一些健全性检查:我测试是否相应的方法和存在此名称的实例变量。 As the class ItemsCollection does not enforce that only objects of class Item are added, I select only the elements fulfilling both checks. 由于类ItemsCollection不强制只添加类Item的对象,因此我只选择满足两个检查的元素。 You can also remove the select and put the test into the map and return nil if the checks fail. 您还可以删除选择并将测试放入地图中,如果检查失败,则返回nil。
The key is the return value. 关键是返回值。 If not 'return' statement is given, the result of the last statement is returned. 如果没有给出'return'语句,则返回最后一个语句的结果。 You last statement returns a Hash. 你最后一个语句返回一个哈希。
Add 'return self' as the last line of initialize and you're golden. 添加'return self'作为初始化的最后一行,你就是黄金。
Class Item
def initialize(options = {})
## Do all kinds of stuff.
return self
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.