Archive

Archive for February, 2009

Getting started with engines development in rails 2.3

February 4, 2009 4 comments

Rails 2.3 RC1 has just been released. There are number of new features like application templates, Metal points, Rack integration and support for Engines. Earlier engines plugins were not in much favour. But now since merb has similar feature in form of slices they have recently been back in favour and now the engines have made it to core. but not all feature has been ported as pointed out by post on rails engines site.

Lets get started with developing a simple plugin that uses engines feature of rails 2.3 RC1. This tutorial is based on rails flickr demo application. lets install latest 2.3 gems on your machine.


gem install rails --source http://gems.rubyonrails.org

Lets generate empty rails application and run plugin generator. There is no seperate generator for engines as engine plugin is type of plugin. Lets call our plugin flickr_search from application root issue this command


$ script/generate plugin flickr_search

This will generate a flickr_search folder in vendor/plugin which contains whole bunch of files which is empty skeleton for new plugin. since our plugin is based on flickr api you need to install flickr gem and get API key from http://www.flickr.com/services/api/misc.api_keys.html.


$ sudo gem install flickr

Now edit init.rb file in flickr_search folder and write out this code. Make sure you replace your API key in code


require 'rubygems'
require 'flickr'
MY_KEY='Enter your Flicker API Key'
class Flickr
alias old_initialize initialize
def initialize(api_key=MY_KEY, email=nil, password=nil)
puts "new_initialize " + MY_KEY
old_initialize(api_key, email, password)
@host="http://api.flickr.com"
@activity_file='flickr_activity_cache.xml'
end
end

With engines support in rails you can have same app folders in your plugin as well. so lets create app folder in flickr_search folder also create sub folders like controller, views, models and helpers as in any rails application. Lets create a controller file in controllers folder called flickr_controller.rb and create index action. Noew in views folder create layout folder and add layout file called flickrlayout.html.erb. Add this code to layout

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Flickr</title>
<%= javascript_include_tag :defaults %>
<%= stylesheet_link_tag 'flickr' %>
</head>
<body>
<%= yield %>
</body>
</html>

Notice that the code has some asset helpers. currently rails does not have support for seperate assets for plugin so we need to copy these style sheets and other assets to rails public directory. This can easily be done by writing few lines of code in install.rb file. but in our case we will simply create flickr.css file in public/stylesheets directory of main rails application. so lets create this file and copy these styles in it.


body {
background-color: #888;
font-family: Lucida Grande;
font-size: 11px;
margin: 25px;
}

form {
margin: 0;
margin-bottom: 10px;
background-color: rgb(222,231,236);
border: 5px solid #333;
padding: 25px;
}

fieldset {
border: none;
}

#spinner {
float: right;
margin: 10px;
}

#photos img {
border: 1px solid #000;
width: 75px;
height: 75px;
margin: 5px;
}

Lets create a view for searching flickr images. In app/views directory of you plugin create index.html.erb file. Copy this code in it


<% form_remote_tag :url => {:action => 'search'}, :update => 'photos' do %>
<fieldset>
<label for="tags">Tags:</label>

<%= text_field_tag 'tags' %>
<%= submit_tag 'Find' %>
</fieldset>

<div id="photos"></div>
<% end %>

Create a search action in flickr_controller.rb file that gets called by AJAX action in index.html.erb view. Now your controller code should look like this


class FlickrController < ApplicationController

layout "flickrlayout"

def index
end

def search
flickr = Flickr.new

if params[:tags].empty?
render :text => '<h2>Please enter a search string</h2>'
else
begin
photos = flickr.photos(:tags => params[:tags], :per_page => '24')
render :partial => 'photo', :collection => photos
rescue NoMethodError
render :text => '<h2>No matching photos found</h2>'
end
end
end
end

Also create _photo.html.erb partial in views/flickr folder. this will contain this line of code


<img class='photo' src="<%= photo.sizes[0]['source'] %>">

With engine you can also add routes with routes.rb file. so lets create config folder in plugin root folder and add routes.rb file. you can add custom route for flickr search here


ActionController::Routing::Routes.draw do |map|
map.pics '/pics', :controller => 'flickr'
end

Now go ahead and run your application the flickr search should be working on http://0.0.0.0:3000/pics

One thing about migrations there is still no way to have seperate migration in engines plugin you would still need to generate and copy migrations to main applications db/migrate folder.

Advertisements
Categories: Ruby Language