Rails Plugins - Linux For You, March 2011 Issue


Published on

'Linux For You' article by http://foodlets.in founders Govind Naroji and Sagar Arlekar.

This is a tutorial on will_paginate (pagination), authlogic + omniauth (authentication) and paperclip (file attachments) plugins.

Published in: Education
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Rails Plugins - Linux For You, March 2011 Issue

  1. 1. Tutorial DevelopersRails Plug-insMaking site Development Easy!This article is a tutorial on how to use Rails plug-ins for pagination, authenticationand file attachments. It is aimed at readers with a basic knowledge of Ruby onRails programming.A plug-in is a wonderful way to package a frequently reference, we have made the source code of this app available implemented solution to a common problem and on GitHub: https://github.com/gnaroji/Events-Application. reuse the code. In case you had to build a blogging To create a new Rails app, issue the following command:application, you could use a blog plug-in, an authenticationplug-in, an image-upload plug-in, a comments plug-in and rails eventsa ratings plug-in. Plug-ins make it super simple to create an cd eventsapplication, and save a lot of effort, which in turn, allows youto focus on the user interaction, security and testing. Lets use a scaffold to get started: In this article, we will discuss some of the plug-ins thatmade our life easy while building Foodlets.in, a visual guide script/generate scaffold Event title:string description:stringfor restaurant food. start_date:date end_date:date user_id:integer For the purpose of this article, lets build a basic events-management application on Rails version 2.3.8. This app And here’s another scaffold for the User model:would have the Event and the User models. We shall addin features like user authentication, Facebook Connect, script/generate scaffold user login:string email:stringpagination for listing events, image attachment and the persistence_token:string crypted_password:string password_ability to use jQuery in place of the default libraries. For your salt:string www.LinuxForU.com | LINUX For YoU | March 2011 | 69
  2. 2. Developers TutorialPaperclip plug-in :message => "Attachment should be a jpg, jpeg or aThis plug-in adds an image to the event, and shows a png"thumbnail. It helps in handling file attachments and theirstorage on the server’s file-system. It allows uploaded files The first validation will verify that the image size is lessto be handled like regular model fields/properties. It also than 5 MB, and the second will verify that only JPEG andincludes methods to validate file size, file type, etc. Paperclip PNG images are stored.proves to be excellent while handling image attachments. Ituses Imagemagick to resize images and generate thumbnails. Changes to views To facilitate the upload of the image, we need to make theInstallation ‘new event’ and ‘edit event’ forms multi-part. Replace theInstall the plugin from the online git repository: following code…script/plugin install https://github.com/thoughtbot/paperclip.git # events/app/views/events/new.html.erb and events/app/views/ events/edit.html.erb This will install the paperclip plugin under events/ <% form_for(@event) do |f| %>vendor/plugins …with:UsageLet us add an image attachment to our Event model: # events/app/views/events/new.html.erb and events/app/views/ events/edit.html.erbscript/generate paperclip event image <% form_for(@event, :html => { :multipart => true } ) do |f| %> Paperclip comes with a generator, and this command will Then add the file field given below:create a migration named TIMESTAMP_add_attachments_image_to_event.rb in the events/db/migrate/ directory. This # events/app/views/events/new.html.erb and events/app/views/migration will add the following fields to the Event model: events/edit.html.erb • image_file_name <%= f.file_field :image %> • image_content_type • image_file_size To display the image thumbnail in the show and index • image_updated_at views, you should add the following helper: Run the migration, as follows: # events/app/views/events/show.html.erb and events/app/views/rake db:migrate events/index.html.erb <%= image_tag @event.image.url(:thumbnail) %> We need to specify in the Event model that it uses animage attachment. The code to be added to the model is: To learn more, check https://github.com/thoughtbot/ paperclip/wiki.# events/app/models/event.rbhas_attached_file :image, Will_Paginate plug-in:styles => {:thumbnail => "100x100#", :large => "500x500#"} This plug-in will allow us to implement pagination, i.e., to break a long list of data items into numbered pages. We shall The styles parameter mentions that we need a restrict listings to five events per page in the Event index view.thumbnail of size 100*100 pixels, and a large image ofsize 500*500 pixels. ‘thumbnail’ and ‘large’ are labels, Installationand could be words of the user’s choice. Lets add in a Install will_paginate from the online git repository:few validations: script/plugin install git://github.com/mislav/will_paginate.git# events/app/models/event.rbvalidates_attachment_size :image, :less_than => 5.megabytes, This will install the will_paginate plugin under events/ :message => "Image should be present and less than 5 vendor/pluginsMB in size"validates_attachment_content_type :image, Usage :content_type => [image/jpeg,image/png,image/ In the index method of EventsController (events/app/jpg], controllers/events_controller.rb), replace the following code…70 | March 2011 | LINUX For YoU | www.LinuxForU.com
  3. 3. Tutorial Developers @events = Event.all one change to the view for new user -- the form should capture only email, login and password fields. Now, you …with: must have noticed that our User model doesn’t have a password field, so how can we use it in the new form? Thats@events = Event.paginate(:per_page => 5, :page => params[:page], because the password is encrypted before it is stored—:order => updated_at DESC) Authlogic takes the value of your password, encrypts it and stores it in the crypted_password field. Here, the parameters are as follows: Once you associate a model with Authlogic, by default • :per_page: number of records on a page. it adds a set of validations for the fields. Most of the • :page: the number of the page to be fetched; the fields are optional, but password confirmation is required default is 1. by default; if you don’t need it, then set it to false. You • :order: to decide on the ascending or descending order can read more about the other fields at the Authlogic on a field. ActsAsAuthentic documentation. Other parameters like :conditions, :include, etc, can also Create the UserSession model:be used. For example, to list all events starting today, or in thefuture, you could add in a condition: script/generate session user_session@events = Event.paginate(:per_page => 5, :page => params[:page], Now create the UserSessionsController. Remember that :order => DATE(start_date) asc, :conditions => [start_date >= the sign-in will not require the user to be signed in, while?, Date.today]) sign-out can happen only if the user is already signed in. In the index view, add the following code wherever you # events/app/controllers/user_sessions_controller.rbwant the pagination links to appear: before_filter :require_no_user, :only => [:new, :create] before_filter :require_user, :only => :destroy# events/app/views/events/index.html.erb<%= will_paginate %> Add the following code to the new and create methods for the sign-in: For further reading, check http://rubydoc.info/gems/will_paginate/. # events/app/controllers/user_sessions_controller.rb # newAuthlogic plug-in @user_session = UserSession.newAuthlogic is an easy-to-use but powerful authentication plug-in for Rails. In laymen terms, it gives you user registration, # createsign-in (with a ‘Remember me’ option), sign-out and user @user_session = UserSession.new(params[:user_session])account activation. Our rule is that only authenticated users if @user_session.savecan create an event. flash[:notice] = "You have signed in successfully!" redirect_to root_urlInstallation elseRun the command to install the plugin: render :action => :new endscript/plugin install git://github.com/binarylogic/authlogic.git For the sign-out, simply destroy the user session:Adding user authentication to the applicationThe first thing that you need to do is associate the # app/controllers/user_sessions_controller.rbauthentication functionality with the User model: # destroy current_user_session.destroy#user.rb flash[:notice] = "You have signed out successfully!"acts_as_authentic do |c| redirect_to root_url c.require_password_confirmation = falseend In the view for the sign-in, the form should look like what follows: In this tutorial, we are going to focus on userauthentication only, and will create a new user using the # app/views/user_sessions/new.html.erbcreate operation provided by the scaffold. We need to make <% form_for @user_session, :url => user_session_path do |f| %> www.LinuxForU.com | LINUX For YoU | March 2011 | 71
  4. 4. Developers Tutorial # fields for username, password, remember_me create new events. Add the following code to the start of the<% end %> new method in the Events Controller: Next, wire up the routes: # events/app/controllers/events_controller.rb # new# config/routes.rb if current_user.nil?map.resource :user_session flash[:notice] = "You must be logged in to access this page"map.root :controller => "events_controller", :action => "index" redirect_to (new_user_session_url) return You then need to add some code to the Application endController for persisting the session. Declare the helper methods current_user_session and Try to create a new event without signing in—it shouldcurrent_user, which can be used in other controllers where take you to the sign-in page, /user_sessions/new. For sign-out,the session object or the current user object is required: use: /user_sessions/destroy. Read more about Authlogic at https://github.com/# app/controllers/application.rb binarylogic/authlogic.helper_method :current_user_session, :current_user Omniauth plug-in We don’t want the password to be written to the log files! Omniauth is a Rails plug-in that enables external authentication for your application. It allows people to use# app/controllers/application.rb Facebook Connect. Some other supported external providersfilter_parameter_logging :password are Twitter and Foursquare via OAuth, Google Apps via OpenID and Flickr. Besides the helper methods, you need to add twoauthentication methods to the Application Controller: Installation Install the plugin from the repository at github: • require_user: to be used in controller actions that require signed-in users script/plugin install git://github.com/intridea/omniauth.git • require_no_user: to be used in controller actions that require non-signed-in users Adding Facebook authentication to# app/controllers/application.rb the Events application# current_user_session (for retrieving the current session) For Rails v2.3.8, you need to create an initialiser for return @current_user_session if defined?(@current_user_ Omniauth, and specify a strategy for each external provider:session) @current_user_session = UserSession.find # events/config/initializers/omniauth.rb #Facebook# current_user (for retrieving the current user) ActionController::Dispatcher.middleware.use return @current_user if defined?(@current_user) OmniAuth::Strategies::Facebook, <APP_ID>, <APP_SECRET> @current_user = current_user_session && current_user_session.user Please note that you have to register your app with Facebook in order to get the API key. Also, you need to ensure that you# require_user provided the correct settings for your Facebook App: unless current_user flash[:notice] = "Please sign in to access this page" Site URL = http://yoursitename.com redirect_to root_url Site Domain = yoursitename.com return falseend Next, add a ‘Connect with Facebook’ button to the home page (you can get the Facebook button image from the# require_no_user Facebook Developers website): # check if it is the current_user # app/views/events/index.html.rb That’s it! You are ready to use authentication in the <a href="/auth/facebook"><img src="/images/fb-small-button.png"application now! Next, ensure that only signed-in users can alt="Connect with Facebook"/></a>72 | March 2011 | LINUX For YoU | www.LinuxForU.com
  5. 5. Tutorial Developers This link takes you to ‘/auth/facebook’ as required by We will not discuss authorisation methods, as they areOmniauth, after which Omniauth redirects you to Facebook, simple CRUD methods on either the Authorization modelwhich then takes care of authenticating you, and returns a response or the User model. The gist of this code is that you need tomessage on the callback URL /auth/facebook/callback. This extract and process the response from Facebook.callback URL needs to be configured in routes for all providers: Thats it! You now have Facebook Connect for your application. Who would have thought that it could be so# events/config/routes.rb simple? Thanks to the people at Intridea who came upmap.connect /auth/:provider/callback, :controller => user_ with this wonderful plug-in! Read more about Omniauth atsessions, :action => social_session_create https://github.com/intridea/omniauth. The response that you get from Facebook is an OAuth JRails plug-inresponse, and will contain a UID field which denotes the Rails, by default, uses the Prototype JavaScript library.user’s unique OAuth ID at Facebook and a provider field When a new Rails project is created, the following files(set to facebook), besides other fields like name, email, etc. will be present in the events/public/javascripts/ directory:Let’s create a new model to store the key fields, along with • prototype.jsan additional user_id field to map it to your User model: • effects.js • dragdrop.jsscript/generate model authorization provider:string uid:string • controls.jsuser_id:integer The last three are script.aculo.us libraries. If you wish to use jQuery instead, don’t worry, jRails comes to the This will generate authorization.rb, and you need to rescue. This plug-in lets you use your favourite JS library,associate it with your User model by adding a has_one jQuery, instead of Prototype. It includes the jQueryassociation as follows: equivalent (jquery.js and jquery-ui.js) of the above four files in your app. jRails will allow your app to use the# events/app/models/authorization.rb Rails JavaScript helpers by callingjQuery functions.has_one :user, :primary_key => "user_id", :foreign_key => "id" Installation For external authentication, handle the session creation Install the plugin from github:differently in the UserSessionsController. Use a new method,create_social_session: script/plugin install https://github.com/aaronchi/jrails.git# events/app/controllers/user_sessions_controller.rb Usage# create_social_session Adding the following helper to the view will include jquery.js # get the auth response from the request and jquery-ui.js in the HTML: @auth_response = request.env[rack.auth] # Check if the user has an existing social profile # e.g. events/app/views/events/new.html.erb # (in the Authorization model - match on uid,provider) <%= javascript_include_tag :defaults %> @auth = Authorization.find_from_hash(@auth_response) # if the user doesnt have a social profile then nil is Now you can include any jQuery library and call thereturned functions through the available Rails helpers, or pure if @auth.nil? JavaScript code. To know more about jRails, go to https:// # Create a new user or add an authorization to an existing github.com/aaronchi/jrails/wiki.user Well, the next time you think of a feature for your Rails @auth = Authorization.create_from_hash(@auth_response) app, just Google around, there could be an existing plug-in end for it! It’ll save you a lot of time... # Log-in the authorizing user with remember me as false @user_session = UserSession.create(@auth.user, false) if @user_session.save By: sagar arlekar and govind naroji flash[:notice] = "Successfully logged in." redirect_to root_url Sagar and Govind are the creators of Foodlets—a visual else guide for restaurant food. They are open source enthusiasts. Foodlets.in has been built entirely using open source flash[:notice] = "Login failed!" technologies. They can be reached at sagar.arlekar@gmail.com render :action => new and govind.naroji@gmail.com. end www.LinuxForU.com | LINUX For YoU | March 2011 | 73