Category Archives: RubyOnRails

Paperclip, Amazon S3 and CNAME’s

On Amazon S3 you can access your files through different URL’s, depending on which suites best your requirements:

  • Your bucket as “folder”: http://s3.amazonaws.com/your-bucket/your-file.txt
  • As subdomain: http://your-bucket.s3.amazonaws.com/your-file.txt
  • With a CNAME on your own domain: http://images.my-domain.com/your-file.jpg

How to setup a CNAME with Amazon S3 is explained pretty well here.

I had however some trouble setting up the correct URL to this CNAME in Paperclip, the popular Rails gem for handling file uploads.

This is the final configuration which is working for me is:

has_attached_file :image,
      :storage => 's3',
      :s3_credentials => { :access_key_id => ENV['S3_KEY'], :secret_access_key => ENV['S3_SECRET'] },
      :s3_headers => { 'Expires' => 1.year.from_now.httpdate },
      :s3_host_alias => 'subdomain.my-domain.com',
      :bucket => 'subdomain.my-domain.com',
      :url => ":s3_alias_url",
      :path => "/images/:class/:id_:basename.:style.:extension",
      :styles => { :thumb  => '70x70#',
      							:medium => '350x350',
      							:original => '1000x1000>' },
      :default_style => :original,
      :convert_options => { :all => '-strip -trim' }

I’m using Heroku as hosting service, therefore I save the S3 key and secret in an environment variable.
:s3_host_alias is the CNAME which you need to configure for your domain. The exact same string needs to be as well the name of the bucket.
Finally just assign “:s3_alias_url” to :url. Without that the URL won’t be generated correctly. You would end up with something like “http://s3.amazonaws.com/your-file.txt” which is missing entirely the bucket name and would not load the file.
Note that for this configuration it’s not necessary to define :bucket.

DeliciousTwitterFacebookLinkedInRedditSlashdotTechnorati FavoritesDiggShare
Posted in RubyOnRails | Leave a comment

Serialize / Deserialize nested objects in ActiveRecord

Using ActiveRecord’s serialize method you can save Ruby objects in a single field of your model. The serialization is done through YAML.

Today I tried to save a nested object structure with this method. These are the classes:

class PhotoStyle
  attr_accessor :image
 
  def initialize
    @image = StyleElement.new
  end
end
 
class StyleElement
  attr_accessor :selector, :style
 
  def initialize
    @selector = '*'
    @style = {}
  end
end

The model which saves a PhotoStyle object:

class Photo < ActiveRecord::Base
  serialize :style, PhotoStyle
end

This first approach didn’t quite work out. Saving the model worked fine, but when I loaded it only PhotoStyle got deserialized to the original type. The nested StyleElement didn’t:

p = Photo.last
p.style
=> #<photostyle:0xb70a906c @image=#<YAML::Object:0xb72079a4 @ivars={"selector"=>"#theimage", "style"=>{"border"=>"0", "box-shadow"=>"1px 3px 15px #555"}}, @class="StyleElement">}, @class="PhotoStyle">>
</photostyle:0xb70a906c>

Note the YAML object assigned to the @image instance variable.

I'm not sure if that's a bug in Rails3 or if that is by design. You can however "fix" it by running this code snippet when your application starts up:

YAML::Syck::Resolver.class_eval do
  def transfer_with_autoload(type, val)
    match = type.match(/object:(\w+(?:::\w+)*)/)
    match && match[1].constantize
    transfer_without_autoload(type, val)
  end
  alias_method_chain :transfer, :autoload
end

Save it e.g. in yaml_autoloader.rb in the config/initializers folder of your app.

Now all types will autoload:

#<photostyle:0xb73dcb08 @image=#<StyleElement:0xb73dd058 @selector="#theimage", @style={"border"=>"0", "box-shadow"=>"1px 3px 15px #555"}>> 
</photostyle:0xb73dcb08>

I found above code snippet here. Thanks!

Read more about ActiveRecord's serialize method here: Simple user preferences for your Rails app.

Update:
Still not sure if that's a bug, but I submitted a lighthouse ticket.

Update 2:
Apparently this is not a bug in Rails, but a problem in my code :-) Please see Aaron's comment in above ticket.

DeliciousTwitterFacebookLinkedInRedditSlashdotTechnorati FavoritesDiggShare
Posted in Ruby, RubyOnRails | 2 Comments

Heroku, Rails 3, RVM and Ubuntu

Today I tried to use Heroku on Ubuntu / RVM for a Rails 3 test app. I ran into a similar problem like I had yesterday with OpenSSL.

After installing the Heroku gem:

gem install heroku

and running the command for create a new app

heroku create

I got this error

/home/siebel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- readline (LoadError)
	from /home/siebel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
	from /home/siebel/.rvm/gems/ruby-1.8.7-p249/gems/heroku-1.9.10/lib/heroku/commands/app.rb:1
	from /home/siebel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
	from /home/siebel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
	from /home/siebel/.rvm/gems/ruby-1.8.7-p249/gems/heroku-1.9.10/lib/heroku/command.rb:5
	from /home/siebel/.rvm/gems/ruby-1.8.7-p249/gems/heroku-1.9.10/lib/heroku/command.rb:5:in `each'
	from /home/siebel/.rvm/gems/ruby-1.8.7-p249/gems/heroku-1.9.10/lib/heroku/command.rb:5
	from /home/siebel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
	from /home/siebel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
	from /home/siebel/.rvm/gems/ruby-1.8.7-p249/gems/heroku-1.9.10/bin/heroku:7
	from /home/siebel/.rvm/gems/ruby-1.8.7-p249/bin/heroku:19:in `load'
	from /home/siebel/.rvm/gems/ruby-1.8.7-p249/bin/heroku:19

Now, the first line looks darn familiar and so does the solution:

First install libreadline-dev:

sudo apt-get install libreadline-dev

Then cd into

~/.rvm/src/ruby-1.8.7-p249/ext/readline

and build the extension:

ruby extconf.rb
make
make install

That’s it… heroku should run after that without problems.

DeliciousTwitterFacebookLinkedInRedditSlashdotTechnorati FavoritesDiggShare
Posted in RubyOnRails | 26 Comments

OpenSSL, Rails 3 and Ubuntu

I’m using RVM on my Ubuntu box. This way I can nicely install several Ruby and Rails versions next to each other. With Rails 3 however I had a little bit of trouble. When starting the server using

rails server

the server started fine, but as soon as I clicked “About your application’s environment”, I got this error on the console:

LoadError: no such file to load -- openssl

If you’re getting this too the first thing to check is whether these packages are installed:

  • openssl
  • libssl-dev
  • libssl0.9.8

If they are and it anyway doesn’t work you want to go to the source code of your Ruby installation. In my case the source is in this path:

~/.rvm/src/ruby-1.8.7-p249

Now you cd to ext/openssl and run the following commands:

ruby extconf.rb
make
make install

After restarting WEBrick, everything was good:

For a more complete description on how to install Rails 3 on Ubuntu using RVM, checkout this blog post by Rohit Arondekar: Installing Rails 3.0 Beta 3 on Ubuntu using RVM

DeliciousTwitterFacebookLinkedInRedditSlashdotTechnorati FavoritesDiggShare
Posted in Linux, RubyOnRails | 3 Comments

Mobile_Fu, Internet Explorer and respond_to

Today I noticed that List Kung Fu displays the mobile version of the list page when I browse there with regular desktop Internet Explorer. Surfing to the same page with Firefox or Opera on the same machine worked fine and just returned the regular HTML page.

So what’s up?

Simple… Internet Explorer sends a really funny accepts header, none of the formats actually is text/html. Thus HTML is covered with an implicit */*. That’s not awesome (in good IE manner), but not really a problem. A problem it just becomes with something like this in your controller action:

      respond_to do |format|
        format.mobile
        format.html
      end

Since Internet Explorer doesn’t send an explicit accept for text/html, Rails would just default to the first format, in above case format.mobile and then correctly return the mobile version of the view. The fix is easy. Just move format.html to the first position:

      respond_to do |format|
        format.html
        format.mobile
      end

Now */* would default to format.html.

DeliciousTwitterFacebookLinkedInRedditSlashdotTechnorati FavoritesDiggShare
Posted in RubyOnRails | 1 Comment