基于多态父类的 Paperclip 动态样式不起作用(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)

查看:39
本文介绍了基于多态父类的 Paperclip 动态样式不起作用(Rails 4.2.5、Paperclip 4.3.1)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Basically I have an Image model which polymorphically belongs to imageable which are by far List and Item. 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. So I create the Image model.

我想要实现的是 List 应该有一个徽标拇指图像,其中高度等于宽度,但 Item 具有不同的样式.Paperclip 文档告诉我们使用 lambda 创建动态样式.所以这是我的 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. Paperclip doc has told us to create dynamic styles using lambda. So here's my Image model:

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 .人们认为,当与可成像相关的所有内容都没有分配时,回形针处理器出现得太早了.所以结果是我总是有一个 200x100 大小的图像,即使可成像是一个 List.

And I have nested form in my new.html.erb for lists. Everything works well if I don't use dynamic styles in Image model. If I do so, the imageable_type remains nil when the image styles are processed. It is believed that the Paperclip processor comes in too early when everything related to the imageable aren't assigned. So the result is that I always have an image with 200x100 size even when the imageable is a List.

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

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). Now I'd be grateful if anyone can provide a clean solution before I give in and use STI or monkey-patch Active Record.

推荐答案

monkey-patch 解决方案几乎解释了为什么会这样.但是如果您对 Active Record 没有全面的了解,就不容易理解.基本上,您必须在分配 Paperclip 属性之前让 Rails 分配可成像的相关属性.

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. Basically, you have to make Rails assign imageable related attributes before assigning the Paperclip ones.

感谢@Eren CAY 此处,我找到了更简单的解决方案.但我对其进行了一些修改,以便在我的应用中更好地运行.

I've found a simpler solution thanks to @Eren CAY here. But I made some modifications for it to work better in my app.

在我的 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它的可成像类型的指定参数(无论参数是字符串还是对象或其他).通常,只有在分配文件属性后,才会分配其他可成像的相关属性.

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). 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. 仅将字符串而不是对象传递给图像.如果需要,然后将字符串常量化.
  2. 将 image_styles 存储在可成像模型中.我更喜欢用这种方式来维护样式,而不是将它们全部放在 Image 模型中.
  3. 将强参数传递给 List.new,因为它有自己的属性.('clean' 过程是可选的,我只是不希望传递一大堆 image_attributes 并触发 Paperclip)
  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. I prefer this way to maintain the styles rather than put them all in Image model.
  3. Pass strong parameters to List.new as it has its own attributes. (The 'clean' process is optional, I just don't want the whole bunch of image_attributes to be passed and trigger Paperclip)

这篇关于基于多态父类的 Paperclip 动态样式不起作用(Rails 4.2.5、Paperclip 4.3.1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆