Blog

Thursday, October 28, 2010

CarrierWave, an alternative to PaperClip for Uploading Files in Rails or Ruby Applications

I recently switched to CarrierWave: "Classier solution for file uploads in Ruby for Rack, Rails, Merb and Sinatra". Why? Here's three reasons:

  1. Uploading logic/handling is extracted into a separate class. Hence the tag "Classier solution". It addresses my sensibility for Single Responsibility and separation of concerns.
  2. It maintains a cache across redisplays. Meaning the user does not need to upload a file again, if other fields are invalid on the model.
  3. Dead easy upload from a remote URL.

Definitley give it a try. Anything I have missed? Let me know in the comments.

Wednesday, October 27, 2010

Redmine Estimated Time Summary Plugin

Redmine doesn't provide any summaries/totals for time estimated on issues out-of-the-box. If this is what you need, I highly recommend redmine_estimated_summary plugin.

Friday, October 22, 2010

Rail's ActiveRecord: include vs join

Confused when to use the :include vs. :join option? Remember these points:

  • join does not load the association into association
  • include does, it loads each association into memory
  • include is not compatible with select option
  • use include when the association is referenced
  • example use with join, doing a dynamic count on an association
  • or when the association is not referenced

Thursday, October 21, 2010

ActiveRecord::Base#becomes

An ActiveRecord method I did not existed: becomes.

Returns an instance of the specified klass with the attributes of the current record. This is mostly useful in relation to single-table inheritance structures where you want a subclass to appear as the superclass. This can be used along with record identification in Action Pack to allow, say, Client < Company to do something like render :partial => @client.becomes(Company) to render that instance using the companies/company partial instead of clients/client. Note: The new instance will share a link to the same attributes as the original class. So any change to the attributes in either instance will affect the other.

Web Integrator Application Hand-off Checklist

One scenario in developing applications, is the application is built and then handed off to a Web Integrator to implement the CSS. The other is templates are created and these are integrated by the web developer. This checklist is primary for the first scenario, but is probably applicable to the second. Here is a list of checks you should make before handing off for integration:

  • Demo data: Can the web integrator easily add demo data to the application. This should be done via a script.
  • Translation: If your application is multi-lingual, ensure all strings are in a locale file and the Web Integrator knows how to edit these. Spend some time teaching the Web Integrator on how it works.
  • Test translations: Before an application is translated, run the application in the secondary language to make sure that all "strings" for that language are missing. Check especially for emails static pages and built-in error messages, labels and attributes.
  • Language Switcher: Ensure a language switcher exists and is working.
  • Emails: If your application sends emails, ensure the developer can send and preview these easily. This can be done with the a script to send emails and a preview option via http. Rather than your application send emails, use a email service provider.
  • Minimize custom helpers: Helpers can be a roadblock for a Web Integrator not familiar with Rails. If you do use helpers, have the helper render a partial which can be easily customized.
  • Test accounts: Most applications are not standalone these days. If your application connects with external services such as Twitter and Youtube, ensure test accounts have been setup and can easily be used. You want to encourage the Web Integrator to use these integrations as much as possible. It's a great way to catch bugs!
  • Overlay option: Seen a web site without an overlay these days? Allow your Web Integrator to render a page without the entire layout easily. Passing a parameter along the URI is great way to do this.

Any thing I have missed? Please let me know in the comments.

Tuesday, October 19, 2010

Rails UJS using jQuery results in Unknown File Type/Prompted to save file with IE

I'm developing a Rails 2.3 project with the UJS file for Rails 3. Instead of the remote_form_fortags, I'm adding the data-remote attribute. This was running great on Safari and Firefox, but testing a form post on IE would result in the browser trying to save the file. There are a lot of posts regarding this issue, but none of them worked for me.

The fix ended up being very simple. Upgrade jQuery. The application was using 1.4.2. I upgraded to 1.4.3 and everything worked as it should under IE.

Related posts

Monday, October 18, 2010

Unix History Commands

!! : to run the previous command 
^P : move up through history list, one command at a time. (Up arrow key) 
^N : move down (or Down arrow key). 
!n : run nth command in history list. where n is a number from your history list. 
!n:p : only preview command number n (will not execute the command). 
!string : Run most recent command starting with characters in st

Source

Cached Key for ActiveRecord Collections

Last night I was doing some optimizations on Heroku utilizing Vanish, their reverse proxy server, and wanted to set an etag for an ActiveRecord collection. Basically I wanted to do something like this:

def index
    @videos = Video.published

    fresh_when :etag => @videos
    headers['Cache-Control'] = 'public'
   end

Surprisingly an ActiveRecord collection does not support the cache_key. Fortunately Jim Gay has written a gem, group_cache_key, to resolve this shortcoming. Just add the gem to your Gemfile and bundle install.

Thursday, October 14, 2010

Slow startup with Rspec (1.3.0) and Spork

This is probably network specific, because at my home office things are fine, but on site at a client, Rspec starts up very slow when running against spork. I tracked it down to line 19 in $GEM_PATH/gems/rspec-1.3.0/lib/spec/runner/drb_command_line.rb

DRb.start_service("druby://:0"); \

Change it to...

DRb.start_service("druby://127.0.0.1:0"); \

I think I have seen postings to the Rspec mailing list in regards to this issue. I will try to track them down to add to this post.

Update

It appears this is an OS X related issue. Checkout this thread for more information: http://www.ruby-forum.com/topic/154556. Thank you, Stuart.

Wednesday, October 13, 2010

Ensure all your external assets are SSL too

Just a quick reminder to link all your assets with https:// when they are under SSL. Since libraries such as jQuery are hosted by third parties such as Google, it's easy to forget to use https. When a user accesses a page under https and some assets are not accessed securely, the user will see a dreaded message warning that the page has some unsecured assets.

In Rails I use the request protocol which returns http: or https://

= javascript_include_tag "#{request.protocol}ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"

I have updated my Webmaster Launch Checklist to include this item.

Thursday, October 7, 2010

Pushing specific tags to Heroku

From the Heroku's October Newsletter, I thought that this was very helpful. Tag a release in Git:

git tag -a v1.1

And push it to Heroku:

git push -f heroku v1.1^{}:master

Allow the designer to easily preview Rails application emails

In my post Leave a project how you would like to find it, I discussed how to leave a project with a great README. I added another item to that, how to preview emails. When handing off a project to a designer to skin, an issue that arises is previewing the application emails.

In his Scaling Labs video, Greg Pollack suggests handing of application emails to an email service provider. I think that is a great idea, but sometimes if you are working on a short lived website that might be over kill. So my solution is to create a rake that a designer can easily use. Here's my recipe:

  • Create a separate config/mail.rb environment based on development.
  • Append config.action_mailer.delivery_method = :sendmail to the file.
  • Configure your database.yml with the same settings as your development environment.
  • Write your rake tasks.

Here an (edited) example of the rake task I wrote (lib/application.rake):

desc %{Sends test notification
Must specify RAILS_ENV=mail
EMAIL=you@example.com to specify email address}
    
task :send_notification => :environment do |t|
  registration = OpenStruct.new
  registration.first_name = Faker::Name.first_name
  registration.last_name = Faker::Name.last_name
  registration.email_address = ENV['EMAIL']
  
  CompetitionMailer.deliver_notification(registration)
end

Now run rake send_notification RAILS_ENV=mail EMAIL=nicholas@example.com. Check your email inbox!

Platform notes:

  • Rails 2.3.8
  • Mac OS X

There are other solutions that you may be interested in as well:

  • MockApp: "a native Mac application that embeds its own SMTP server. It also features an e-mail client browser, enabling instant viewing of both raw content and HTML rendering, so you can see how your mail looks when delivered".
  • MailTrap: "A mock SMTP server for use in Rails development".

Wednesday, October 6, 2010

Using rails.js, Rails 3 UJS in Rails 2 application

It took me a while to find these links over the weekend, so I thought I would list them here. I wanted to use the rails.js UJS in a Rails 2 application. I was specifically interested in using jQuery.

I hope you find these helpful. Any other UJS hints for Rails 2? Please add them to the comments.

Tuesday, October 5, 2010

Keeping it fun, knowing when to stop

On Sunday afternoon, I had the pleasure to design and modify my girlfriend's, Alex, MySpace page for her band. It was a really fun experience. Often my work is solitary, programming alone without a pair. Sunday was my first experience for a longtime working with a pair. While it wasn't pair programming, you could describe it as pair design. She had a vision, and I had the technical skill set. While the project was relatively simple, there were a few constraints we were working with: the MySpace interface and my design skill set. Through the afternoon, there were ideas being bounced between us, and refinements moving forward. I loved it.

The hours flew by, and before we knew it it was time for dinner. Alex was keen to keep going since we were so close. I knew in reality that we had another couple of hours to go. So I said, "I want to keep this fun". I knew after a couple of hours, we would be tired and hungry. No more fun.

So we stopped, published what we had, and committed to finishing it the following weekend. It kept it fun.

I think we need to stop more often to keep things fun. Often we just keep going for the sake of finishing something completely. The web is great medium where we can publish work in progress, and come back to refine it. Often we have this notion of only publishing "completed" work. In reality, it's never completed and will always need refinement.

How do you keep it fun? Let me know in the comments.

Saturday, October 2, 2010

Installing Redmine on Heroku with S3 Storage: Step by Step

Update: 15 August 2011This blog post was written almost a year ago. I haven't attempted to install Redmine on Heroku since then, so your milage may vary. I do intend to do an updated version in the future as this has been a very popular post.

I've started using Redmine this year, a project management web application, and I'm a big fan. I'm also a big fan of Heroku for deploying Rails applications. So, you know it makes sense -- deploy Redmine on Heroku! Here's how to do it step by step:

Initial Setup

$ mkdir your-company-redmine
$ cd your-company-redmine
$ git init
$ git remote add redmine git://github.com/edavis10/redmine.git
$ git fetch redmine
$ git merge redmine/1.0-stable
$ rake db:create RAILS_ENV=production

# if you don't have these installed
$ (sudo) gem install rails --version 2.3.5
$ (sudo) gem install rack --version 1.0.1

# setup database locally
$ RAILS_ENV=production rake db:migrate
$ RAILS_ENV=production rake redmine:load_default_data

$ rake generate_session_store

# add .gems
rails --version 2.3.5

$ mkdir tmp public/plugin_assets

# remove from .gitignore
/config/initializers/session_store.rb

$ git add .
$ git commit -m "Initial configuration"

Install Plugins

# install plugins, I like to use giternal
$ (sudo) gem install giternal

# add config/giternal.yml
redmine_heroku:
  path: vendor/plugins
  repo: http://github.com/edavis10/redmine_heroku.git
  
redmine_s3:
  path: vendor/plugins
  repo: http://github.com/tigrish/redmine_s3.git

$ giternal update
$ giternal freeze

$ git add .
$ git commit -m "Adds plugins"

Configure Heroku Plugin

# Remove from .gitignore
/public/plugin_assets

$ rake heroku:setup

Configure S3

# config/s3.yml

production:
  access_key_id: YOUR_S3_ACCESS_KEY_ID
  secret_access_key: YOUR_S3_SECRET_ACCESS_KEY
  bucket: YOUR_S3_REDMINE_PRODUCTION_BUCKET
  cname_bucket: false

development:
  access_key_id: YOUR_S3_ACCESS_KEY_ID
  secret_access_key: YOUR_S3_SECRET_ACCESS_KEY
  bucket: YOUR_S3_REDMINE_DEVELOPMENT_BUCKET
  cname_bucket: false
$ git add .
$ git commit -m "Configures S3 plugin"

Configure Sendgrid for Email

# remove from .gitignore
/config/email.yml

$ heroku addons:add sendgrid
$ heroku config


# configure config/email.yml
production:
  delivery_method: :smtp
  smtp_settings:
    address: "smtp.sendgrid.net"
    port: 25
    authentication: :plain
    domain: "heroku.com"
    user_name: "YOUR_SENDGRID_PASSWORD"
    password: "YOUR_SENDGRID_USERNAME"
$ git add .
$ git commit -m "Configures SendGrid for email delivery"

Deploy to Heroku

$ heroku create your-company-redmine
$ git push heroku deploy

# since we have the database setup locally, lets' push it
$ heroku db:push

Friday, October 1, 2010

Collapsing Margins in CSS

This is one of those rudimentary behaviours in CSS that I need to be reminded of once and a while. Top and bottom margins from adjacent elements will collapse. The element with the larger margin will prevail.

Collasping margins in CSS

Please note this blog is no longer maintained. Please visit CivilCode Inc - Custom Software Development.