我确信这与我对Ruby内部的缺乏理解有关,但是这里有:
基本上我希望能够在我的资产文件夹中设置一个'附件目录',只需在模型顶部附近调用has_attachments_folder "videos"
即可。不要担心方法的目的是什么,我有一部分工作。以下示例用法。
class Video < ActiveRecord::Base
has_attachment_assets_folder "videos"
end
class Email < ActiveRecord::Base
has_attachment_assets_folder "attachments/email"
end
def self.has_attachment_assets_folder(physical_path, arguments={})
ActiveRecord::Base.send :define_method, :global_assets_path do |args={}|
# Default to using the absolute system file path unless the argument
# :asset_path => true is supplied
p = "#{ Rails.root }/app/assets/#{ physical_path }"
if args[:asset_path]
p = "/assets/#{ physical_path.include?("/") ? physical_path.partition("/")[2..-1].join("/") : physical_path }"
end
p.squeeze!("/")
logger.info "Defining global_assets_path...class name: #{ self.class.name }, physical_path: #{ physical_path }, p: #{ p }"
p
end
end
基本上,global_assets_path方法应该返回调用has_attachment_assets_folder
指定的附件目录的完整或相对路径。
has_attachment_assets_folder "videos", :asset_path => true
= "/assets/videos"
has_attachment_assets_folder "attachments/email", :asset_path => true
= "/assets/attachments/email"
问题是,如果我在Rails应用程序的常规上下文中使用它(一次访问一个模型),它可以正常工作。但是我正在运行一个主要的迁移,它要求我在迁移文件中一次使用多个模型。似乎每个模型都共享方法global_assets_path
,因为会发生以下情况:
Email.all.each do |e|
puts e.global_assets_path(:asset_path => true) # Correct output of "/assets/attachments/email"
end
Video.all.each do |v|
puts v.global_assets_path(:asset_path => true) # Correct output of "/assets/video"
end
test = Video.pluck(:category)
Email.all.each do |e|
puts e.global_assets_path(:asset_path => true) # Correct output of "/assets/attachments/email"
end
Video.all.each do |v|
puts v.global_assets_path(:asset_path => true) # Incorrect output of "/assets/attachments/email" because the Video model was instantiated for the first time on the 1st line.
end
答案 0 :(得分:0)
你在错误的事情上打电话给define_method
。这样:
ActiveRecord::Base.send :define_method, :global_assets_path
正在向define_method
发送ActiveRecord::Base
,以便将global_assets_path
方法添加到ActiveRecord::Base
。当你这样说:
class Email < ActiveRecord::Base
has_attachment_assets_folder "attachments/email"
end
您希望将global_assets_path
方法添加到Email
,而不是ActiveRecord::Base
。在self
电话中Email
将has_attachment_assets_folder
,因此您想说:
def self.has_attachment_assets_folder(physical_path, arguments = {})
define_method :global_assets_path do |args={}|
...
end
end
在global_assets_path
(self
子类)上定义ActiveRecord::Base
并单独留下ActiveRecord::Base
。