Uploading files to Amazon S3 in a Ruby on Rails Application
I have been working on an app locally, and am getting ready to make it available publicly. The app allows users to upload MP3s, so the first step in launching the app is make it so uploads go somewhere other than my computer. I decided to use Amazon's Simple Storage Service (S3) for this.
I started this process here. The first steps were easy enough, sign up for AWS, and follow the steps to get the necessary credentials. Next, I started following the instructions found in the section "To use the AWS ORM in a Rails 3 application". I installed the "aws-sdk" gem as indicated; gem install aws-sdk, added the gem to my gemfile; gem 'aws-sdk', and ran bundle install.
After getting these basics done, it was time to actually modify my code to do the uploads. I knew from looking at a friend's app who does a similar thing that two things needed to be done; create a YAML file that contains the S3 credentials, and modify the attachment model of my app so it knows where to store the MP3s.
First, I created the YAML file that contains the bucket name and credentials. (I later realized that I also had to manually create the bucket in the AWS console.) I created the file and added the necessary configuration as found on the AWS documentation linked above (with my credentials included):
development: access_key_id: REPLACE_WITH_ACCESS_KEY_ID secret_access_key: REPLACE_WITH_SECRET_ACCESS_KEY test: <<: *development production: <<: *development
I then added a few lines to where my attachemnt is uploaded in the attachment model, as detailed on this blog post, except, of course, modifying it for my app:
has_attached_file :file, :storage => :s3, :s3_credentials => "#{RAILS_ROOT}/config/s3.yml", :path => "tunes/:style/:id/:filename"
With these two tasks complete, I figured I would be in business. However, I encountered an error when trying to upload new files (both when creating or updating a record). This error said that there was an "unknown attribute: file" in the controller. This confused me since I hadn't modified anything's name or location, so why didn't it know what "file" was?
I am still not exactly sure why that error occured, but I know how I was able to fix it (with the help of #rubyonrails). There were a few problems going on; first of all, my s3.yml file was indented incorrectly, I had a bunch of extra leading spaces, which YAML does not like. Once I fixed this, a new error occured, saying Rails could not find an alias called "development". It turns out that the AWS S3 documentation is wrong, and that rather than put development: at the start of my YAML file, I had to put development: &development, which seems to be how you declare an alias in YAML (the &development" part at least.)
The final change, which I dont think was a breaking change, was that the :s3_credentials => "#{RAILS_ROOT}/config/s3.yml", line in my model was changed to :s3_credentials => "#{Rails.root}/config/s3.yml",. "RAILS_ROOT" has been decprecated in Rails 3.0, and should now be "Rails.root".
So, with those changes made, I am now successfully able to upload files to my S3 bucket. Here are the functioning snippets:
config/s3.yml
development: &development bucket: tunes-bucket access_key_id: xxx secret_access_key: xxx test: <<: *development
production: <<: *development
models/attachment.rb
has_attached_file :file, :storage => :s3, :s3_credentials => "#{Rails.root}/config/s3.yml", :path => "tunes/:style/:id/:filename"











