基于多态父类的 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)
问题描述
基本上我有一个 Image
模型,它 多态 属于 imageable
到目前为止 List
和 项目代码>.由于图像将具有自己的属性和关系,因此我不想将图像视为
List
和 Item
的属性并将其弄乱.所以我创建了 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:
- 仅将字符串而不是对象传递给图像.如果需要,然后将字符串常量化.
- 将 image_styles 存储在可成像模型中.我更喜欢用这种方式来维护样式,而不是将它们全部放在
Image
模型中. - 将强参数传递给
List.new
,因为它有自己的属性.('clean' 过程是可选的,我只是不希望传递一大堆 image_attributes 并触发 Paperclip)
- Pass only a string rather than a object to image. Then constantize the string if it's needed.
- Store image_styles in imageable models. I prefer this way to maintain the styles rather than put them all in
Image
model. - 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屋!