Ruby on rails Ruby on Rails-回形针和动态参数

Ruby on rails Ruby on Rails-回形针和动态参数,ruby-on-rails,ruby,paperclip,Ruby On Rails,Ruby,Paperclip,我正在用回形针为RubyonRails编写一些图像上传代码,我有一个可行的解决方案,但它非常粗糙,所以我非常感谢关于如何更好地实现它的建议。我有一个“资产”类,包含上传图像的信息,包括回形针附件,还有一个“生成器”类,封装尺寸信息。每个“项目”都有多个资产和发电机;所有资产应根据每个发电机规定的大小调整大小;因此,每个项目都有其所有资产都应该具备的特定规模 发电机型号: class Generator < ActiveRecord::Base attr_accessible :heig

我正在用回形针为RubyonRails编写一些图像上传代码,我有一个可行的解决方案,但它非常粗糙,所以我非常感谢关于如何更好地实现它的建议。我有一个“资产”类,包含上传图像的信息,包括回形针附件,还有一个“生成器”类,封装尺寸信息。每个“项目”都有多个资产和发电机;所有资产应根据每个发电机规定的大小调整大小;因此,每个项目都有其所有资产都应该具备的特定规模

发电机型号:

class Generator < ActiveRecord::Base
  attr_accessible :height, :width

  belongs_to :project

  def sym
    "#{self.width}x#{self.height}".to_sym
  end
end
我遇到的问题是一个鸡蛋问题:新创建的资产在正确实例化之前不知道使用哪个生成器(大小规格)。我试着使用@project.assets.build,但在资产设置其项目关联之前,回形针代码仍然被执行,而我的结果为零

“if@generators==nil”hack是这样的,因此更新方法可以工作,而不需要在控制器中进行进一步的hack

总而言之,感觉很糟糕。有谁能建议如何以一种更合理的方式写这篇文章,或者甚至是一种处理这类事情的方法吗


提前感谢!:)

我在一个项目中遇到了同样的回形针鸡/蛋问题,该项目试图使用基于多态关系关联模型的动态样式。我已根据您现有的代码调整了我的解决方案。解释如下:

class Asset < ActiveRecord::Base
  attr_accessible :image, :deferred_image
  attr_writer :deferred_image

  has_attached_file :image,
    :styles => lambda { |a| a.instance.styles }

  belongs_to :project

  after_save :assign_deferred_image

  def styles
    project.generators.each_with_object({}) { |g, hsh| hsh[g.sym] = "#{g.width}x#{g.height}" }
  end

  private
  def assign_deferred_image
    if @deferred_image
      self.image = @deferred_image
      @deferred_image = nil
      save!
    end
  end
end
以及以下观点:

<%= form_for @asset do |f| %>
  <%# other asset attributes %>
  <%= f.label :deferred_upload %>
  <%= f.file_field :deferred_upload %>
  <%= f.submit %>
<% end %>

与您现有的方法完全相同,但更简洁。

虽然我非常喜欢Cade的解决方案,但只是一个建议。看起来“样式”属于一个项目……那么你为什么不计算那里的生成器呢

例如:

class Asset < ActiveRecord::Base
  attr_accessible :filename,
  :image # etc.
   attr_accessor :generators

   has_attached_file :image,
     :styles => lambda { |a| a.instance.project.styles }
end


 class Project < ActiveRecord::Base
   ....

   def styles
     @generators ||= self.generators.inject {} do |hash, g|
       hash[g.sym] = "#{g.width}x#{g.height}"
     end
   end
end

我刚刚解决了一个类似的问题。 在我的“样式”lambda中,我根据“类别”属性的值返回不同的样式。但问题是Image.new(attrs)和Image.update_attributes(attrs)没有按可预测的顺序设置属性,因此无法保证Image.category在调用my styles lambda之前会有一个值。我的解决方案是覆盖图像模型中的属性=(),如下所示:

class Image
  ...
  has_attached_file :image, :styles => my_lambda, ...
  ...
  def attributes=(new_attributes, guard_protected_attributes = true)
    return unless new_attributes.is_a?(Hash)
    if new_attributes.key?("image")
      only_attached_file    = {
        "image" => new_attributes["image"]
      }
      without_attached_file = new_attributes
      without_attached_file.delete("image") 
      # set the non-paperclip attributes first
      super(without_attached_file, guard_protected_attributes)
      # set the paperclip attribute(s) after
      super(only_attached_file, guard_protected_attributes)
    else
      super(new_attributes, guard_protected_attributes)
    end
  end
  ...
end
这样可以确保回形针属性设置在其他属性之后,因此可以在:样式lambda中使用它们

在“手动”设置回形针属性的情况下,这显然没有帮助。但是,在这些情况下,您可以通过指定合理的顺序来帮助自己。就我而言,我可以写:

image = Image.new
image.category = "some category"
image.image = File.open("/somefile") # styles lambda can use the "category" attribute
image.save!

(回形针2.7.4、rails 3、ruby 1.8.7)

虽然在哪里找到实际样式方法是一个有趣的问题,但这对新记录来说是不起作用的。在styles lambda中,
a.instance.project
将是
nil
,直到记录被保存为止,因此您将在
nil
上得到
NoMethodError
。我编辑了我的解决方案…我确定该实例必须指向@asset变量?如果您像我一样修改控制器,那么它应该已经将项目包含在一个隐藏的实例变量中,供paperclip使用…Rails在项目模型上拍摄错误,styles action。说明:
语法错误,意外的关键字\u do\u块,期望关键字\u end
这个问题及其答案对在我的应用程序中构建相同功能有很大帮助。谢谢大家!:)
def styles
  (@generators || project.generators).each_with_object({}) { |g, hsh| hsh[g.sym] = "#{g.width}x#{g.height}" }
end
class Asset < ActiveRecord::Base
  attr_accessible :filename,
  :image # etc.
   attr_accessor :generators

   has_attached_file :image,
     :styles => lambda { |a| a.instance.project.styles }
end


 class Project < ActiveRecord::Base
   ....

   def styles
     @generators ||= self.generators.inject {} do |hash, g|
       hash[g.sym] = "#{g.width}x#{g.height}"
     end
   end
end
def create
  @project = Project.find(params[:project_id])
  @asset = @project.assets.new
  @asset.generators = @project.generators
  @asset.update_attributes(params[:asset])
  @asset.uploaded_by = current_user
end
class Image
  ...
  has_attached_file :image, :styles => my_lambda, ...
  ...
  def attributes=(new_attributes, guard_protected_attributes = true)
    return unless new_attributes.is_a?(Hash)
    if new_attributes.key?("image")
      only_attached_file    = {
        "image" => new_attributes["image"]
      }
      without_attached_file = new_attributes
      without_attached_file.delete("image") 
      # set the non-paperclip attributes first
      super(without_attached_file, guard_protected_attributes)
      # set the paperclip attribute(s) after
      super(only_attached_file, guard_protected_attributes)
    else
      super(new_attributes, guard_protected_attributes)
    end
  end
  ...
end
image = Image.new
image.category = "some category"
image.image = File.open("/somefile") # styles lambda can use the "category" attribute
image.save!