基本上我有Image
模型多态属于imageable
,目前为List
和Item
。由于图片将具有自己的属性和关系,因此我不想将图像视为List
和Item
的属性并将其搞砸。所以我创建了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或猴子补丁活动记录之前提供一个干净的解决方案,我将不胜感激。
答案 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
其可成像类型的指定参数(无论参数是字符串或对象还是其他)。通常情况下,只有分配了文件属性后才会分配其他可成像相关属性。
与原始解决方案的主要区别在于:
Image
模型中。List.new
,因为它有自己的属性。 (&#39; clean&#39;过程是可选的,我只是不希望传递一大堆image_attributes并触发Paperclip)