如何动态确定carrierwave上传器列名?

时间:2017-01-25 22:58:22

标签: ruby-on-rails carrierwave

我有一些元编程将多个直接S3上传进程压缩到一个控制器中。然后,这些操作在许多模型中共享。为了实现这一点,在许多其他细节中,我需要知道给定模型上传器的列名。我通过提供一个' uploader_name'来促进这一点。我的每个模型中使用共享操作的方法。例如,我有一个Expense模型,它有一个收据上传...

def uploader_name
  'receipt'
end 

mount_uploader :receipt, ReceiptUploader

所以,现在我可以调用Expense.new.uploader_name来返回一个字符串,或者在共享操作中我会使用@ obj.send(@ obj.uploader_name)来获取上传者对象(其中@obj是任何一个使用共享动作的附属模型)。这很好用。但是,我想我可以清理它。一种有助于我重构的方法是不需要uploader_name方法。或者,能够在共享模块中使用单个uploader_name方法,该方法能够动态确定上传者的列名。

Carrierwave中是否有方法可以在模型上传器上访问列名,而不知道上传器的名称是什么?由于模块是在多个类之间共享的,我必须动态地解决它 - 我已经读过了载波,但没有找到解决方案。

像这样......例如:

obj = self.class.name
obj.new.uploader # would return the mounted :receipts uploader
obj.new.uploader_column # would return the uploader column, in this case :receipt

2 个答案:

答案 0 :(得分:1)

上传者类提供了一些方法。因此,为了解决这个问题,我只需将上传者的:mounted_as方法委托给调用它的类。然后,在不知道实际上传者的名字的情况下,我可以调用self.mounted_as.to_s来返回上传者的名字。

因此,对于具有头像上传者的用户模型,我会这样做。

class User    
  mount_uploader :avatar, AvatarUploader
  delegate :mounted_as, to: :avatar

所以,如果我打电话给@ user.mounted_as,我会得到:头像。或者,更重要的是......如果我打电话给self.mounted,我会得到:当自己是用户时的头像。我有一个模块,在使用上传器的所有模型之间共享。在那个模块中,我包括

def uploader_name
  self.mounted_as.to_s
end

现在,我可以做一些元编程,因为我不知道自己是谁,我不知道自己的上传者是什么。但是,现在我可以动态访问它们。这很有用,因为我可以在使用上传器的多个班级中共享一个上传器控制器和一个上传器表单。

我还可以通过简单地抓取上传者的extension_whitelist方法中的扩展名来执行将接受的扩展名传递给表单输入(请参阅html5接受选项)。

self.send(uploader_name).extension_whitelist
# this is dynamically getting @user.avatar.extension_whitelist
# or @company.logo.extension_whitelist

我还可以使用例如......

设置上传器属性
obj.send(obj.uploader_name).content_type = 'image/jpeg'
# this is dynamically setting @user.avatar.content_type = 'image/jpeg'
# or @company.logo.content_type = 'image/jpeg'

答案 1 :(得分:0)

obj.class.uploaders.keys.first
=> :receipt