問題描述
回形針不為一種型號存儲替代尺寸,但為另一種型號存儲 (Paperclip is not storing alternative sizes for one model, but does for another)
我有兩個附有圖片的模型。第一個是這樣定義的:
class Post < ActiveRecord::Base
has_attached_file :cover_image, styles: { large: "750x750^", medium: "600x600>", thumb: "100x100>" }, default_url: ":style/missing.gif"
validates_attachment_content_type :cover_image, content_type: /\Aimage\/.*\Z/
end
這很好用,在我的 /public 文件夾中總共存儲了 4 張圖像。
不過我的第二個模型......
class Lesson < ActiveRecord::Base
has_attached_file :image, styles: { large: "750x750^", medium: "600x600>", thumb: "100x100>" }, default_url: ":style/missing.gif"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end
... 僅將原始圖像存儲在名為 original 的文件夾中。
我的服務器日誌在 POST 請求中確實顯示了類似的內容:
Command :: file ‑b ‑‑mime '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑jxf7m7.jpg'
Command :: identify ‑format '%wx%h,%[exif:orientation]' '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]' 2>/dev/null
Command :: identify ‑format %m '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]'
Command :: convert '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]' ‑auto‑orient ‑resize "750x750^" '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/a802cd21677cc830b7ba993a8ff7edd920151207‑39937‑1p9h15m'
Command :: identify ‑format '%wx%h,%[exif:orientation]' '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]' 2>/dev/null
Command :: identify ‑format %m '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]'
Command :: convert '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]' ‑auto‑orient ‑resize "600x600>" '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/a802cd21677cc830b7ba993a8ff7edd920151207‑39937‑r4bxgl'
Command :: identify ‑format '%wx%h,%[exif:orientation]' '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]' 2>/dev/null
Command :: identify ‑format %m '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]'
Command :: convert '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑wmm770.jpg[0]' ‑auto‑orient ‑resize "100x100>" '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/a802cd21677cc830b7ba993a8ff7edd920151207‑39937‑4zvubq'
Command :: file ‑b ‑‑mime '/var/folders/2b/q6z4f1fn58s83fbx77xwsk5h0000gn/T/64ecce8dbf7049731a63696ae4d7933020151207‑39937‑19vrckc.jpg'
這可能是由字段名稱引起的?還有其他想法嗎?
編輯我的課程模型實際上有點複雜,因為它使用共享表來區分內容類型:
class Lesson < ActiveRecord::Base
self.table_name = 'steps'
default_scope { where(content_type: name) }
has_attached_file :cover_image, styles: { large: "750x750^", medium: "600x600>", thumb: "100x100>" }, default_url: ":style/missing.gif"
validates_attachment_content_type :cover_image, content_type: /\Aimage\/.*\Z/
validates :title, presence: true, length: { maximum: 255 }
def self.create_for_course(course, attributes = {})
content = new(attributes)
if content.valid?
step = Step.create(content_type: name, course: course)
instance = step.becomes(self)
instance.update_attributes(attributes)
instance
else
step = content.becomes(Step)
step.course = course
step.content_type = name
step.becomes(self)
end
end
#include Content
#restrict_attrs :title, :content_body, :cover_image_file_name, :cover_image_content_type, :cover_image_file_size, :cover_image_updated_at, :cover_image
end
參考解法
方法 1:
This was too long for a comment; you'll benefit from using the paperclip_defaults
option:
#config/application.rb
...
config.paperclip_defaults = {
styles: { large: "750x750^", medium: "600x600>", thumb: "100x100>" },
default_url: ":style/missing.gif"
}
This will allow you to just call the attachment name in your models and override the defaults if you so wish:
#app/models/post.rb
class Post < ActiveRecord::Base
has_attached_file :cover_image
validates_attachment_content_type :cover_image, content_type: /\Aimage\/.*\Z/
end
‑‑
In respect to your error, I'm not sure what the problem might be.
I have a suggestion though. It's a little tricky, but if you can get it working, it makes all your models super dry.
#app/models/asset.rb
class Asset < ActiveRecord::Base
#Associations
##################
belongs_to :assetable, polymorphic: true
#Paperclip
##################
delegate :url, to: :attachment
########################################
##################
# Methods #
##################
before_create :dimensions #‑> https://github.com/thoughtbot/paperclip/wiki/Extracting‑image‑dimensions
#Width & Height
def dimensions
return unless image? && has_dimensions?
self.width = geometry.width
self.height = geometry.height
end
########
private
#Geometry ‑> https://github.com/galetahub/ckeditor/blob/master/lib/ckeditor/backend/paperclip.rb#L23
def geometry
@geometry ||= begin
file = attachment.respond_to?(:queued_for_write) ? attachment.queued_for_write[:original] : attachment.to_file
::Paperclip::Geometry.from_file(file)
end
end
#Image?
def image?
image_types = %w(image/jpeg image/png image/gif image/jpg image/pjpeg image/tiff image/x‑png)
image_types.include? attachment_content_type
end
#Dimensions
def has_dimensions?
respond_to?(:width) && respond_to?(:height)
end
end
This can then be used with STI's:
#app/models/post.rb
class Post < ActiveRecord::Base
has_one :cover, class_name: "Post::Cover", as: :assetable, dependent: :destroy
accepts_nested_attributes_for :cover, reject_if: :all_blank
has
end
#app/models/post/cover.rb
class Post::Cover < Asset
has_attached_file :attachment
end
This allows you to set the cover
attribute as a nested association, but will have the added benefit of storing all the assets in your App in the assets
table:
‑‑
Update
You could use the following to make your create_for_course
method DRYer:
#app/models/post.rb
class Lesson < ActiveRecord::Base
attr_reader :course
belongs_to :step
before_create :set_step, if Proc.new { |a| a.course }
private
def set_step
self.step.create(course: course) #‑> we can use the course virtual attribute)
end
end
Although I doubt it catches your functionality specifically, it would allow you to run:
lesson = Lesson.create course: "5"
# automatically creates "step" with course of "5" and current lesson
(by bo‑oz、Richard Peck)