For example here is my paperclip configuration. Here is my model file:
class File < ApplicationRecord
belongs_to :attachable, polymorphic: true, optional: true
has_attached_file(:attach_file, local_option)
end
In this model file, I have defined two option named local_option and s3_option.
def local_option
{
:storage => :filesystem,
:path => 'public/:class/:id/:basename.:extension'
}
end
def s3_option
{
:storage => :s3,
:s3_headers => lambda { |attachment| {'Content-Type' => attachment.attach_file_content_type} }
}
end
When I run, I meet this error:
method_missing': undefined local variable or method `local_option' for
Class:0x007fc9be09dac8> (NameError)
I don't know why ruby/rails doesn't see local_option method. Please tell me how.
Thanks
It should be class instance method, not instance method.
def self.local_option
{
storage: :filesystem,
path: 'public/:class/:id/:basename.:extension'
}
end
And voila - error is gone.
Advice: since it is non-changing data, I'd put it into a constant:
LOCAL_FILE_OPTIONS = {
storage: :filesystem,
path: 'public/:class/:id/:basename.:extension'
}.freeze
Now
has_attached_file(:attach_file, LOCAL_FILE_OPTIONS)
Related
I have a two columns on my attachment model on which the user sets the dimension to which they want to resize the image.
However, the variables when the resize happens are nil, but set to actual values after the resize happens.
below is the code
has_attached_file :file, :styles => lambda { |a|
{ :logo => ["200x50>",:png],
:user_defined => ["#{a.instance.custom_width}x#{a.instance.custom_height}>",:png] }
}
the custom_width & custom_height are nil when conversion happens however the logo conversion works as expected.
I am using ruby 2.2.4p230 & Rails 4.2.4
below is the full mode code
class Attachment < ActiveRecord::Base
belongs_to :model_one
belongs_to :attachable, polymorphic: true
#has_attached_file :file, styles: { logo: ['200x50>',:png] }
has_attached_file :file, styles: lambda { |attachment| attachment.instance.styles }
def styles
Rails.logger.info self.inspect
Rails.logger.info self.attachable
styles = {}
m = "200x50>"
l = "#{self.custom_width}x#{self.custom_height}>"
styles[:logo] = [m, :png]
styles[:user_defined] = [l, :png]
styles
end
end
Can anyone please help and let me know if i am doing something wrong?
I am trying to implement the steps to check and resize images with paperclip based on this blog post: http://www.techdarkside.com/how-to-re-size-images-that-are-too-large-on-the-fly-with-paperclip-and-rails
Here is what I have in place...
class Question < ActiveRecord::Base
# subclasses
class Question::Image < Asset
has_attached_file :attachment,
:url => "/uploads/:class/:attachment/:id_partition/:basename_:style.:extension",
:styles => Proc.new { |attachment| attachment.instance.styles },
:styles => Proc.new { |attachment| attachment.instance.resize }
attr_accessible :attachment
# http://www.ryanalynporter.com/2012/06/07/resizing-thumbnails-on-demand-with-paperclip-and-rails/
def dynamic_style_format_symbol
URI.escape(#dynamic_style_format).to_sym
end
def styles
unless #dynamic_style_format.blank?
{ dynamic_style_format_symbol => #dynamic_style_format }
else
{ :medium => "300x300>", :thumb => "100x100>" }
end
end
def dynamic_attachment_url(format)
#dynamic_style_format = format
attachment.reprocess!(dynamic_style_format_symbol) unless attachment.exists?(dynamic_style_format_symbol)
attachment.url(dynamic_style_format_symbol)
end
def resize
if self.attachment_file_size > 2000000
"300x300>"
else
" "
end
end
end
I'm thinking the issue is with the reuse of the :styles symbol, however I'm not sure how to work both the styles method AND the resize method into a single Proc statement.
Here is what I ended up with thanks to #janfoeh suggestion. I did need to add :originalto the options in style to get this to work. I also bumped the max file size up to 5mb.
class Question < ActiveRecord::Base
# subclasses
class Question::Image < Asset
has_attached_file :attachment,
:url => "/uploads/:class/:attachment/:id_partition/:basename_:style.:extension",
:styles => Proc.new { |attachment| attachment.instance.styles }
attr_accessible :attachment
# http://www.ryanalynporter.com/2012/06/07/resizing-thumbnails-on-demand-with-paperclip-and-rails/
def dynamic_style_format_symbol
URI.escape(#dynamic_style_format).to_sym
end
def styles
unless #dynamic_style_format.blank?
{ dynamic_style_format_symbol => #dynamic_style_format }
else
{ :original => resize, :medium => "300x300>", :thumb => "100x100>" }
end
end
def dynamic_attachment_url(format)
#dynamic_style_format = format
attachment.reprocess!(dynamic_style_format_symbol) unless attachment.exists?(dynamic_style_format_symbol)
attachment.url(dynamic_style_format_symbol)
end
def resize
if self.attachment_file_size > 5000000
"1000x1000>"
else
" "
end
end
end
I have an issue using Blitline to process images. I've added the gem to my gemfile restarted terminal etc... but in the rails console I get this error when I try to test it:
Loading development environment (Rails 4.0.1)
2.0.0p353 :001 > blitline_service = Blitline.new
NameError: uninitialized constant Blitline
It's the same error I get when I try to use blitline through a model in my app...
NameError in DrawingsController#create
uninitialized constant Drawing::Blitline
Complete model code
class Drawing < ActiveRecord::Base
scope :published, -> { where(published: true) }
attr_accessible :image, :title, :user_id, :week_id, :key, :published, :safe_for_kids
#=mount_uploader :image, DrawingUploader
belongs_to :week
belongs_to :user
def image_name
File.basename(image.path || image.filename) if image
end
before_save :run_blitline_job
private
def run_blitline_job
filename = File.basename(image, '.*')
# self.title ||= sanitize_filename(filename).titleize # set default name based on filename
filename_with_ext = File.basename(image)
key = "uploads/thumbnails/#{SecureRandom.hex}/#{filename_with_ext}"
bucket = ENV["S3_BUCKET"]
images = blitline_job(image, bucket, key)
self.image = images['results'][0]['images'][0]['s3_url'] # extracts s3_url from blitline's ruby hashes
end
def blitline_job(original_image, bucket, key)
blitline_service = Blitline.new
blitline_service.add_job_via_hash({ # New add job method in Blitline gem 2.0.1. Messy.
"application_id" => ENV['BLITLINE_APPLICATION_ID'],
"src" => original_image,
"functions" => [{
"name" => "watermark", # watermark the image
"params" => { "text" => "oh hai" },
"functions" => [{
"name" => "resize_to_fill", # resize after watermark
"params" => { "width" => 200, "height" => 200 },
"save" => {
"image_identifier" => "MY_CLIENT_ID", # Not sure what this is for
"s3_destination" => { "key" => key, "bucket" => bucket } # push to your S3 bucket
}
}]
}]
})
return blitline_service.post_jobs
end
end
Any help appreciated...
Here is my validation:
describe User
it { should validate_attachment_size(:avatar).less_than(20.megabytes) }
end
Here is my User model:
class User < ActiveRecord::Base
validates_attachment :avatar, :content_type => { :content_type => /image/ }, size: { in: 0..20.megabytes }, allow_blank: true
end
The error I keep getting is:
Failure/Error: it { should validate_attachment_size(:avatar).less_than(20.megabytes) }
Attachment avatar must be between and 20971520 bytes
Not sure why this is failing. Any help is greatly appreciated!
I am trying to override validates_attachment in Subclass but I notice it only works well with Superclass validation; I wonder why my validates_attachment in subclass doesn't work. Has anybody faced this problem? and how have you solved this problem? Here is an example code:
class Superclass
validates_attachment :logo, :image_ratio => { :ratio => {"1:1" => "28", "4:1" => "50", "5:1" => "40"} }
end
class Subclass < Superclass
validates_attachment :logo, :image_ratio => { :ratio => {"1:1" => "40", "2:1" => "60"} }
end
I suggest that you should put both the class's fields in different tables. It could be possible that you are getting problems because of that.
However if you really want to have only one table for both the classes then I believe that you could use something like this:
validates_attachment :logo, :image_ratio => { :ratio => {"1:1" => "40", "2:1" => "60"} }, :unless => Proc.new {|attach| attach.type == "SubClass"}
I assumed that you have a attach_type column but depending on how you are determining whether the attachment type is a SubClass, it is left upto you to change it.
You could also try to remove your validates_attachment from the Subclass and instead try with_options in your model, like the following:
with_options :unless => :attach_type == "SubClass" do |attach|
attach.validates_attachment :logo, :image_ratio => { :ratio => {"1:1" => "40", "2:1" => "60"}}
end
This works for me... rails 4
validates :photo, :presence => true,
:attachment_content_type => { :content_type => "image/jpg" },
:attachment_size => { :in => 0..10.kilobytes }
Incase anyone else runs into an issue where they need instance access before they can validate I used the following:
class AttachmentDynamicContentTypeValidator < Paperclip::Validators::AttachmentContentTypeValidator
def validate_each(record, attribute, value)
#record = record
super
end
def allowed_types
#record.my_valid_types_array || ["text/plain"]
end
def check_validity!; end
end
And in the actual asset instance I added the following:
class Asset < ActiveRecord::Base
validates :asset, attachment_dynamic_content_type: :asset_content_type
end
Hope that helps someone.