Category Archives: Ruby on Rails

Ruby on Rails: Sending Email with ActionMailer via SES and SMTP

I’m a huge fan of Amazon web services. They’ve served me quite well with some of my ASP.NET applications. So I’d be foolish (in my opinion anyway) not to use them in my Rails applications. I’m in need of sending transactional email from some of my Rails web apps, so I set up my SES account. I didn’t want to use the amazon-ses-mailer gem since SES now supports SMTP. So I generated my SMTP credentials and went into my application.rb file to start configuring ActionMailer.

I was a little stumped after a while on how I should configure ActionMailer’s SMTP settings to use SES via SMTP. A few posts here, here, and finally on this StackOverflow post lead me to this configuration:

config.action_mailer.default_url_options = { 
  :host => "thenameofyourdomain.com" 
}

config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
    
config.action_mailer.smtp_settings = {
    :address => "email-smtp.us-east-1.amazonaws.com",
    :port => 465,
    :domain => "thenameofyourdomain.com",
    :authentication => :login,
    :user_name => "your-ses-smtp-username",
    :password => "your-ses-smtp-password"
}

Now, SES SMTP uses TLS (SSL) when authenticating, so you need one more snippet of code in an initializer when your application starts up:

require 'net/smtp'

module Net
  class SMTP
    def tls?
      true
    end
  end
end

The final hint for me to get this working was the require ‘net/smtp’. Without it the email wouldn’t actually get delivered. I wanted to record this mostly for my reference in the future, but hopefully it helps any other Rails developers who get stuck on this topic.

Create an XML Sitemap on Heroku via Amazon S3

I’ve started hosting a few simple Rails applications on Heroku and so far, I’m really pleased with their hosting service. This post isn’t as much about Heroku as it is how to serve an XML sitemap for your application. Heroku apps don’t give you file system access from within your application, so you’re forced to host your sitemap on an external service, like Amazon S3. There’s a great plugin called sitemap_generator that lets you generate a sitemap and upload it to your Amazon S3 account using carrierwave and Fog.

Even though sitemap_generater will ping all of the major search engines when you build your sitemap (which you should rebuild regularly with a rake task), you will want to configure the sitemap in Google Webmaster Tools. Unfortunately, Webmaster Tools will only let you set a sitemap to come from your domain, not another host. What can we do to fix that?

Well, the easiest solution I came up with was to create a controller to handle your sitemap, but redirect it to the location of your sitemap on S3 (via CloudFront obviously). So, lets get to the code. Create a file called sitemap_controller.rb and paste this in:

class SitemapController < ApplicationController
   def index
      redirect_to SITEMAP_PATH
   end  
end

This will redirect a call to the index action of this controller to the value of SITEMAP_PATH. But what is SITEMAP_PATH? Well, in my case, my application relies heavily on a custom Rails engine where all of my controllers and models are defined. So I figured it would be nice to configure the location of the sitemap on a per application basis. So in my actual rails application, I created an initializer and set the value of SITEMAP_PATH. Put this in sitemap.rb in config/initializers:

SITEMAP_PATH="http://somepathtoyoursitemap.com/"

That's the actual location of your sitemap on S3 (again, most likely via CloudFront). Now all that's left is to wire up a Rails route to actually respond to a request for sitemap.xml. That's done easily enough with the following:

match "/sitemap.xml", :controller => "sitemap", :action => "index"

That's it! Simply restart your app if its already running so the initializer will load and access your sitemap.

Thinking Sphinx – Indexing Models Defined in a Rails Engine

I’m back in the Ruby on Rails game after a long hiatus and my, things have changed a lot. And they’ve changed for the better. The application I’m working on, like many other web applications, requires an internal search feature. Sphinx was very reliable for me in the past, however, it seems that ultrasphinx and acts_as_sphinx has been replaced with a better Rails plugin, Thinking Sphinx. Getting started was super easy. After installing Sphinx and setting up the Thinking Sphinx gem (version 2.0.11) in my application’s Gemfile, I was ready to get started.

But, I ran into a problem. The platform I’m building leverages a Rails Engine to implement most of the application’s functionality. Thinking Sphinx wasn’t setting up any models to index, even though I had defined them. Turns out, that if you don’t define your models in a typical path that Thinking Sphinx is looking at, i.e. app/models, then you’re in trouble. However, after a bunch of searching, I found the solution to my problem. Create an initializer sphinx.rb in your config/initializers directory of your application. To it, add:

module ThinkingSphinx
  class Context
    def load_models
      MyModule::MyClass
    end
  end
end

I defined my models in a sub-folder of app/models and put them in a module, so hence the MyModule::MyClass. This explicitly tells Thinking Sphinx which models to load. Running rake thinking_sphinx:config after that change set up the sphinx config file as I expected it would. Then I ran thinking_sphinx:inde and I was off and running. Jumping into the rails console, I was able to verify that searching worked as expected. Hope that helps!

Updating Pagination When Deleting Items with AJAX In Ruby on Rails

Ruby on Rails & AJAXRuby on Rails

Lately, I seem to be on a tear here with my Ruby on Rails development related posts. I suppose its more for my own documentation, but if it helps someone else out with their own development struggles, even better.

Today, I wanted to find a solution to updating pagination using AJAX. My issue was I use AJAX to update the DOM to remove an item when its deleted. However, the pagination doesn’t update and the listings don’t adjust as you delete them from the middle of the list. My solution, while not rocket science, I think is pretty cool. Basically, just keep using AJAX!

The first thing I need is a div to encapsulate my list. Something like:

     <div id="my_list">
          <%= render :partial => "items", :collection => items %>
          <%= will_paginate items, :renderer => 'ItemLinkRenderer' %>
     </div>

Obviously, that’s my original list inside the my_list div. I’ll get to what ItemLinkRenderer is in a big.

I delete my items from the list by updating the dom from within the delete action. So, something like this:

    @item = Item.find(params[:id])
    if !@item.nil?
        @item.destroy
        render(:update) { |page|
            page.remove dom_id(@item)
        }
    end

This should look pretty straight forward. Delete the item from the database, then remove it from the current document.

But what about updating the pagination and the list? We can remove an item, but how do we adjust the displayed list? Well, just fetch the list of items again.

    @items = Item.paginate :all, :page => params[:page], :per_page => 10
    if @items.length > 0
        page.replace_html "my_items", :partial => "items", :locals => {:items => @items}
    else
        page.replace_html "my_items", "<p>You have no items.</p>"
    end

Ok, so we can render the items. But, if you put this in, then start deleting items, you’ll notice your pagination links get messed up and you have your delete action in the URL. This isn’t good, but, like I mentioned earlier, this is where ItemLinkRenderer comes in. You can define a helper class called ItemLinkRenderer (in item_link_renderer.rb) to render your links properly.

    class ItemLinkRenderer < WillPaginate::LinkRenderer
        def page_link_or_span(page, span_class = 'current', text = nil)
            text ||= page.to_s
            if page and page != current_page
                @template.link_to text, :controller => "items", :action => "list", :page => page
            else
                @template.content_tag :span, text, :class => span_class
            end
        end
    end

This will render your pagination links properly. Hopefully this works out well for anyone who stumbles upon this. Let me know if it does or if you find any errors with what I’ve presented.

Accessing “Child” Associations in Ruby on Rails

Ruby on Rails
My good buddy Dan of SecondRotation.com helped me out with a Rails problem last night. I wanted to access the associations defined on an association of one of my model classes when calling find, in essence, accessing a “child” association. I looked high and low for this, but with no luck so Dan was able to come to my rescue. He said you can do this:

@collection = MyClass.find(:all, :conditions => ["id = ?", params[:id]], 
      :include => [:foo => [:bar]], :order => sort)

I guess using :include like this is will tell Rails and ActiveRecord that you want to include the Bar class association in the JOIN you’re doing in SQL so you can enhance your query. Makes sense, but too bad it seems to be hardly documented!

AJAX Pagination and Sorting in Ruby On Rails

I recently decided the account section of a Rails application I’m working on will be completely AJAX. Every link the user would click on would just replace a section of the account page giving them the impression that they’ve never left their account section because the URL isn’t changing. However, I needed to do pagination and sorting for lists of different things. So hunting on Google I went.

I first came across this article over at Rails on the Run about how to do it with will_paginate, prototype, and low pro. I mucked around with it for about 30 minutes and definitely had some struggles, so I went back to Google. I eventually came across this article at Redline Software’s Weblog about an easier way to do it with will_paginate. The nuts and bolts of it is you can use a helper class to write your pagination links for you very easily (I won’t steal their code and post it here. Check out the link to grab it.)!

But I’m not done yet. Remember, I also need to be able to sort my lists of data. So I ran with the same idea presented by Redline Software and came up with this way to write out the anchor tags for my sort links:

def sort_remote_url(text, value)
    value += "_reverse" if params[:sort] == value
    @template.link_to_remote text, {:url => params.merge(:sort => value)}
end

What sort_remote_url does is take in the text for the link and the value of the sort parameter. When you click on the sort link, it works just like the pagination and updates the current view.

Sorting Geographical Based Search Results In Ruby on Rails

Ruby on Rails

I’ve spent the last few months on a Ruby on Rails project for a client. I’m integrating a lot of different applications into it, creating quite the “mashup”. One part of the project requires the ability to search the system for results that fit within a radius of a given postal code. So to do this, I need some sort of searching algorithm or application and a geocoding application for zip code relationships. The search results need to be able to be sorted by the different attributes on the results.

So this meant I needed several pieces. One was a searching module. I found ferret and the acts_as_ferret Rails plugin to do full text searching. From what I could gather online, this was one of the best solutions out there. I want to be able to display distances between zip codes, which I can do using GeoKit. So I find myself off and running.

I was able to do everything successfully from getting the right results back to calculating distances (Side note. If you need a start with acts_as_ferret, there’s a good article here at Rails Envy). However, because the distances between zip codes are calculated and not part of the ferret index, I can’t sort by results. Uh oh…

The solution was, in my opinion, a hack, but it works. What I did was let acts_as_ferret handle sorting for everything except distances (it couldn’t do it anyway, so fine). After I get my results back, I decided, well, I guess I can sort them again, right? So, let’s do this:

@total, search_results = MyModel.full_text_search(@search_term, 
  {:sort => s},
  {:include => [:zip_code],
    :conditions => conditions})

This gets me my search results. What about distances? Well, this can be done, even though its an issue performance wise:

for sr in search_results
   sr.destination_distance = round_to(sr.zip_code.distance_to(@search_zip_code), 2)
end

So now each result knows what its distance is from the searched upon zip code. Now what about sorting?

if params[:sort] == "distance"
    search_results = search_results.sort
    @total = search_results.length
elsif params[:sort] == "distance_reverse"
    search_results = search_results.sort
    search_results = search_results.reverse
    @total = search_results.length
end

So now you’re thinking, ok, but how do you know how to sort MyModel? Easy, I decided I’d override <=> for the MyModel class so that a MyModel was less than, greater than, or equal to another MyModel based on distance. So I did this:

def <=>(item)
    if self.destination_distance < item.destination_distance
      return -1
    elsif self.destination_distance > item.destination_distance
      return 1
    else
      return 0
    end
end

So you can see with the example above, I can sort by just calling sort. To reverse the sort, just call reverse after sorting.

So there you go, sorting by distance values. There are definitely drawbacks with this method. First, you have to iterate over all of the search results to set the distance on them. Second, what if I need to sort by some other calculated value? Since I overroad <=> for distance, I can’t really do it for another value. But for now, this works. Maybe I, or someone else, can come up with a better solution.

Uploading and Resizing Images in Ruby on Rails

ImageMagick

In my previous article on using ImageMagick and Mini-Magick to manipulate images in Ruby on Rails, I talked about how to install all of the goodies you’d need to work with images in Rails. I thought I’d expand on this a little bit more and give an example on how I used this cool stuff to upload images and resize them in my Rails application.

You’ll need to set up some HTML code to upload the file to the server. Something like this will suffice:

<% form_tag :action => 'upload', :multipart => true, :id => 'upload_form' do -%>
     <input style="margin-left: 5px;" type="file" id="imageone_file" name="imageone[file]" />
<% end -%>

Now you’ll want to build a model (based on ActiveRecord or not) to save your image for you. For my use, I did based my image model on an ActiveRecord class since I wanted to at least store the file name of the image in my database. But doing that is up to you. Anyway, on to saving the image. In your class, you want to grab the data for the image file in the posted form and save it to the file system. Something like this will suffice:

def image_save(file)
    @file = file
    @content_type = file.content_type.chomp
    @original_filename = base_part_of(file.original_filename)
    @extension = @original_filename[@original_filename.rindex(".") .. @original_filename.length].strip.chomp
    
    self.file_name = "#{epoch_time()}#{@extension}"
    
    is_saved = false
    begin
      if self.file
        if self.content_type =~ /^image/
          # Make the directory for the id of the listing if it doesn't exist
          Dir.mkdir("#{RAILS_ROOT}/public/images/originals/") unless File.exists?("#{RAILS_ROOT}/public/images/originals/")
          
          # What's the new file name?
          
          # Create the temporary file
          File.open("#{RAILS_ROOT}/public/images/originals/#{self.file_name}", "wb") do |f|
            f.write(@file.read)
            f.close
          end
          
          # Crop the image to the sizes we need
          crop()
          
          is_saved = true
        end
      end
    rescue
    end
    
    return is_saved
end

So what are we doing here? First, we grab the content type of the file, its original file name, and the extension of the file. We save this information out to attributes defined on the model itself, i.e.

attr_accessor :file, :content_type, :original_filename, :extension

Then we check to make sure the directory where we want to save the original file exists, and if not, create it. Then we save the file itself. Once we have the file saved, you’ll notice I call a method called crop(). This is my method that resizes the original image and saves the resized images to the file system. How do I do that? Check this out:

  def crop()
    image = MiniMagick::Image.from_file("#{RAILS_ROOT}/public/images/originals/#{self.file_name}")
    if !image.nil?
      # Resize to 360x360
      image.resize "360x360"
      image.write("#{RAILS_ROOT}/public/images/360x360/#{self.file_name}")

      # Resize to 240x240
      image.resize "240x240"
      image.write("#{RAILS_ROOT}/public/images/240x240/#{self.file_name}")

      # Resize to 120x120
      image.resize "120x120"
      image.write("#{RAILS_ROOT}/public/images/120x120/#{self.file_name}")

      # Resize to 80x80
      image.resize "80x80"
      image.write("#{RAILS_ROOT}/public/images/80x80/#{self.file_name}")
      
      # Resize to 40x40
      image.resize "40x40"
      image.write("#{RAILS_ROOT}/public/images/40x40/#{self.file_name}")
    end
  end

As you can tell, I needed several different image sizes. You start with the lowest size and work your way down. Not doing this gets you funky sized images. MiniMagick makes it really easy to just open the file and set the new size for the image and then just write it out to where you want it. Nice!

Ruby on Rails Image Manipulation with ImageMagick and Mini-Magick on OS X

I’m working on a Ruby on Rails project that requires users to be able to upload images. At the same time, we want to resize images so that they appear as we want them to on site. To do this, I found that the best solution would be to use the Ruby Gem Mini-Magick which uses ImageMagick. The benefits of using Mini-Magick is that its lighter weight that just using RMagick. So away I went…

I develop my Rails applications on OS X, so I thought I might have most of the stuff already that I’d need since XCode was installed. I had ImageMagick installed from a previous PHP project I had worked on, so I figured I’d just install the Ruby Gem Mini-Magick.. I did and hooked it up to my application. When running it though, it didn’t work. Bummer. I kept getting cryptic errors like:

ImageMagick command (identify "/tmp/minimagick99445-0.jpg") failed: Error Given 256

Great, what does that mean? So I did some sleuthing on Google and didn’t have much luck for about an hour or so. Then I came across this post at MattKing.org. How could I have missed this? A no brainer that you need to have the image libraries installed before compiling ImageMagick (and thus mini-magick).

So with out further ado, here are the steps you need to perform to get this to work!

Step One – Download Image Libraries

Before compiling and installing ImageMagick, you need to have all of the image libraries installed for the image types you want to manipulate. In my case, I wanted to support JPG, GIF, PNG, and TIFF. So I had to install the following libraries:

Once you have those downloaded, you can go on to Step 2

Step Two – Install Image Libraries

Now that you have all of the image libraries downloaded, its time to install them. Extract them using tar and install them!

JPEG

tar xzvf jpegsrc.v6b.tar.gz
cd jpeg-6b
./configure
make
sudo make install

LibPNG

tar xzvf libpng-1.2.24.tar.gz
cd libpng-1.2.24
./configure
make
sudo make install

GifLib

tar xzvf giflib-4.1.4.tar.gz
cd giflib-4.1.4
.configure
make
sudo make install

LibTiff

tar xzvf tiff-3.8.2.tar.gz
cd tiff-3.8.2
.configure
make
sudo make install

Step Three – Download & Install ImageMagick

With all of the image libraries installed, you can download ImageMagick. I installed mine to the /usr/ directory, but I think /usr/local/ would work as well.

tar xzvf ImageMagick-6.3.8-9.tar.gz
cd ImageMagick-6.3.8
./configure --prefix=/usr/
make
sudo make install

Step Four – Install ImageMagick

You’re almost there! Now that you have all of the image libraries installed and ImageMagick installed, you can go ahead and install the Ruby gem Mini-Magick

sudo gem install mini_magick

One note that I found very helpful on Matt King’s blog post was to check to make sure the configure script for ImageMagick could find the image libraries you wanted to be able to use. Check the output at the end of the configure script and make sure yes is present next to each image library you want to use.

You should be ready to rock now! To use mini-magick, insert the following lines into your environment.rb file:

require 'rubygems'
gem 'mini_magick'
require 'mini_magick'

Now that you’re all set up, you can load up a file and do whatever you want to it using Mini-Magick. Perhaps something like this!

filename = "path to your file"
fileout = "path to output file"
image = MiniMagick::Image.from_file(filename)
image.resize "120x120"
image.write(fileout)

There you go! If something doesn’t work, the first thing I’d check is to make sure all of the libraries and ImageMagick were installed properly. Also check file permissions in case for some reason the directory you’re trying to save your file is locked down so the web server user can’t write to it.

One more side note before I finish. I was able to use these exact steps to install ImageMagick and Mini-Magick on my Debian server which I’m using for my public test environment. So, that cool thing about using these steps installing everything from source allows you to duplicate on other *NIX systems.