Using model attribute as :filename when using paperclip gem - ruby

I'm getting an error when attempting to change the :filename of my paperclip attachment to equal an attribute on the class I'm attaching the paperclip file to.
When I use "#{self.company_name}" it errors out. Apparently in this scope, "self" is not Company. When I wrote this line I assumed that self is the instance of Company that I'm uploading this attachment to. Any idea how I can fix this? The Paperclip docs say to use ":filename" but I'd like to use the value of Company.company_name instead.
class Company < ActiveRecord::Base
include AliasAttrs
has_attached_file :company_logo, {
:storage => :ftp,
:path => "/logos/#{self.company_name}",
:url => FTP_CONFIG[:access_host]+"logos/:filename",
:ftp_servers => [
{
:host => FTP_CONFIG[:host],
:user => FTP_CONFIG[:user],
:password => FTP_CONFIG[:pass],
:port => 21 # optional, 21 by default
}
]
}
end
Update
I tried using the advice found in this post: https://robots.thoughtbot.com/paperclip-tips-and-updates
But now I am getting the following error when starting my server:
undefined method `interpolations' for Paperclip::Attachment:Class (NoMethodError)

It looks like the syntax for interpolations has changed. Updated it and it worked. Add the following to your model or create a paperclip.rb file in config/initializers
Paperclip.interpolates :company_name do |attachment, style|
attachment.instance.company_name
end

Related

Change path of images uploaded on Amazon S3 using PaperClip in Rails

How can I change the path of the images I upload using paperclip and rails. I want the path to be inside my bucket's gov_id folder and the image just stays there without any subfolders. And also how to make the url of the image to follow this format: "https://s3-ap-southeast-1.amazonaws.com/BUCKET_NAME/GOV_ID/IMAGE_NAME.EXTENSION"
Note: I have a gov_id folder inside my bucket
I have an attachment model that looks like this:
class Attachment < ApplicationRecord
belongs_to :attachable, polymorphic: true
has_attached_file :image, :styles => {:thumb => "200x200#"},
:storage => :s3,
validates_attachment :image, content_type: { content_type: ["image/jpg", "image/jpeg", "image/png"] }
validates_attachment :image, presence: true
before_save :rename_file
def rename_file
extension = File.extname(image_file_name).gsub(/^\.+/, '')
new_image_file_name = "gov_#{self.attachable.reference_code}.#{extension}"
image.instance_write(:file_name, new_image_file_name)
end
end
this stores the image uploaded to my bucket but not inside the gov_id folder. It goes to attachments/images/000/000/013/original
And the url becomes "s3-ap-southeast-1.amazonaws.com/BUCKET_NAME/attachments/images/000/000/013/original/gov_UG2S463C.png?1500620951
The problem is that you are trying to assign it a new name and succeeding, but you aren't telling it to do this in a format that s3 understands.
The thing you have to remember, is that s3 buckets work based on keys and objects. If you look at an s3 bucket, the folder structure is just for show, for the most part. The file path (including the file name) is essentially the key, and the object is the image stored there (in this case).
So, the key you are assigning the image is the default paperclip path (source:
paperclip docs), which ends in :file_name
in this block
has_attached_file :image, :styles => {:thumb => "200x200#"},
:storage => :s3,
You have a comma at the end of your has_attached_file, which I assume means you deleted things like bucket_name: (which is fine, but next_time, replace any sensitive info with a placeholder name. it makes the problem easier to understand).
You should have a path: symbol associated with the key used to access the s3 object. Usually, paperclip auto-generates this for you, but here you want to manually assign it. So you should be able to add something like this:
has_attached_file :image, :styles => {:thumb => "200x200#"},
:storage => s3,
:path => "/gov_id/:class/:attachment/:style/:file_name"
If you would like the '000/000/001' then put :path => "/gov_id/:class/:attachment/:id_partition/:style/:file_name"
I assume you want to have style in there so that it will deal with both the :original and :thumb style appropriately.
Also, instead of using a before_save, you might want to look into Paperclip.interpolates
something like:
has_attached_file :image, :styles => {:thumb => "200x200#"},
:storage => s3,
:path => "/gov_id/:class/:attachment/:style/:replaced_file_name"
Paperclip.interpolates :replaced_file_name do
extension = File.extname(image_file_name).gsub(/^\.+/, '')
new_image_file_name = "gov_#{self.attachable.reference_code}.#{extension}"
new_image_file_name
end

Upload paperclip images to s3 bucket

Not quite sure whats going on here, but when i try and upload an image to my s3 bucket i get this error
NameError in PostsController#create
uninitialized constant AWS::Core::ClientLogging
Rails.root: /home/richardlewis/Rails/myblog
Application Trace | Framework Trace | Full Trace
app/controllers/posts_controller.rb:41:in `create'
Im testing this in my dev environment at present. This is my current setup
Gemfile
#Paperclip and aws
gem "paperclip", "~> 3.0"
gem 'aws-sdk'
gem 'aws-s3'
Image Model
class Image < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
attr_accessible :photo
has_attached_file :photo, :styles => { :small_blog => "250x250#", :large_blog => "680x224#", :thumb => "95x95#" },
:storage => :s3,
:url => ":s3_domain_url",
:s3_protocol => 'http',
:path => "/images/:id/:style.:extension",
:s3_credentials => {
:bucket => ENV['AWS_BUCKET'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
end
My ENV variables are stored in a env.rb file and loaded within initializers
has anyone come across this before?
Upgrading to the latest paperclip, 3.5.1, will fix this issue.

Rails paperclip plugin

I am a newbie. I am trying to upload an image through paperclip. The url and path code is working but the style option is not working. This is my code:
class User < ActiveRecord::Base
has_attached_file :image, :styles => { :small => "150x150>" },
:url => "/assets/users/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/users/:id/:style/:basename.:extension"
end
When I use the style it doesn't work. If I remove the style option it does work. Please help me out!
Not sure if this will work but try :style_:basename.:extension

Haml + ActionMailer - Rails?

I'm trying to use ActionMailer without Rails in a project, and I want to use Haml for the HTML email templates. Anyone have any luck getting this configured and initialized so that the templates will be found and rendered? I'm currently getting errors like:
ActionView::MissingTemplate: Missing template new_reg/daily_stats/full with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en]} in view paths "/home/petersen/new_reg/lib/new_reg/mailers/views"
To clarify, this is ActionMailer 3.0.4
Looks like the issue is that without the full Rails stack, Haml doesn't completely load, specifically the Haml::Plugin class. Adding require 'haml/template/plugin' after the normal require 'haml' line seems to solve the problems.
require 'haml/template/plugin' in the "configure do" block together with ActionMailer::Base.view_paths = "./views/" did it for me (Sinatra)
Not necessary in Rails -- but since you're using ActionMailer without Rails -- did you specify ActionMailer::Base.register_template_extension('haml')?
I'm seeing a similar issue and am using ActionMailer 3.0.3. register_template_extension does not exist in ActionMailer 3.
I'm using Sinatra. I've got mailer.rb (below) in APP_ROOT/lib and the views are located in APP_ROOT/views/mailer. This sends an email with a subject, the body is blank though.
require 'action_mailer'
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.view_paths = File.dirname(__FILE__)+"/../views/"
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => 'exmaple.com',
:user_name => 'user#exmaple.com',
:password => 'password',
:authentication => 'plain',
:enable_starttls_auto => true }
class Mailer < ActionMailer::Base
def new_comment_notifier(post,comment)
#post = post
#comment = comment
mail(:to => "user#example.com",
:subject => "new comment on: #{post.title}")
end
end

ActionMailer 3 without Rails

I'm writing a small Ruby program that will pull records from a database and send an HTML email daily. I'm attempting to use ActionMailer 3.0.3 for this, but I'm running in to issues. All the searching I've done so far on using ActionMailer outside of Rails applies to versions prior to version 3. Could someone point me in the right direction of where to find resources on how to do this? Here's where I am so far on my mailer file:
# lib/bug_mailer.rb
require 'action_mailer'
ActionMailer::Base.delivery_method = :file
class BugMailer < ActionMailer::Base
def daily_email
mail(
:to => "example#mail.com",
:from => "example#mail.com",
:subject => "testing mail"
)
end
end
BugMailer.daily_email.deliver
I'm definitely stuck on where to put my views. Every attempt I've made to tell ActionMailer where my templates are has failed.
I guess I should also ask if there's a different way to go about accomplishing this program. Basically, I'm doing everything from scratch at this point. Obviously what makes Rails awesome is it's convention, so is trying to use parts of Rails on their own a waste of time? Is there a way to get the Rails-like environment without creating a full-blown Rails app?
After some serious debugging, I found how to configure it.
file mailer.rb
require 'action_mailer'
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "domain.com.ar",
:authentication => :plain,
:user_name => "test#domain.com.ar",
:password => "passw0rd",
:enable_starttls_auto => true
}
ActionMailer::Base.view_paths= File.dirname(__FILE__)
class Mailer < ActionMailer::Base
def daily_email
#var = "var"
mail( :to => "myemail#gmail.com",
:from => "test#domain.com.ar",
:subject => "testing mail") do |format|
format.text
format.html
end
end
end
email = Mailer.daily_email
puts email
email.deliver
file mailer/daily_email.html.erb
<p>this is an html email</p>
<p> and this is a variable <%= #var %> </p>
file mailer/daily_email.text.erb
this is a text email
and this is a variable <%= #var %>
Nice question! It helped me to understand a bit more how Rails 3 works :)
It took me a while to get this to work in (non-)Rails 4. I suspect it's just because I have ':require => false' all over my Gemfile, but I needed to add the following to make it work:
require 'action_view/record_identifier'
require 'action_view/helpers'
require 'action_mailer'
Without the above code, I kept getting a NoMethodError with undefined method 'assign_controller'.
After that, I configured ActionMailer as follows:
ActionMailer::Base.smtp_settings = {
address: 'localhost', port: '25', authentication: :plain
}
ActionMailer::Base.default from: 'noreply#example.com'
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.logger = Logger.new(STDOUT)
ActionMailer::Base.logger.level = Logger::DEBUG
ActionMailer::Base.view_paths = [
File.join(File.expand_path("../../", __FILE__), 'views', 'mailers')
# Note that this is an Array
]
The templates go in lib/<GEM_NAME>/views/mailers/<MAILER_CLASS_NAME>/<MAILER_ACTION_NAME>.erb (MAILER_ACTION_NAME is the public instance method of your mailer class that you call to send the email).
Lastly, don't forget to put this in your spec_helper:
ActionMailer::Base.delivery_method = :test

Resources