0

Im trying to set up Amazon S3 storage with paperclip in my rails app.

I have a model called "Asset" which belongs to "User"

Here are the first few lines in Asset.rb

attr_accessible :user_id, :uploaded_file

belongs_to :user
#set up "uploaded_file" filed as attached_file(using paperclip)
has_attached_file :uploaded_file,
                :path => "assets/:id/:basename.:extension",
                :storage => :s3,
                :s3_credentials => "#{Rails.root}/config/amazon_s3.yml",
                :bucket => "XXXXX"

validates_attachment_size :uploaded_file, :less_than => 1000.megabytes
validates_attachment_presence :uploaded_file

Im getting an error when I load the view:

NoMethodError in AssetsController#create
undefined method `symbolize_keys' for #<String:0x00000103939258>

What does this mean. it has something to do with this line in "Asset.rb" :s3_credentials => "#{Rails.root}/config/amazon_s3.yml",

I looked up on the web and there were several discussions on how Rails_ROOT was deprecated so I used Rails.root instead. Still getting this error.

Also Im storing the AWS key and secret password in a amazon_s3.yml config file.

This is not the best practice, so if anyone has any other ideas, I would love to hear them. heroku says on their website to put the variables as environment variables, however, Im not sure how I would set that up on heroku and also what about when Im on my local development machine? How would that work?

Im just a bit confused, so looking to see if there is a complete example or tutorial out there somewhere. All I could find were deprecated settings.....

Thanks

banditKing
  • 9,405
  • 28
  • 100
  • 157

1 Answers1

2

How it works for me (adopted to your situation):

#Asset.rb
has_attached_file :uploaded_file, {
  :path => "assets/:id/:basename.:extension"
}.merge(PAPERCLIP_STORAGE_OPTIONS)

#environments/development.rb and test.rb
PAPERCLIP_STORAGE_OPTIONS = {
  :storage => :s3,
  :bucket => "XXXX",
  :s3_credentials => YAML.load_file("#{Rails.root}/config/s3_credentials.yml")
}

#environments/production.rb
PAPERCLIP_STORAGE_OPTIONS = {
  :storage => :s3,
  :bucket => ENV['S3_BUCKET_NAME'],
  :s3_credentials => {
    :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
    :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
  }
}

#config/s3_credentials.yml
access_key_id: "XXXX"
secret_access_key: "XXXX"

Please note

  1. Add s3_credetials.yml to .gitignore.
  2. Be sure, you added ENV variables in heroku: https://devcenter.heroku.com/articles/s3
  3. You can change the value of PAPERCLIP_STORAGE_OPTIONS to { }. Then the files will be stored locally (for example, for tests).

This question has helped me in solving problems: How can I set paperclip's storage mechanism based on the current Rails environment?

Off-topic, but it may be useful: if you want to read the file - @asset.uploaded_file.s3_object.read

Community
  • 1
  • 1
Mik
  • 4,117
  • 1
  • 25
  • 32
  • Hi thanks for this great answer. I have a question: I have this line in my "environments/development.rb" from before: "Paperclip.options[:command_path] = "/usr/local/bin/" " Should I add your suggested line: "PAPERCLIP_STORAGE_OPTIONS = {......} after this line or replace it. Thanks – banditKing Jun 17 '12 at 16:17
  • This didn't work. Im getting this error" Routing Error uninitialized constant Asset::PAPERCLIP_STORAGE_OPTIONS" – banditKing Jun 17 '12 at 16:44
  • Add before or after: does not matter. I just rechecked: the same works for me. Have you tried to restart the server? Make sure you have written same constant name in config, or which environment you launch, or where you put config... Standart debugging process. But I dunno why you getting `routing error`. It's strange, perhaps an error around here. – Mik Jun 17 '12 at 17:32