简体   繁体   English

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

[英]Paperclip dynamic styles based on polymorphic parent class doesn't work (Rails 4.2.5, Paperclip 4.3.1)

Basically I have an Image model which polymorphically belongs to imageable which are by far List and Item . 基本上,我有一个Image模型,该模型多态地属于imageable对象,到目前为止,它们都是ListItem Since an image will have its own attribute and relationship, I don't want to treat images like attributes of the List and Item and mess it up. 由于图像将具有其自己的属性和关系,因此我不想将图像像ListItem属性一样对待并将其弄乱。 So I create the Image model. 因此,我创建了Image模型。

What I want to achieve is that List should have a logo thumb image where height equals width but Item has a different style. 我要实现的是List应该有一个徽标拇指图像,其中高度等于宽度,但Item具有不同的样式。 Paperclip doc has told us to create dynamic styles using lambda . 回形针doc告诉我们使用lambda创建动态样式。 So here's my Image model: 所以这是我的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

And my List model: 而我的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

And my lists_controller.rb : 和我的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

And I have nested form in my new.html.erb for lists. 我在new.html.erb嵌套了表单列表。 Everything works well if I don't use dynamic styles in Image model. 如果我Image模型中不使用动态样式那么一切都会很好 If I do so, the imageable_type remains nil when the image styles are processed. 如果这样做,则在处理图像样式时imageable_type仍为nil It is believed that the Paperclip processor comes in too early when everything related to the imageable aren't assigned. 据信,如果没有分配与可成像图像有关的所有内容,Paperclip处理器来得太早。 So the result is that I always have an image with 200x100 size even when the imageable is a List . 因此,结果是即使可成像对象是List ,我也总是拥有200x100尺寸的图像。

I've been seeking around for a solution. 我一直在寻找解决方案。 But many solutions are for Rails 3 and failed in my app (like attr_accessible solution and any solution intending to retrieve anything about the imageable). 但是许多解决方案都是针对Rails 3的,并且在我的应用程序中失败了(例如attr_accessible解决方案以及任何旨在检索可成像内容的解决方案)。 Now I'd be grateful if anyone can provide a clean solution before I give in and use STI or monkey-patch Active Record. 现在,如果有人在我提供并使用STI或猴子补丁Active Record之前可以提供干净的解决方案,我将不胜感激。

The monkey-patch solution explains pretty much about why this is happening. 猴子补丁解决方案说明了为什么会发生这种情况。 But it's not easy to understand if you don't have comprehensive knowledge about Active Record. 但是,如果您不具备有关Active Record的全面知识,就很难理解。 Basically, you have to make Rails assign imageable related attributes before assigning the Paperclip ones. 基本上,在分配回形针之前,必须使Rails分配可成像的相关属性。

I've found a simpler solution thanks to @Eren CAY here . 感谢@Eren CAY 在这里,我找到了一个更简单的解决方案。 But I made some modifications for it to work better in my app. 但是我对其进行了一些修改,以使其在我的应用中可以更好地工作。

In my Image model: 在我的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

And in my lists_controller.rb : 在我的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

I think the essential is the specified parameter passed to tell Image its imageable type (no matter the parameter is a string or object or sth else). 我认为关键是传递给Image的可成像类型的指定参数(无论该参数是字符串,对象还是其他)。 Normally, it's only after the file attribute is assigned that other imageable related attributes are assigned. 通常,只有在分配了文件属性之后,才会分配其他可成像的相关属性。

The main differences from the original solution is that: 与原始解决方案的主要区别在于:

  1. Pass only a string rather than a object to image. 仅将字符串而不是对象传递给图像。 Then constantize the string if it's needed. 然后根据需要对字符串进行常量化。
  2. Store image_styles in imageable models . 将image_styles存储在可成像模型中 I prefer this way to maintain the styles rather than put them all in Image model. 我更喜欢这种方式来维护样式,而不是将其全部放入Image模型中。
  3. Pass strong parameters to List.new as it has its own attributes. 将强大的参数传递给List.new因为它具有自己的属性。 (The 'clean' process is optional, I just don't want the whole bunch of image_attributes to be passed and trigger Paperclip) (“干净”过程是可选的,我只是不希望传递全部image_attributes并触发回形针)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM