目前,如果我想将一个方法应用于一组ActiveRecord对象,我必须像这样构建调用:
messages = Message.find(:all)
csv = Message.to_csv(messages)
如何定义方法,使其结构如此?
messages = Message.find(:all)
csv = messages.to_csv
这是当前的型号代码:
require 'fastercsv'
class Message < ActiveRecord::Base
def Message.to_csv(messages)
FasterCSV.generate do |csv|
csv << ["from","to", "received"]
for m in messages
csv << [m.from,m.to,m.created_at]
end
end
end
end
答案 0 :(得分:6)
以下内容将在messages数组中包含的所有实例上调用to_csv。
messages = Message.find(:all)
csv = messages.map { |message| message.to_csv }
在Rails中,在Ruby 1.9中或通过其他方式使用Symbol#to_proc,您还可以将其缩短为:
csv = messages.map(&:to_csv)
当您想要进行更复杂的操作时,较长的形式很有用:
csv = messages.map { |message|
if message.length < 1000
message.to_csv
else
"Too long"
end
}
答案 1 :(得分:3)
将其放入 lib / 中的文件中。我建议将其称为base_ext.rb
require 'fastercsv'
class ActiveRecord::Base
def self.to_csv(objects, skip_attributes=[])
FasterCSV.generate do |csv|
csv << attribute_names - skip_attributes
objects.each do |object|
csv << (attribute_names - skip_attributes).map { |a| "'#{object.attributes[a]}'" }.join(", ")
end
end
end
end
之后,转到 config / environment.rb 并将require 'base_ext'
放在文件的底部以包含新扩展名。重新启动服务器后,您应该可以访问所有模型类的to_csv
方法,当您传递它时,一组对象应该为您生成一个漂亮的CSV格式。
答案 2 :(得分:2)
FasterCSV修补了Array类并且已经为它添加了'to_csv'方法,但它没有做你想要的。您可以通过执行以下操作来自己覆盖它:
class Array
def to_csv(options = Hash.new)
collect { |item| item.to_csv }.join "\n"
end
end
或者那些东西,但那有点糟糕。
老实说,作为模型上的类方法,它更有意义。
答案 3 :(得分:0)
您可以在Message类上创建一个方法来执行......
在你的控制器......
@csv_file = Message.send_all_to_csv
在你的模特中......
require 'fastercsv'
class Message < ActiveRecord::Base
def send_all_to_csv
@messages = Find.all
FasterCSV.generate do |csv|
csv << ["from","to", "received"]
for message in @messages
csv << [message.from,message.to,message.created_at]
end
end
# do something with your csv object (return it to the controller
# or pass it on to another class method
end
end
答案 4 :(得分:0)
您可以直接在messages
对象本身上定义方法,但是如果您这样做,该方法只能用于该特定实例:
def messages.to_csv()
FasterCSV.generate do |csv|
csv << ["from", "to", "received"]
self.each { |m| csv << [m.from, m.to, m.created_at] }
end
end
然后你可以这样称呼它:
messages.to_csv
我是一个Ruby新手,所以我不确定这是否是惯用的Ruby:也就是说,我不确定直接在对象实例上定义新方法有多普遍或被接受,我只知道这是可能的; - )
答案 5 :(得分:0)
如果它被隔离到一个AR模型,我会添加一个to_custom_csv_array实例方法
def to_custom_csv_array
[self.from,self.to,self.created_at]
end
然后覆盖类
上的finddef self.find(*args)
collection = super
collection.extend(CustomToCSV) if collection.is_a?(Array)
end
并在CustomToCSV中定义to_custom_csv以生成csv
module CustomToCSV
def to_custom_csv
FasterCSV.generate do |csv|
csv << ["from","to", "received"]
csv << self.map {|obj| obj.to_custom_csv_array}
end
end
end
这是来自记忆但应该有用。
答案 6 :(得分:0)
我知道这是一个非常古老的问题,但只是想提供反馈意见。 查看博客http://blog.zahiduzzaman.com/2013/07/adding-tocsv-method-to-active-record.html 只是实现这个的另一种方式