ruby on rails


2
Mar 09

Paperclip not saving your images?

I’ve had a few guys email me asking if I had any idea why Paperclip wasn’t saving their uploaded images. Here’s a form one of them sent me:

<% form_for(@post) do |f| %>
  <%= f.error_messages %>


    <%= f.label :title %>
    <%= f.text_field :title %>
 


    <%= f.label :description %>
    <%= f.text_area :description %>
 

  <%= f.file_field :image %>


    <%= f.submit "Update" %>
 

<% end %>

Notice anything different on this form?

<% form_for(@post, :html => { :multipart => true }) do |f| %>
  <%= f.error_messages %>


    <%= f.label :title %>
    <%= f.text_field :title %>
 


    <%= f.label :description %>
    <%= f.text_area :description %>
 

  <%= f.file_field :image %>


    <%= f.submit "Update" %>
 

<% end %>

Simple mistake, but I’ve done it a few times in the early AM and wondered WTF was going on!

:html => { :multipart => true

21
Feb 09

Check if a file exists in Rails

Recently I was porting a legacy PHP application to Rails. One of the primary tasks was to resize a bunch of images. Below you can see what one of the database rows looks like.

mysql> SELECT id, filename FROM old_posts
+----+---------------------------------------+
| id | filename                              |
+----+---------------------------------------+
|  1 | unxplained-photo-1225258423-85706.jpg |
+----+---------------------------------------+
1 row in set (0.00 sec)                                                                  

mysql>

You’ll see that the name of the filename is stored in the database, the problem I encountered was that often times the actual file didn’t exist even though the record remained in the database.

Rails would get angry at me when I tried to resize an non-existent file. To account for this, I did the following:

if FileTest.exists?(filename)
 # some code here to
 # resize the image
end

For more information on this handy ruby module pop into the docs.


20
Feb 09

Rails’ symbols: don’t create them dynamically!

Symbols are great, we use them in hashes all the time…but did you know, symbols aren’t part of Rails’ garbage collection? When you create them, the memory the use has been allocated permanently! Why is this bad? So if we create a handful of symobls…no biggie, but what if we’re dynamically creating lots and lots of them? Major faux pas!

This was brought to my attention last night when I was trying to create a hash with some dynamic symbols. See below:

## here is some data

>> hardware = Hardware.find(:all, :limit => 2)
=> [#<Hardware id: 1, name: "Bolts", description: "Lorem ipsum dolor sit amet, consectetur adipisicing...", photo_front_file_name: "144_replica_wheels_Closeout_30_percent_off_prices_l...", photo_front_content_type: "image/jpeg", photo_front_file_size: 80842, photo_angle_file_name: nil, photo_angle_content_type: nil, photo_angle_file_size: nil, created_at: "2009-02-19 11:04:48", updated_at: "2009-02-20 20:29:46">, #<Hardware id: 2, name: "Nuts", description: "Lorem ipsum dolor sit amet, consectetur adipisicing...", photo_front_file_name: nil, photo_front_content_type: nil, photo_front_file_size: nil, photo_angle_file_name: nil, photo_angle_content_type: nil, photo_angle_file_size: nil, created_at: "2009-02-19 11:04:48", updated_at: "2009-02-20 07:18:32">]
>> y hardware.first
--- !ruby/object:Hardware
attributes:
  name: Bolts
  updated_at: 2009-02-20 20:29:46
  photo_angle_file_size:
  photo_front_file_name: 144_replica_wheels_Closeout_30_percent_off_prices_listed_.jpg
  photo_front_file_size: "80842"
  id: "1"
  description: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in recodehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  photo_angle_content_type:
  photo_front_content_type: image/jpeg
  created_at: 2009-02-19 11:04:48
  photo_angle_file_name:
attributes_cache: {}

=> nil
## don't do this
for hardware_item in hardware
 formatted[:#{hardware_item.name.downcase}] = hardware_item.description
end

>> formatted[:bolts]
=> "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in recodehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

## this is better
for hardware_item in hardware
 formatted[hardware_item.name.downcase] = hardware_item.description
end

>> formatted['bolts']
=> "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in recodehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

19
Feb 09

rake db:migrate for production databases

After I updated one of my applications that I’ve been working on, I kept running into an internal server error. I looked at the logs and for some reason none of my SQL queries were working.

Looks like I ran “rake db:migrate” and migrated the development database…not the production one. I scratched my head trying to remember the command. Here it is!”

rake db:migrate RAILS_ENV=”production”

18
Feb 09

All Rails crash course tutorials are available on GitHub!

ZIP files are silly :)

I’ve created a GitHub repository for all the tutorials to date and plan on using GitHub to version control all future applications. I will be editing the posts and removing any old download links shortly.

The repository is located at:
http://github.com/ng/crashcourse/tree/master

Want to check out the code? Run this in terminal:

git clone git://github.com/ng/crashcourse.git

Don’t have git installed? If you’re on OSX it’s simple!
http://code.google.com/p/git-osx-installer/


17
Feb 09

Paperclip doesn’t accept multiple files in Rails 2.3

Those of you who have upgraded to Rails 2.3 may have encountered a bug where Thoughtbot’s Paperclip doesn’t want to accept multiple file attachments. I checked my models, migrations, and forms but I couldn’t figure it out for the life of me.

It turns out there is some kind of bug with the Rack interface that is wonky in 2.3. By updating to edge Rails I was able to fix this little bug.


17
Feb 09

MySQL gem on OSX Leopard 10.5.x

I started to play with Rails 2.3 and ran into a little issue trying to access my database. I guess I shouldn’t have been ignoring all those decodeciation warnings…oops. Naturally, the first thing I did was run “sudo gem install mysql” which threw the following error:

ng$ sudo gem install mysql
Building native extensions.  This could take a while...
ERROR:  Error installing mysql:
  ERROR: Failed to build gem native extension.

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb install mysql
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... no
checking for mysql_query() in -lmysqlclient... no

Gem files will remain installed in /Library/Ruby/Gems/1.8/gems/mysql-2.7 for inspection.
Results logged to /Library/Ruby/Gems/1.8/gems/mysql-2.7/gem_make.out

After digging around, I found the following command:

sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
Building native extensions.  This could take a while...
Successfully installed mysql-2.7
1 gem installed

Looks like it was successful…but wait, let’s check. Pop into IRB:

>> require 'mysql'
LoadError: dlopen(/Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle, 9): Library not loaded: /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib
  Referenced from: /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
  Reason: image not found - /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
  from /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
  from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:36:in `require'
  from (irb):1

Further searching revelaed the solution:

sudo install_name_tool -change /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib /usr/local/mysql/lib/libmysqlclient.15.dylib /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle

16
Feb 09

adapter: mysql (ArgumentError)

I was up late working on a project and I kept running into this error after I tried to deploy to my staging server. It turns out you can’t use tabs in a YAML file. Oops..after I removed the tabs and used spaces my app started successfully.

/usr/lib64/ruby/1.8/yaml.rb:133:in `load': syntax error on line 18, col 3: `   adapter: mysql' (ArgumentError)
  from /usr/lib64/ruby/1.8/yaml.rb:133:in `load'

  from /usr/lib64/ruby/gems/1.8/gems/rails-2.1.2/lib/initializer.rb:716:in `database_configuration'
  from /usr/lib64/ruby/gems/1.8/gems/rails-2.1.2/lib/initializer.rb:340:in `
initialize_database'
  from /usr/lib64/ruby/gems/1.8/gems/rails-2.1.2/lib/initializer.rb:124:in `process'

  from /usr/lib64/ruby/gems/1.8/gems/rails-2.1.2/lib/initializer.rb:97:in `send'
  from /usr/lib64/ruby/gems/1.8/gems/rails-2.1.2/lib/initializer.rb:97:in `
run'

15
Jan 09

unable to read font during ImageMagick/RMagick installation

I was installing Rmagick earlier on OSX and ran into a little hiccup, during the installation I recieved the following error:

unable to read font `/System/Library/Fonts/Times.dfont’

After about 30 minutes of digging, I found the solution! Open up Font Book and remove any duplicate fonts; duplicate fonts have a small black dot next to their names.


24
Jun 08

Basic HTTP Authentication and Partials

Hello again! I’ve been quite busy in between jobs and haven’t had much free time to work on my postings…well, let’s make up for lost time! Last time we spoke, I left you with a Rails app that made use of a basic relational database that contained books and associated authors. Let’s move the chains and introduce a few new concepts that you’ll be able to use with your own applications.

In this installment we’re going to create a landing page so visitors don’t get dumped to your book controller, use a partial, learn about the before_filter, and add some basic HTTP authentication.

if/for blocks and Rails’ partials

The first thing we’re going to do is create a new landing page so visitors don’t get dumped onto the scaffolding, but first reset the database. I had some random entries there I wanted to wipe out, we can do this with:

ng:bookstore ng$ rake db:reset

Next, we’ll be generating a new controller to handle the requests for our landing page; following convetion this controller will be plural…call it “homes”.

ng:bookstore ng$ script/generate controller homes
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/homes
      exists  test/functional/
      create  app/controllers/homes_controller.rb
      create  test/functional/homes_controller_test.rb
      create  app/helpers/homes_helper.rb
ng:bookstore ng$

If you try to access http://localhost:3000/homes you’ll get a routing error; know what to do? Bingo! Let’s add a resource to our route and change the default map.root controller. I’ve removed the comments, but your routes.rb file should look similar to this:

ActionController::Routing::Routes.draw do |map|
  map.resources :authors
  map.resources :books
  map.resources :homes

  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
  map.root    :controller => 'homes'
end

Now that our routes are set up, we need to create an index.html.erb file. We’ll place this in the apps/views/homes directory. You will be able to access the homes controller by either of these urls:

  • http://localhost:3000/
  • http://localhost:3000/homes

Our index file is quite barren right now, let’s add some code to so we can list our current book inventory. First, we need data to play with! Open your apps/controllers/homes_controller.rb and add an index method. Let’s pull all records from our database and make it available to our view.

class HomesController < ApplicationController

  def index
    @books = Book.find(:all)
  end

end

Now that we’ve defined our data, we can loop through it using a basic for loop. I’ve set up the table structure with a header row, the individual rows are generated by our loop.

<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
  </tr>
  <% for book in @books %>
  <tr>
    <td><%=h book.title %></td>
    <td><%=h book.description %></td>
  </tr>
  <% end %>
</table>

It essentially reads, “For each book in our @books collection, output a row with two columns. In in first column output an html escaped book title, in the second column output a html escaped book description. Once we’ve cycled through all the data in our @books collection, end the loop.”

I’m going to plug the above code into our index file.

<h1>Our Bookstore</h1>

<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus sed nisi. Morbi aliquam ornare metus. Aliquam sed pede quis nulla porta rhoncus. Ut adipiscing aliquam enim. Sed laoreet justo in turpis. Aenean metus lorem, mollis elementum, pulvinar non, pharetra at, metus. Phasellus interdum tortor non tellus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer facilisis, erat sed aliquam tristique, mi augue tristique mauris, in mollis turpis tellus vel sem. Vivamus ac nibh ac lectus venenatis blandit. Morbi eget sem ac turpis sodales tincidunt. In in nunc commodo ante venenatis ornare. Aliquam sit amet ligula. 
</p>

<h2>Current Inventory</h2>
<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
  </tr>
  <% for book in @books %>
  <tr>
    <td><%=h book.title %></td>
    <td><%=h book.description %></td>
  </tr>
  <% end %>
</table>


<p>Aliquam vestibulum ultricies velit. Vivamus pulvinar urna. Mauris tincidunt blandit massa. </p>

Visit your bookstore. It looks kind of weird with no books eh? Let’s notify our visitors that we don’t have any books in stock; we’ll do this with a simple if statement.

<h1>Our Bookstore</h1>

<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus sed nisi. Morbi aliquam ornare metus. Aliquam sed pede quis nulla porta rhoncus. Ut adipiscing aliquam enim. Sed laoreet justo in turpis. Aenean metus lorem, mollis elementum, pulvinar non, pharetra at, metus. Phasellus interdum tortor non tellus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer facilisis, erat sed aliquam tristique, mi augue tristique mauris, in mollis turpis tellus vel sem. Vivamus ac nibh ac lectus venenatis blandit. Morbi eget sem ac turpis sodales tincidunt. In in nunc commodo ante venenatis ornare. Aliquam sit amet ligula. 
</p>

<% if @books.empty? %>
<h2>We don't have any books in stock, but they're coming!</h2>
<% else %>
<h2>Current Inventory</h2>
<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
  </tr>
    <% for book in @books %>
    <tr>
      <td><%=h book.title %></td>
      <td><%=h book.description %></td>
    </tr>
    <% end %>
</table>
<% end %>

<p>Aliquam vestibulum ultricies velit. Vivamus pulvinar urna. Mauris tincidunt blandit massa. </p>

Pretty cool eh? It’s these little methods that make me smile! Let’s take another look at our index file…take a peek and ask yourself if anything looks out of place? Does that for loop bother you? It bothers me! I don’t like to see lots of code in my views…let’s get rid of it!

Rails has a handy feature called partials; partials are little fragments of code that can be included, and reused in your views. All partials take follow the same naming convention: “_filename.mimetype.erb”. Don’t worry about mimetypes right now, for the most part you’ll be something like _filename.html.erb or _filename.xml.erb. Create a new partial named named “book listings”, then place our if/for block in the partial.

<!-- _book_listings.html.erb -->
<% if @books.empty? %>
<h2>We don't have any books in stock, but they're coming!</h2>
<% else %>
<h2>Current Inventory</h2>
<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
  </tr>
    <% for book in @books %>
    <tr>
      <td><%=h book.title %></td>
      <td><%=h book.description %></td>
    </tr>
    <% end %>
</table>
<% end %>

Now that we have a partial, we need to call it. render :partial => ‘partial_name’. Render the partial in our index view where our old if/for block was.

<!-- index.html.erb -->
<h1>Our Bookstore</h1>

<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus sed nisi. Morbi aliquam ornare metus. Aliquam sed pede quis nulla porta rhoncus. Ut adipiscing aliquam enim. Sed laoreet justo in turpis. Aenean metus lorem, mollis elementum, pulvinar non, pharetra at, metus. Phasellus interdum tortor non tellus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer facilisis, erat sed aliquam tristique, mi augue tristique mauris, in mollis turpis tellus vel sem. Vivamus ac nibh ac lectus venenatis blandit. Morbi eget sem ac turpis sodales tincidunt. In in nunc commodo ante venenatis ornare. Aliquam sit amet ligula. 
</p>

<%= render :partial => 'book_listings' %>

<p>Aliquam vestibulum ultricies velit. Vivamus pulvinar urna. Mauris tincidunt blandit massa. </p>

Rails’ before filter and basic HTTP authentication

Originally, I wanted to have us create a separate administrator section for administering the Books and Authors, but I think you’ll be able to do that on your own with the concepts we’ve worked on. Instead of a separate administrators section, let’s add some basic HTTP authentication to our Books and Authors controllers. By adding this authentication, we will be password protecting all calls to this controller. Here’s a snippet of code I use for basic access control:

def authenticate
  authenticate_or_request_with_http_basic do |user_name, password|
    user_name == "foo" && password == "bar"
  end
end

If we placed this method in our Books controller with the rest of our methods, anybody could call it by visiting books/authenticate; instead we’re going to place in a walled garden. Using Rails you have two options to protect your methods: private and protected. If you’re curious what they both do, here’s an an excerpt from RubyLearning:

  • Protected methods can be invoked only by objects of the defining class and its subclasses. Access is kept within the family. However, usage of protected is limited.
  • Private methods cannot be called with an explicit receiver – the receiver is always self. This means that private methods can be called only in the context of the current object; you cannot invoke another object’s private methods.

We’ll be using the protected method, we can do this by wrapping it like so:

class BooksController < ApplicationController  
  # note: I've truncated the methods after index

  before_filter :authenticate

  # GET /books
  # GET /books.xml
  def index
    @books = Book.find(:all)

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @books }
    end
  end

protected

  def authenticate
    authenticate_or_request_with_http_basic do |user_name, password|
      user_name == "foo" && password == "bar"
    end
  end

You may have noticed before_filter :authenticate before all of our methods. This is part of the master plan! By adding a “before_filter” we’re asking Rails to call authenticate (which we’ve defined). As is, authenticate is called before any method; often you’ll have a situation where you only want to apply the before_filter to select methods. Check this out:

# apply authenticate to all methods
before_filter :authenticate

# apply authenticate to all methods EXCEPT index, and show
before_filter :authenticate, :except => [:index, :show]

# apply authenticate to ONLY the index and show
before_filter :authenticate, :only => [:index, :show]

So let’s review…in the codevious section: we created a new landing page for our visitors, played with some if and for blocks, added basic HTTP authentication, and had a crash course on the before_filter. I’m sure you’ve been playing with the app in your browser, but if you haven’t…load up http://localhost:3000/books and you should be greeted with a familiar authentication dialog box!

Leave a comment, or send me an email with ideas for future articles! I wanted to cover SEO friendly URLs, validations, and a whole lot more this time but I wanted to get you guys an update sooner than later! Useful? Donate to my beer fund or digg this!

More Rails reading:

Understanding Rails partials