Follow Along as I Stumble on the Path to Learning RoR

Gems

Automatically Handle N+1 Queries

I found a gem that’s helping me a bunch, so I just wanted to give it a quick mention.  After asking people for help on a N+1 query that I couldn’t figure out, one of the people recommended checking out the Goldiloader gem.

I was so impressed that the gem solved my N+1 query so easily, I decided to use it across my site.

It’s ridiculously simple to use once you have model associations defined.

All you need to do is to add the gem to your gemfile and it does the eager loading for you!  If there are places you want to avoid eager loading, you can disable Goldiloader for a query.

Advertisements

Improving ActiveAdmin Performance

ActiveAdmin is my favorite gem for creating admin features in Rails.  It makes it so easy to create views to monitor and manage apps.  Much of the heavy lifting is done for you by them gem.

I found that I need to do some tuning on my ActiveAdmin views to get the functionality I wanted without placing too heavy a burden on my server.

I mainly did this by doing two simple things:

(1) Specify Filters – if you don’t specify your filters, you may get far too many (and consuming too many resources when you don’t need to).  Specifying filters are easy, just go into you admin files for the resource (i.e. app > admin > article.rb), then add a line for each filter you want

filter :title
filter :created_at

(2)  Specify Index (and other) Columns – similar to above, if you don’t specify values, you may be receiving too much data.  Be more efficient by only showing what you need to see in a view.

You can do this in your admin file for a resource, simply by adding this:

index do
column :title
column :description
column :created_at
column :updated_at
end

 

 


Seeding DB with Paperclip Images with CSV

I needed to seed my app, hosted on Heroku, with new users.  Since I wanted to created a lot of the them, I wanted to CSV.  My users have avatars, so I wanted to upload those for the users as well.

Here’s how I did it:

1. I stored the original images I wanted to use for the avatars on AWS S3 (make sure that they are set with public permission to read them.

2. I created a CSV that had columns (in this order) for the users: username, email, password, password_confirmation, avatar.  In the avatar field, I put the URL of the S3 image.  I named this CSV file “user_data” and put it in the DB directory.

3. Using the answer to this Stack Overflow question, I created a file (I named user_seed.rake) in lib/tasks.  The code in the file I used was:

require ‘csv’

namespace :csv do

desc “Import CSV Data”
task :import_stuff => :environment do

csv_file_path = ‘db/user_data.csv’

CSV.foreach(csv_file_path) do |row|
User.create!({
:username => row[0],
:email => row[1],
:password => row[2],
:password_confirmation => row[3],
:avatar => URI.parse(row[4])
})
puts “Row added!”
end
end

end

4.  Run rake csv:import_stuff


Using CloudFront with S3 and Paperclip

I wanted to cache my S3 images for my Rails app, so I changed my app to serve images using AWS CloudFront, a CDN.

Doing this was pretty simple.

(1) Set-up a AWS CloudFront instance and your S3 bucket as your origin

(2) Change your Paperclip settings to use the new CloudFront instance.  I did this in production.rb (make sure neither the url or s3_host_alias values are being written by Paperclip settings in your model):

config.paperclip_defaults = {
storage: :s3,
:url => “:s3_alias_url”,
:s3_host_alias => “your-cloud-front-url.cloudfront.net”,
:path => “:rails_env/:class/:attachment/:id/:style/:filename”,
:bucket => “your-bucket-name”,
s3_credentials: {
bucket: ENV[‘AWS_S3_BUCKET’],
access_key_id: ENV[‘AWS_ACCESS_KEY_ID’],
secret_access_key: ENV[‘AWS_SECRET_ACCESS_KEY’],
}
}

and that’s it!

Now, if you check the URL of your images, it should see that their source is prefaced with your CloudFront URL.


Sendgrid Settings

I tried following Sendgrid’s instructions, but they didn’t work.  I was getting this error:

Errno::ECONNREFUSED – Connection refused – connect(2) for “localhost” port 25

I fixed it by adding these settings:

config/environments/production.rb

config.action_mailer.raise_delivery_errors = true config.action_mailer.default_url_options = { :host => ‘sitename.com’ } config.action_mailer.perform_deliveries = true ActionMailer::Base.smtp_settings = { :address => ‘smtp.sendgrid.net’, :port => ‘587’, :authentication => :plain, :user_name => ENV[‘SENDGRID_USERNAME’], :password => ENV[‘SENDGRID_PASSWORD’], :domain => ‘heroku.com’ } ActionMailer::Base.delivery_method = :smtp


Adding a Sitemap to Google for Sites on Heroku

I’m using the awesome Sitemap Generator gem for Rails  and also hosting my app on Heroku.  Since I’m updating my sitemap daily, and Heroku forces me to write to somewhere else, I need to create the sitemap nightly on Amazon Web Services (S3), instead.

The problem I ran into is that when I went to Google Webmaster Tools, it only allowed me to specify a url for the sitemap beginning with the name of my domain.  However, since the sitemap is hosted on AWS, it has an address that starts with an Amazon URL.

I found an answer here.

Basically what you need to do is to add a second property in Google Webmaster Tools for your S3 bucket.  I added a property to my directory with the sitemap (i.e. http://s3.amazonaws.com/mybucket/sitemaps/) and then verified that I owned the property by placing the Google supplied HTML file in the sitemaps folder on S3.

The last step is adding the URL to the sitemap in settings for the new [S3] property that was added to Google Webmaster Tools.


Setting Paperclip Image URL

I had to find the URL of Paperclip images in order to use them in meta tags.  This is what I ended up doing (where User is the model and image the attachment name):

user.image.url(:thumbnail)