【问题标题】:Paperclip dynamic styles based on polymorphic parent class doesn't work (Rails 4.2.5, Paperclip 4.3.1)基于多态父类的 Paperclip 动态样式不起作用(Rails 4.2.5、Paperclip 4.3.1)
【发布时间】:2015-12-18 18:37:13
【问题描述】:

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

我想要实现的是List 应该有一个徽标拇指图像,其中高度等于宽度,但Item 具有不同的样式。 Paperclip 文档告诉我们使用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。人们认为,当与 imageable 相关的所有内容都没有分配时,Paperclip 处理器就来得太早了。所以结果是我总是有一个大小为200x100 的图像,即使图像是List

我一直在寻找解决方案。但是许多解决方案适用于 Rails 3,但在我的应用程序中失败了(例如 attr_accessible 解决方案和任何打算检索有关可成像的任何内容的解决方案)。现在,如果有人能在我放弃并使用 STI 或猴子补丁 Active Record 之前提供一个干净的解决方案,我将不胜感激。

【问题讨论】:

    标签: ruby-on-rails ruby paperclip


    【解决方案1】:

    monkey-patch 解决方案很好地解释了为什么会发生这种情况。但是如果你对 Active Record 没有全面的了解,就不容易理解。基本上,您必须先让 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. 只将字符串而不是对象传递给图像。然后在需要时对字符串进行常量化。
    2. 将 image_styles 存储在可成像模型中。我更喜欢这种方式来维护样式,而不是将它们全部放在Image 模型中。
    3. 将强参数传递给List.new,因为它有自己的属性。 ('clean' 过程是可选的,我只是不希望传递一大堆 image_attributes 并触发 Paperclip)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-15
      • 2014-05-15
      相关资源
      最近更新 更多