基于多态父类的Paperclip动态样式不起作用(Rails 4.2.5,Paperclip 4.3.1)

时间:2015-12-18 18:37:13

标签: ruby-on-rails ruby paperclip

基本上我有Image模型多态属于imageable,目前为ListItem。由于图片将具有自己的属性和关系,因此我不想将图像视为ListItem的属性并将其搞砸。所以我创建了Image模型。

我想要实现的是List应该有徽标拇指图像,其中高度等于宽度,但Item具有不同的样式。 Paperclip doc告诉我们使用lambda创建动态样式。所以这是Image模型:

class Image < ActiveRecord::Base

  belongs_to :imageable, polymorphic: true

  has_attached_file :file,
                    :styles => lambda { |file| { thumb: (file.instance.imageable_type == "List") ? "300x300!" : "200x100!") } }
                    :default_url => "/images/:style/missing.png"

end

我的List型号:

class List < ActiveRecord::Base
  def list_params
    params.require(:list).permit(:title, :image_attributes)
  end

  has_one :image, as: :imageable
  accepts_nested_attributes_for :image
  validates :image, presence: true
end

我的lists_controller.rb

class ListsController < ApplicationController
  def list_params
    params.require(:list).permit(:title, :image_attributes)
  end

  def create
    @list = List.new(list_params)
    if @list.save
      redirect_to @list
    else
      render :action => "new"
    end 
  end
end

我在new.html.erb列表中嵌套了表单。 如果我不在Image模型中使用动态样式,那么一切运作良好。如果我这样做,则imageable_type在处理图像样式时仍为nil。据信,当与可成像相关的所有内容都未分配时,Paperclip处理器过早出现。因此,即使可成像为200x100,我也总是拥有List大小的图片。

我一直在寻求解决方案。但是许多解决方案适用于Rails 3并且在我的应用程序中失败(例如attr_accessible解决方案以及任何打算检索有关可成像的任何解决方案)。现在,如果有人能在我投入使用STI或猴子补丁活动记录之前提供一个干净的解决方案,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

monkey-patch解决方案解释了为什么会发生这种情况。但是,如果您不具备有关Active Record的全面知识,那么这一点并不容易理解。基本上,在分配Paperclip之前,你必须让Rails分配可成像的相关属性。

感谢@Eren CAY here,我找到了一个更简单的解决方案。但我做了一些修改,以便在我的应用程序中更好地工作。

在我的Image模型中:

class Image < ActiveRecord::Base

  belongs_to :imageable, polymorphic: true

  has_attached_file :file,
                    :styles => -> (file) {file.instance.get_customized_styles},
                    :default_url => "/images/:style/missing.png"

  def get_customized_styles
    raise "Imageable not found." unless imageable_type

    if imageable_type == "List"
      imageable_type.constantize.image_styles
    else
      raise "Please define styles for #{imageable_type}."
    end
  end

end

在我的lists_controller.rb

class ListsController < ApplicationController

  def list_params
    params.require(:list).permit(:title, :description, :image_attributes)
  end

  def new
    @list = List.new
    @list.build_image
  end

  def create
    cleaned_list_params = list_params.dup
    cleaned_list_params.delete(:image_attributes)
    @list = List.new(cleaned_list_params)

    image_params = {imageable_type: "List", file: params[:list][:image_attributes][:file]}
    @list.build_image(image_params)
    if @list.save
      redirect_to :action => "index"
    else
      render :action => "new"
    end
  end

end

我认为必要的是传递给告诉Image其可成像类型的指定参数(无论参数是字符串或对象还是其他)。通常情况下,只有分配了文件属性后才会分配其他可成像相关属性。

与原始解决方案的主要区别在于:

  1. 仅将字符串而不是对象传递给图片。然后,如果需要,则对字符串进行constantized。
  2. 将image_styles存储在可成像模型中。我更喜欢这种方式来维护样式,而不是将它们全部放在Image模型中。
  3. 将强参数传递给List.new,因为它有自己的属性。 (&#39; clean&#39;过程是可选的,我只是不希望传递一大堆image_attributes并触发Paperclip)