Download Using Git with Rails

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Notes on Ruby on Rails
Created 11/02/09
Updated 11/10/10, Updated 02/06/11, Updated 09/15/11, Updated 03/22/12, Updated 04/06/12, Updated 05/20/12
Updated 06/25/12, Updated 07/14/12, Updated 08/12/12, Updated 12/16/12, Updated 01/27/13, Updated 03/16/13
Updated 07/03/13, Updated 09/25/13, Updated 11/19/13, Updated 01/02/14, Updated 01/22/14, Updated 02/16/14
Updated 04/21/14, Updated 05/26/14, Updated 06/08/14, Updated 07/28/14, Updated 09/08/14, Updated 11/05/14
Updated 12/13/14, Updated 02/09/15
http://www.codebeerstartups.com/2013/04/must-have-gems-for-development-machine-in-ruby-on-rails/
Introduction ...............................................................................................................................................................2
Concepts ....................................................................................................................................................................3
Installating Rails ........................................................................................................................................................5
Background on the Ruby Language ...........................................................................................................................5
Starting a new Ruby on Rails Project ........................................................................................................................9
Development Tools.................................................................................................................................................. 11
Running the Application .......................................................................................................................................... 12
Creating Models, Views, and Controllers ................................................................................................................ 12
Using Rake .............................................................................................................................................................. 12
Using RVM ............................................................................................................................................................. 13
From Static Pages to Dynamic Pages ...................................................................................................................... 13
Using ActiveRecord for Persistence ........................................................................................................................ 13
Using the Rails Console........................................................................................................................................... 20
Layouts and Rendering in Rails ............................................................................................................................... 20
Asset Pipeline .......................................................................................................................................................... 22
Writing Controllers .................................................................................................................................................. 24
Routing .................................................................................................................................................................... 25
Common Code (i.e., Helpers) .................................................................................................................................. 27
Resources ................................................................................................................................................................. 27
Using Git with Rails ................................................................................................................................................ 29
Using Gravatars ....................................................................................................................................................... 29
Further details of implementing User Management ................................................................................................ 30
Session Management ............................................................................................................................................... 31
Caching (improved in Rails 4) ................................................................................................................................. 32
Testing within Rails ................................................................................................................................................. 32
Debugging ............................................................................................................................................................... 32
Pagination ................................................................................................................................................................ 33
Using Modules ......................................................................................................................................................... 33
Rack ......................................................................................................................................................................... 34
Performance Testing (improved in Rails 4) ............................................................................................................. 34
Using RSpec for Tests ............................................................................................................................................. 34
Caching (new in 4.0) ............................................................................................................................................... 34
Turbolinks (new in 4.0) ........................................................................................................................................... 34
Declarative eTags (new in 4.0) ................................................................................................................................ 35
Engines .................................................................................................................................................................... 35
Observations and Open Issues ................................................................................................................................. 35
Appendix A: Chronology ....................................................................................................................................... 36
Appendix C: Sample Programs............................................................................................................................... 37
Appendix C: Gems of Interest to Try out ............................................................................................................... 38
Appendix D: Devise Gem ....................................................................................................................................... 38
Appendix E: CanCan Gem ..................................................................................................................................... 40
Appendix F: Paperclip Gem ................................................................................................................................... 44
Appendix G: Squeel Gem ....................................................................................................................................... 45
Appendix H: Rails 12factor Gem ........................................................................................................................... 48
Appendix I: Fog Gem ............................................................................................................................................. 48
Appendix J: Tagging Gem ...................................................................................................................................... 49
Appendix K: TheRubyRacer Gem .......................................................................................................................... 49
Page 1
Introduction
Ruby on Rails, often shortened to Rails or RoR, is an open source full-stack web application framework for the
Ruby programming language. Rails is a full-stack framework, meaning that it gives the Web developer the full
ability to gather information from the web server, talking to or querying the database, and template rendering out of
the box. As a result, Rails features a routing system that is independent of the Web server.
The current version is 4.2.0, released December 2014. The 4.2.x versions started in December 2014.
A prior current version was 4.1.8, released November 17, 2014. The 4.1.x versions started in April 2014.
A prior current version was 4.0.6, released in June 2014. The 4.0.x versions started in mid-summer 2013.
A prior current version was 3.2.14, released July 23, 2013. The 3.2.x versions started early 2012.
Early versions of Rails go back to 2004.
Reception
In 2011, Gartner Research noted that despite criticisms and comparisons to Java, many high-profile consumer web
firms are using Ruby on Rails to build agile, scalable web applications. Some of the largest sites running Ruby on
Rails include GitHub, Scribd, Groupon, and Basecamp. As of February 2012, it was estimated that over 235,000
web sites were running Ruby on Rails.
Resources
The development and distribution site for Rails is http://rubyonrails.org.
The most useful startup guide has been at http://guides.rubyonrails.org/getting_started.html
Here is a reference to Ruby Syntax: http://zenspider.com/Languages/Ruby/QuickRef.html
The RailsCasts series has been very useful: http://railscasts.com/
“Ruby on Rails 4 Tutorial: Learn Rails by Example” by Michael Hartl. Now in pre-press. The text is available
online at http://ruby.railstutorial.org/ruby-on-rails-tutorial-book.
“Crafting Rails 4 Applications: Expert Practices for Everyday Rails Development Paperback” by Jose Valim.
Pragmatic Programmer’s Press, November 2013, 200 pages. List price $36.00. Not yet released or reviewed.
“Agile Web Development with Rails 4” by Sam Ruby, Dave Thomas, and David Heinemeier Hansson. Pragmatic
Programmer’s Press, October 2013, 500 pages. List price $43.95, Amazon price $23.97. Rated 4.5 stars on
Amazon.com (from 2 reviews). We have bought this as an eBook.
“Ruby on Rails 3 Tutorial (second edition): Learn Rails by Example” by Michael Hartl. Addison-Wesley, August
2012, 600 pages. Amazon price $29.98. Rated 4.5 stars on Amazon.com. Update to a well-regarded book, now
being replaced by the Rails 4 version (above). The text is also available at http://ruby.railstutorial.org/ruby-on-railstutorial-book.
“Ruby and MongoDB Web Development” by Gautham Rege. Packt Publishing, July 2012, 332 pages. List price
$44.99, Amazon price $40.49, used from $27.00. Rated 3 stars on Amazon.com. A discussion of how to develop
using frameworks on top of Ruby (i.e., Rails and Sinatra), to write an application whose state is maintained in
MongoDB. Comments indicated that it wasn’t clearly-written or well-organized, however,
“Learning Rails 3” by Simon St. Laurent, Edd Dumbill, Eric J Gruber. O’Reilly Press, July 2012, 414 pages. Rated
4.5 stars on Amazon.com (from 8 reviews). The description says that this book covers Rails from the web site view
back toward the programming model. This is unique, because it allows you to get web sites and their visual design
started and understood first, then starts covering concepts of Model/View/Controller.
“Rails 3 in Action” by Ryan Bigg and Yehuda Katz. Manning Press, September 2011, 592 pages. List price $49.99,
Amazon price $31.67, used from $25.62. Rated 3.5 stars on Amazon.com. Covers Rails 3.1.x. Reviews indicated
Page 2
that it had more errors than usual for a Manning title, however, the content seemed to be well organized and had
more material on testing than some of the other books. Available on City of Palo Alto library site.
“Agile Web Development with Rails, fourth edition” by Sam Ruby, Dave Thomas, and David Heinemeier Hansson.
Pragmatic Programmer’s Press, March 2011, 480 pages. List price $43.95, Amazon price $25.93, used from $23.47.
Rated 3 stars on Amazon.com. Earlier editions of this book provided the first introductions on Ruby on Rails, going
back to about 2005. Check which edition you are looking at before buying.
“Ruby on Rails 3 Way (Second Edition)” by Obie Fernandez. Addison-Wesley, December 2010, 768 pages. List
price $49.99, Amazon price $28.56, used from $21.89. Rated 3.5 stars on Amazon.com. It literally covers the
“way” to do almost everything with Rails. Quite a large book, organized like a “how-to” book. Not quite a
reference manual, nor is it a tutorial.
Installing Rails 4 on a Mac OSX computer
https://www.evernote.com/shard/s442/sh/f0463d3b-6c17-46e2-a0af-5992c4f2db66/b330815cc2b70615a559c07d29ba0205
Concepts
Like many web frameworks, Ruby on Rails uses a variant of the Model/View/Controller (MVC) architecture pattern
to organize application programming.
In a default configuration, a model in a Ruby on Rails framework maps to a table in a database. By convention, a
model named User will map to the database table users, and the model will have a filename user.rb within
app/models. While developers can choose to use whatever model name and database table name they wish, this is
not a common practice and it's usually discouraged because Rails philosophy is to use convention over
configuration.
A controller is the component of Rails that responds to external request from the web server to the application, and
respond to the external request by determining which view file to render. The controller may also have to query the
model directly for information and pass these onto the view. A controller may contain one or more actions. In Ruby
on Rails, action is typically a basic unit which describes a single rule on how to respond to a specific external webbrowser request. Also note that, if a controller/action is not mapped to the Rails router, the controller/action will be
directly inaccessible to external web requests. By convention, Rails encourage developers to use a RESTful route
which contain actions named create, new, edit, update, destroy, and index, as these are routed automatically by
convention in the routes file if specified.
A view typically is a erb file in the default configuration of Rails. It is typically converted to output html at run-time,
although in theory any format can be used as a view.
Ruby on Rails includes tools that make common development tasks easier "out of the box", such as scaffolding that
can automatically construct some of the models and views needed for a basic website. Also included are WEBrick,
a simple Ruby web server that is distributed with Ruby, and Rake, a build system, distributed as a gem. Together
with Ruby on Rails these tools provide a basic development environment.
Page 3
Ruby on Rails relies on a web server to run it. WEBrick is most common at the time of writing, but it can also be
run by Lighttpd, Apache, Cherokee, Hiawatha, nginx (either as a module - Passenger for example - or via CGI,
FastCGI or mod_ruby), and many others. From 2008 onwards, the Passenger web server replaced Mongrel as the
most-used web server for Ruby on Rails.
Ruby on Rails is also noteworthy for its extensive use of JavaScript such as jQuey. Ruby on Rails initially utilized
lightweight SOAP for web services; this was later replaced by RESTful web services.
Since version 2.0, Ruby on Rails by default offers both HTML and XML as output formats. The latter is the facility
for RESTful web services.
The server uses embedded ruby in the HTML views with files having an html.erb extension. Other templating
methods are available such as HAML which removes much of the normal page 'clutter'. For instance it uses a
format in which indenting indicates the DOM nesting, and many of the syntactic elements of HTML are reduced.
Ruby on Rails 3.2 has been designed to work with Ruby 1.9.3, 1.9.2, and 1.8.7.
Rails 3.2 deprecates plugins (Rails 4.0 will remove them completely) so find Ruby gems to replace any plugins you
may still be using.
Ruby on Rails 4.0 and later has been designed to work with Ruby 2.0.0 or 1.9.3.
Framework structure
Ruby on Rails is separated into various packages, namely ActiveRecord (an object-relational mapping system for
database access), ActiveModel (the data representation system extended by ActiveRecord), ActiveResource
(provides web services), ActionPack, ActiveSupport and ActionMailer.
Deployment
Ruby on Rails is often installed using RubyGems, a package manager which is included with current versions of
Ruby. Many Linux distributions also support installation of Ruby on Rails and its dependencies through their native
package management system.
Ruby on Rails is typically deployed with a database server such as MySQL or PostgreSQL, and a web server such as
Apache running the Phusion Passenger module.
There are many Ruby on Rails hosting services such as Heroku, Engine Yard, and Rails Playground. See our
document “Notes on Heroku”.
New Features in Rails 4.2





Active Job
asynchronous emails
Adequate Record
Web Console
foreign keys
New Features in Rails 4.1
Spring application preloader - Spring is a Rails application preloader. It speeds up development by keeping your
application running in the background so you don't need to boot it every time you run a test, rake task or migration
config/secrets.yml - Rails 4.1 generates a new secrets.yml file in the config folder. By default, this file contains the
application's secret_key_base, but it could also be used to store other secrets such as access keys for external APIs.
The secrets added to this file are accessible via Rails.application.secrets.
Action Pack variants - We often want to render different HTML/JSON/XML templates for phones, tablets, and
desktop browsers. Variants make it easy. The request variant is a specialization of the request format,
like :tablet, :phone, or :desktop.
Page 4
Action Mailer previews - Action Mailer previews provide a way to visually see how emails look by visiting a special
URL that renders them.
Active Record enums - declare an enum attribute where the values map to integers in the database, but can be
queried by name.
New Features in Rails 4.0
It's an amazing new version packed with new goodies and farewells to old features past their expiration date.
A big focus has been on making it dead simple to build modern web applications that are screaming fast without
needing to go the client-side JS/JSON server route. Much of this work was pioneered for Rails in the new version of
Basecamp and focuses on three aspects:
See http://railscasts.com/episodes/400-what-s-new-in-rails-4?view=asciicast.
A good guide for upgrading is located at http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html
Specific changes:
 Strong parameters
 ActiveModel::Model
 Russian Doll caching
 TurboLinks
 Queue API
Installation of Rails
See http://railsinstaller.org/
We used this to generate our system. It provided Ruby 1.9.3 and Rails 3.2.14, which we have now updated to Rails
4.1.8.
Background on the Ruby Language
Syntax
Statements don’t need semicolons.
Comments begin with #
Page 5
Block comments:
=begin
Every body mentioned this way
to have multiline comments.
It has to be at the beginning of a line or
it will be a syntax error.
=end
Variables
These don’t need to be declared, or have any special syntax marker (this is an improvement over PHP where they
had to begin with $).
Variables are not typed.
Flow of control
There is an if/then/else facility
There is a loop construct:
item_list.each do |item|
puts "current_index: #{index}
end
Notice that the do/end pair is defining a code block. Another form of this loop allows the block to get the loop index
(0…n):
itemList.each_with_index do |item, index|
puts "current_index: #{index}
end
Objects and Message Passing
Everything in Ruby, including strings and even nil, is an object.
It’s easier to describe what objects do, which is respond to messages. An object like a string, for example, can
respond to the message length, which returns the number of characters in the string:
>> "foobar".length
# Passing the "length" message to a string
=> 6
Typically, the messages that get passed to objects are methods, which are functions defined on those objects.
Method Definitions
The console allows us to define methods the same way we did with the home action (defining methods in the
console is a bit cumbersome, and ordinarily you would use a file, but it’s convenient for demonstration purposes).
For example, let’s define a function string_message that takes a single argument and returns a message based
on whether the argument is empty or not:
Page 6
>> def string_message(string)
>> if string.empty?
>>
"It's an empty string!"
>> else
>>
"The string is nonempty."
>> end
>> end
=> nil
>> puts string_message("")
It's an empty string!
>> puts string_message("foobar")
The string is nonempty.
Note that Ruby functions have an implicit return, meaning they return the last statement evaluated—in this case, one
of the two message strings, depending on whether the method’s argument string is empty or not. Ruby also has
an explicit return option; the following function is equivalent to the one above:
>> def string_message(string)
>> return "It's an empty string!" if string.empty?
>> return "The string is nonempty."
>> end
The alert reader might notice at this point that the second return here is actually unnecessary—being the last
expression in the function, the string "The string is nonempty." will be returned regardless of the
return keyword, but using return in both places has a pleasing symmetry to it.
Arrays and Ranges
An array is just a list of elements in a particular order. Understanding them gives a good foundation for
understanding hashes and for aspects of Rails data modeling (such as the has_many association which can be
defined in a model file).
So far we’ve spent a lot of time understanding strings, and there’s a natural way to get from strings to arrays using
the split method:
>> "foo bar baz".split
# Split a string into a three-element array
=> ["foo", "bar", "baz"]
The result of this operation is an array of three strings.
Ranges are subparts of an array.
Arrays can be created by setting a variable to [] and built using the array.append() method.
Blocks
Both arrays and ranges respond to a host of methods that accept blocks (similar to closures in other languages),
which are simultaneously one of Ruby’s most powerful and most confusing features:
Page 7
>> (1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5
This code calls the each method on the range (1..5) and passes it the block { |i| puts 2 * i }. The
vertical bars around the variable name in |i| are Ruby syntax for a block variable, and it’s up to the method to
know what to do with the block; in this case, the range’s each method can handle a block with a single local
variable, which we’ve called i, and it just executes the block for each value in the range.
Modules (“packages” in Java)
Modules have many powerful features, and one of them is that they are namespaces. This means that names defined
inside a module are hidden from outside the module.
To see what I mean, you need to know that one of the things you can do inside a module is define another module.
So, for example:
module Animals
module Dog
def self.bark
"bow wow"
end
end
end
Kernel.puts(Dog.bark)
#=> NameError: uninitialized constant Dog
From where we are in the last line, when we say Dog.bark, the name Dog is not visible. That’s because the name
Dog is defined inside the Animals module. However, we are at the same level as the place where Animals was
defined, so the name Animals is visible. Now, we can reach the name Dog, if we want to; we just can’t do it
directly, because it isn’t directly visible. Instead, we have to do it by way of the name Animals, which is directly
visible. The “by way of” operator is two colons (::).
Ruby Classes
We’ve said before that everything in Ruby is an object, and in this section we’ll finally get to define some of our
own. Ruby, like many object-oriented languages, uses classes to organize methods; these classes are then
instantiated to create objects. If you’re new to object-oriented programming, this may sound like gibberish, so let’s
look at some concrete examples.
We’ve seen lots of examples of using classes to instantiate objects, but we have yet to do so explicitly. For example,
we instantiated a string using the double quote characters, which is a literal constructor for strings.
A variable whose name begins with '@' is an instance variable of self. An instance variable belongs to the object
itself. Uninitialized instance variables have a value of nil.
Conventions
A number of naming conventions within class methods, such as using a ? at the end of a name for a method that
returns a Boolean.
Page 8
Modifying Built-In Classes
While inheritance is a powerful idea, in the case of palindromes it might be even more natural to add the
palindrome? method to the String class itself, so that (among other things) we can call palindrome? on a
string literal, which we currently can’t do.
Concerns
Concerns are also a helpful way of extracting a slice of model that doesn’t seem part of its essence (what is and isn’t
in the essence of a model is a fuzzy line and a longer discussion) without going full-bore Single Responsibility
Principle and running the risk of ballooning your object inventory.
Starting a new Ruby on Rails Project
Use the “rails new <name>” command (or the “rails new <name> --database=postgresql” command).
The resulting structure is shown below:
Page 9
The default Gemfile is:
source 'https://rubygems.org'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster.
# Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 1.0.1'
group :doc do
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', require: false
end
# Use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
# Use unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]
Using Bundler
After creating a new Rails application, the next step is to use Bundler to install and include the gems needed by the
app. This involves opening the Gemfile with your favorite text editor, then running the command:
bundle install
A similar command “bundle update” will update the versions of existing gems.
Gems are located in the Ruby193/lib/ruby/gems/1.9.3/gems directory. This is managed by the bundle system.
Version specification in the Gemfile
Most of the version specifiers, like >= 1.0, are self-explanatory. The specifier ~> has a special meaning, best
shown by example:
~> 2.0.3 is identical to >= 2.0.3 and < 2.1.
~> 2.1 is identical to >= 2.1 and < 3.0.
~> 2.2.beta will match prerelease versions like 2.2.beta.12.
Page 10
Other suggestions on project creation
The Hartl book suggests renaming README.rdoc to README.md. If you use the file extension .md then GitHub
will automatically format it nicely for you. However, it appears that as of 2013, GitHub can handle both types.
Before creating the Git repo, if you are using JetBrains, update the IDE’s list of files to ignore (this is on the project
settings), and the .gitignore file itself.
Write the Git commit messages in the present tense (i.e, “Improve the README file”. Git models commits as a
series of patches, and in this context it makes sense to describe what each commit does, rather than what it did.
Moreover, this usage matches up with the commit messages generated by Git commands themselves. See the
GitHub post Shiny new commit styles for more information.
Development Tools
Now that we have dealt with simple changes at the file-system level, let’s load up a viewing/editing environment for
multiple files. The Ruby on Rails 4 Tutorial book names two IDEs: RadRails and RubyMine. Both are crossplatform.
Another IDE is Komodo, which gets good reviews. See http://www.activestate.com/komodo-ide
There is Komodo Edit for free, and Professional for $295 (discounted to $245).
Many Rails developers don’t use a full IDE, they just need a multi-file text editing tool, such as TextMate or
Sublime Text 2. The latter can organize multiple text files into a project, and integrate with source control.
The Ruby plugin for Eclipse
You can also use Eclipse:
 Download and install Eclipse if you don’t already have it.
 Launch Eclipse, then locate and install the Ruby Development Tools plug-in using the Eclipse ‘Help/Install New
Software’ menu option. At the Available Software dialog box:
1.
Select –All Available Sites– for the ‘Work with’ drop down list.
2.
Expand the Programming Languages section and select ‘Dynamic Languages Toolkit – Ruby Development
Tools’.
3.
Press the Next button, review the options, then select the Finish button.
 Use the IDE ‘Eclipse/Preferences’ menu option to pull up the application preferences dialog, then select ‘Ruby’
on the far right of the dialog.
1.
Expand the options under ‘Ruby’ and select ‘Interpreters’. If none are displayed, select the ‘Search…’
button at the right side of the screen to locate any installed interpreters. Apple ships a ruby interpreter – in
OSX 10.5.x I found them in /usr/bin/ruby.
 Now use the IDE ‘File/New/Ruby Project’ to create a new Ruby project. Name it to any convention you follow
(type of project, class, etc.).
NOTE: You want to use the Ruby Perspective when writing Ruby code, which is available using the IDE
‘Window/Open Perspective/Other’ option and selecting ‘Ruby from the list.
 Select ‘File/New/Ruby Class’ to create your first Ruby program. Name it hello, then enter this simple Hello
World program to confirm you can create and run a Ruby program:
class hello
def hello
puts “Hello Ruby World”
end
end
 Save and execute the file and verify you see the text string in the Eclipse console. Congratulations. You just
created your first Ruby program using Eclipse.
Page 11
Running the Application
rails server - The default Rails web server is WEBrick, a pure-Ruby server that isn’t suitable for production
use but is fine in development.
This command is often abbreviated “rails s”
The suggested web server for production is Unicorn.
Creating Models, Views, and Controllers
To get started with this Rails application, you generate a scaffold. Scaffolds in Rails provide a lot of basic
functionality but are generally not used for full-scale development because you may want something more
customized, in which case you’d build it yourself. But for this example of what Rails can do, let’s generate a
scaffold by running this command:
rails generate scaffold purchase name:string cost:float
When you used the rails command earlier, it generated an entire Rails application. You can use this command
inside of an application to generate a specific part of the application by passing the generate argument to the
rails command, followed by what it is you want to generate.
The scaffold command generates a model, a controller, and views based on the name passed after scaffold in
this command. These are the three important parts needed for your purchase tracking. The model provides a way to
interact with a database. The controller interacts with the model to retrieve and format its information and defines
different actions to perform on this data. The views display the information from the controller in a neat format.
Everything after the name for the scaffold are the fields for the database table and the attributes for the objects of
this scaffold. Here you tell Rails that the table for your purchase scaffold will contain name and cost fields, which
are a string and a float. To create this table, the scaffold generator generates what’s known as a migration.
rails generate scaffold User name:string email:string
To create an association (to another table/entity) use the data type “reference”. Then create an index to indicate
what is being referred to.
You can also generate just a model file, or just a controller (which will take a list of method names, generate a static
view for each of them).
rails generate model
rails generate controller StaticPages home help_
Using Rake
Rake is Ruby make, a make-like language written in Ruby. Rails uses Rake extensively, especially for the
innumerable little administrative tasks necessary when developing database-backed web applications. The rake
db:migrate command is probably the most common, but there are many others; you can see a list of database
tasks using -T db:
$ rake -T db
To see all the Rake tasks available, run
$ rake -T
The most common command is rake db:migrate, others are rake db:seed, rake db:create, rake db:drop
Page 12
Using RVM
RVM is a command-line tool which allows you to easily install, manage, and work with multiple Ruby
environments from interpreters to sets of gems. See http://rvm.io/
Using Gemsets
One of the most powerful, useful and often overlooked features of RVM is the gemset. A gemset is a separate gem
directory, so the gems in one gemset don't conflict with the gems in another gemset. A common usage would be to
install Rails 2 in one gemset, and Rails 3 in another. Since they're in different gemsets, there's no possibility of them
interfering with each other.
From Static Pages to Dynamic Pages
Rails has two main ways of making static web pages. First, Rails can handle truly static pages consisting of raw
HTML files. Second, Rails allows us to define views containing raw HTML, which Rails can render so that the web
server can send it to the browser.
Every Rails application comes with a minimal working application thanks to the rails script, with a default welcome
page at the address http://localhost:3000
To learn where this page comes from, take a look at the file public/index.html Because the file contains its
own stylesheet information, it’s a little messy, but it gets the job done: by default, Rails serves any files in the
public directory directly to the browser. In the case of the special index.html file, you don’t even have to
indicate the file in the URL, as index.html is the default.
As an introduction to MVC, we will change this simple app to use a controller to render the static page.
The StaticPages controller generation automatically updates the routes file, called config/routes.rb, which Rails
uses to find the correspondence between URIs and web pages. This is our first encounter with the config directory
which is where Rails collects files needed for the application configuration—hence the name.
To pass dynamic content to the view, assign value to variables with “@” in front. These will be known to the view.
Using ActiveRecord for Persistence
The ActiveRecord pattern is defined as one where objects carry data & behavior, in this case the ability to persist
themselves.
ActiveRecord is an ORM mapping layer, similar to Hibernate. It allows you to create queries and updates without
writing the actual SQL. It also handles caching and transaction management. It is probably more limited than
Hibernate, but this makes it easier to learn and with less unexpected behavior.
Models
See http://guides.rubyonrails.org/association_basics.html for this information.
These define the data objects and their relationships.
You can add validations to your model to ensure that the data conforms to certain rules or that data for a certain field
must be present or that a number you enter must be above a certain other number.
Expressing Data Model Relationships
These are defined by the following elements of the model files:
 has_many for a 1 to N relationship
 belongs_to
Expressing Validation Conditions
Page 13
Here is an example:
validates :name, :presence => true,
:length => { :minimum => 5 }
The Query Interface
See http://guides.rubyonrails.org/active_record_querying.html for this information
There are a number of access methods available on a model class, including:





find - by primary key
first, last, all
find in batches
find multiple with ordering
selecting only specific fields.
For a query, you can chain together a number of where() clauses, or use findAll(). In fact you can conditionally
chain the where clauses, as shown below:
@challenges = Challenge.all
@challenges = @challenges.where('name like ?', "%" + cfp[:name] + "%") if cfp[:name] &&
!cfp[:name].empty?
@challenges = @challenges.where('challenge_type = ?', cfp[:challenge_type]) if
cfp[:challenge_type] && !cfp[:challenge_type].empty?
Though there is a syntactic facility called “dynamic finders” which is similar to Grails, it is being deprecated and
will be removed in Rails 4.1. For example, instead of find_by_first_name(‘jack’) you should use
find_by(first_name: ‘jack’)
The locking options include optimistic (using a version field), and pessimistic (locking at the DB level)
To carry out joins, you might specify Client.joins(“left outer join addresses on addresses.client_id = clients.id”)
however this simply makes fields in addresses available to the where clause, it doesn’t add new fields to the Client
objects returned.
You can use eager loading of related objects (related in the sense of associations), by using the :includes(:address)
specification on the query. What this will do is carry out a main query, and then a supporting query for the specified
related object class, instead of carrying out 1+N queries (where N is the number of records returned in the first
query).
find_by_sql has a close relative called connection#select_all. select_all will retrieve objects
from the database using custom SQL just like find_by_sql but will not instantiate them. Instead, you will get an
array of hashes where each hash indicates a record.
Client.connection.select_all("SELECT * FROM clients WHERE id = '1'")
This facility is the closest within Rails to the ‘projections’ capability in Grails. Essentially this operation is grabbing
the connection, in order to carry out ad-hoc operations on it.
Finally, there is an ‘explain’ facility that will show the query plan for any given query interface call.
Preload, Eagerload, Includes and Joins
These examples from http://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html
Rails provides four different ways to load association data. In this blog we are going to look at each of those.
Preload: loads the association data in a separate query.
Page 14
1 User.preload(:posts).to_a
2
3 # =>
4 SELECT "users".* FROM "users"
5 SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1)
This is how includes loads data in the default case.
Since preload always generates two sql we can’t use posts table in where condition. Following query will result in
error.
1 User.preload(:posts).where("posts.desc='ruby is awesome'")
2
3 # =>
4 SQLite3::SQLException: no such column: posts.desc:
5 SELECT "users".* FROM "users" WHERE (posts.desc='ruby is awesome')
where clauses on users table will work fine.
1 User.preload(:posts).where("users.name='Neeraj'")
2
3 # =>
4 SELECT "users".* FROM "users" WHERE (users.name='Neeraj')
5 SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (3)
Includes: loads the association data in a separate query in the default case just like preload.
However it is smarter than preload. Above we saw that preload failed for query
User.preload(:posts).where(“posts.desc=’ruby is awesome’”). Let’s try same with includes.
1 User.includes(:posts).where('posts.desc = "ruby is awesome"').to_a
2
3 # =>
4 SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0,
5
"posts"."title" AS t1_r1,
6
"posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3
7 FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
8 WHERE (posts.desc = "ruby is awesome")
As you can see includes switches from using two separate queries to creating a single LEFT OUTER JOIN to get
the data. And it also applies the supplied condition.
Page 15
So includes changes from two queries to a single query on some cases. By default for a simple case it will use two
queries. Let’s say that for some reason you want to force a simple includes case to use a single query instead of
two. Use references to achieve that.
1 User.includes(:posts).references(:posts).to_a
2
3 # =>
4 SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0,
5
"posts"."title" AS t1_r1,
6
"posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3
7 FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
In the above case a single query was done.
Eager load: loads all association in a single query using `LEFT OUTER JOIN’.
1 User.eager_load(:posts).to_a
2
3 # =>
4 SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0,
5
"posts"."title" AS t1_r1, "posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3
6 FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
This is exactly what includes does when it is forced to make a single query when where or order clause is using an
attribute from posts table.
Joins: brings association data using inner join.
1 User.joins(:posts)
2
3 # =>
4 SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
In the above case no posts data is selected. Above query can also produce duplicate result. To see it let’s create some
sample data.
1 def self.setup
2
User.delete_all
3
Post.delete_all
4
5
u = User.create name: 'Neeraj'
6
u.posts.create! title: 'ruby', desc: 'ruby is awesome'
Page 16
7
u.posts.create! title: 'rails', desc: 'rails is awesome'
8
u.posts.create! title: 'JavaScript', desc: 'JavaScript is awesome'
9
10 u = User.create name: 'Neil'
11 u.posts.create! title: 'JavaScript', desc: 'Javascript is awesome'
12
13 u = User.create name: 'Trisha'
14 end
With the above sample data if we execute User.joins(:posts) then this is the result we get
1 #<User id: 9, name: "Neeraj">
2 #<User id: 9, name: "Neeraj">
3 #<User id: 9, name: "Neeraj">
4 #<User id: 10, name: "Neil">
We can avoid the duplication by using distinct .
1 User.joins(:posts).select('distinct users.*').to_a
Also if we want to make use of attributes from posts table then we need to select them.
1 records = User.joins(:posts).select('distinct users.*, posts.title as posts_title').to_a
2 records.each do |user|
3 puts user.name
4 puts user.posts_title
5 end
Note that using joins means if you use user.posts then another query will be performed.
Setting up Database Connections
While most Rails programs use SQLite by default, we have been using the ‘mysql2’ adapter or the ‘pg’ adapter, for
the MySQL and PostgreSQL database respectively. The parameters for the database configuration go into
database.yml, and are very standard fields for setting up a MySQL connection.
Migrations
Migrations are a convenient way for you to alter your database in a structured and organized manner. You could edit
fragments of SQL by hand but you would then be responsible for telling other developers that they need to go and
run them. You’d also have to keep track of which changes need to be run against the production machines next time
you deploy.
Active Record tracks which migrations have already been run so all you have to do is update your source and run
rake db:migrate. Active Record will work out which migrations should be run. It will also update your
db/schema.rb file to match the structure of your database.
Page 17
Migrations also allow you to describe these transformations using Ruby. The great thing about this is that (like most
of Active Record’s functionality) it is database independent: you don’t need to worry about the precise syntax of
CREATE TABLE any more than you worry about variations on SELECT * (you can drop down to raw SQL for
database specific features). For example you could use SQLite3 in development, but MySQL in production.
Here is an example:
class CreateProducts < ActiveRecord::Migration
def up
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
def down
drop_table :products
end
end
This creates the table and defines the fields. The t.timestamps creates the date_created and last_updated fields.
Active Record supports the following database column types:
 :binary
 :boolean
 :date
 :datetime
 :decimal
 :float
 :integer
 :primary_key
 :string
 :text
 :time
 :timestamp
These will be mapped onto an appropriate underlying database type. For example, with MySQL the type :string
is mapped to VARCHAR(255). You can create columns of types not supported by Active Record, but these will be
database-specific.
To create a migration file, use the command “rails generate migration <migrationName>”. An example name would
be “ChangeDataTypeForStartsAt”. This will create a migration class ChangeDataTypeForStartsAt.
Then edit the class to define the “up” (at leasts) and the “down” (optional) method. Here is an example:
class ChangeDataTypeForStartsAt < ActiveRecord::Migration
def self.up
change_table :challenges do |t|
t.change :startsAt, :datetime
end
end
def self.down
change_table :challenges do |t|
t.change :startsAt, :date
end
end
end
Apply the migration using the command “rake db:migrate”.
Page 18
Occasionally you will make a mistake when writing a migration. If you have already run the migration then you
cannot just edit the migration and run the migration again: Rails thinks it has already run the migration and so will
do nothing when you run rake db:migrate. You must rollback the migration (for example with rake
db:rollback), edit your migration and then run rake db:migrate to run the corrected version.
In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your coworkers and cause major headaches if the existing version of the migration has already been run on production
machines. Instead, you should write a new migration that performs the changes you require. Editing a freshly
generated migration that has not yet been committed to source control (or, more generally, which has not been
propagated beyond your development machine) is relatively harmless.
Defining Indexes in the Schema
class CreateRelationships < ActiveRecord::Migration
def change
create_table :relationships do |t|
t.integer :follower_id
t.integer :followed_id
t.timestamps
end
add_index :relationships, :follower_id
add_index :relationships, :followed_id
add_index :relationships, [:follower_id, :followed_id], unique: true
end
end
Non-Database Models
In Rails 3 and later the non-database functionality of Active Record is extracted out into Active Model. This allows
you to cleanly add validations and other features to tableless models. See http://railscasts.com/episodes/219-activemodel. Here is an example:
class ChallengeFilter
extend ActiveModel::Naming
include ActiveModel::AttributeMethods
include ActiveModel::Conversion
attr_accessor :name
attr_accessor :challenge_type
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
Virtual Attributes
Keep your controllers clean and forms flexible by adding virtual attributes to your model. This very powerful
technique allows you to create form fields which may not directly relate to the database.
We can create this by defining a virtual attribute for full_name.
class User < ActiveRecord::Base
# Getter
def full_name
[first_name, last_name].join(' ')
end
Page 19
# Setter
def full_name=(name)
split = name.split(' ', 2)
self.first_name = split.first
self.last_name = split.last
end
end
The getter and setter methods defined in the User model.
The getter method gets the first_name and last_name values for the user and returns them, joined by a space.
The setter method splits the passed value at the first space and sets the first_name and last_name to be the
first and second parts of the split string.
Using virtual properties means that the user interface doesn’t have to have a field to map to each field in the
corresponding database table. This is especially useful when you’re using Rails to connect to a legacy database and
can’t alter the fields in its tables.
Using the Rails Console
Since Ruby is interpreted, you can interactively use it through a console.
Type “rails c” to start the console.
Layouts and Rendering in Rails
The view rendering facilities within Rails support the following:
 Having a master layout that all views use
 Create layouts with multiple content sections
 Use partials to DRY up your views
 Use nested layouts (sub-templates)
A view is an ERB file, which allows you to mix HTML and Ruby code to generate dynamic pages. The beginning
of an ERB tag indicates that the result of the code inside the tag will be output to the page. If you want the code to
be evaluated but not output, you use the <% tag, like this:
<% some_variable = "foo" %>
If you were to use <%= some_variable = "foo" %> here, the some_variable variable would be set and
the value output to the screen. By using <% %> instead, the Ruby code is evaluated but not output.
The render method, when passed a string as in this example, renders a partial. A partial is a separate template file
that you can include in other templates to repeat similar code. By convention these begin with an underscore..
The link_to method generates a link with the text of the first argument (Back) and with an href attribute
specified by the second argument. There are several ways to specify the path:
 Use a controller name and an action name. The benefit here is flexibility: you can reference any controller
and action.
 Use a defined constant such as edit_purchases_path which is generated by the routing file
processor. The benefit here is that this constant can be checked at compile time.
Expressions commonly used inside Views
Here are the link generators:
<%= link_to "Home",'#' %>
<%= button_to "Home",'#' %>
The most comprehensive and advanced set are called “FormHelpers”. These include:
Page 20
<%= form_tag :url => ‘update’ %>
<contents>
<%= f.submit %>
<% end %>
<%= form_for(@treasure) do |f| %>
<contents>
<%= f.submit %>
<% end %>
Here are the form field editor generators:
<%=
<%=
<%=
<%=
<%=
<%=
<%=
f.text_field :email %>
f.text_area :description %>
f.number_field :score_points %>
f.check_box :locked %>
f.collection_select :location_id, Hex.order(:id), :id, :get_label %>
f.date_select :starts_at %>
f.datetime_select :bought_at %>
Within any view, you can also have if/then/else, and looping constructs which use regular Ruby syntax, since an
ERB file is really a Ruby script.
The selection generation FormHelpers are worth describing in detail:
select_tag(name, option_tags = nil, options = {})
Creates a dropdown selection box, or if the :multiple option is set to true, a multiple choice selection box. The
second argument is typically a call to one of the “options_for…” functions described below. The third argument is a
set of options from the following:

:multiple - If set to true the selection will allow multiple choices.

:disabled - If set to true, the user will not be able to use this input.

:include_blank - If set to true, an empty option will be created.


:prompt - Create a prompt option with blank value and the text asking user to select something
Any other key creates standard HTML attributes for the tag.
One of the following methods is typically used to create the options that are selectable:
options_for_select(container, selected = nil) public
Returns a string of option tags that have been compiled from a container (hash, array, enumerable, your type).
Given a container where the elements respond to first and last (such as a two-element array), the “lasts” serve as
option values and the “firsts” as option text. Hashes are turned into this form automatically, so the keys become
“firsts” and values become lasts. If selected is specified, the matching “last” or element will get the selected
option-tag. selected may also be an array of values to be selected when using a multiple select.
options_from_collection_for_select(collection, value_method, text_method,
selected = nil) public
Returns a string of option tags that have been compiled by iterating over the collection and assigning the result
of a call to the value_method as the option value and the text_method as the option text.
Within a form_for, you can use:
<%= f.select :challenge_type, ChallengeType.options, :prompt => "Type:" %>
Page 21
Which performs all of the above functions, including emitting correct element name, generating the options, adding
a prompt option, and indicating current value from specified field (:challengeType) of the given model (f).
Partials
Partial views are a way to have common fragments of multiple views shared.
Partials are named files, which typically start with an underscore.
To incorporate a partial, use a single call to a Rails helper called render:
<%= render 'layouts/shim' %>
The effect of this line is to look for a file called app/views/layouts/_shim.html.erb, evaluate its
contents, and insert the results into the view.
Asset Pipeline
One of the most notable differences between Rails 3.0 and more recent versions is the asset pipeline, which
significantly improves the production and management of static assets such as CSS, JavaScript, and images. This
section gives a high-level overview of the asset pipeline and then shows how to use a remarkable tool for making
CSS called Sass, now included by default as part of the asset pipeline.
In current Rails, there are three canonical directories for static assets, each with its own purpose:
 app/assets: assets specific to the present application
 lib/assets: assets for libraries written by your dev team
 vendor/assets: assets from third-party vendors
Manifest Files: Once you’ve placed your assets in their logical locations, you can use manifest files to tell Rails (via
the Sprockets gem) how to combine them to form single files (this applies to CSS and JavaScript but not to images).
This provides a way to reduce the download times.
After you’ve assembled your assets, Rails prepares them for the site template by running them through several
preprocessing engines and using the manifest files to combine them for delivery to the browser. Examples of the
pre-processing includes CoffeeScript and Sass.
Note: for deployments on Heroku, either add in the 12factor gem, or make the following change in
config/environments/production.rb:
# Enable Rails's static asset server (this is needed on Heroku)
config.serve_static_assets = true
About the Asset Pipeline
The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets. It also
adds the ability to write these assets in other languages and pre-processors such as CoffeeScript, Sass and ERB.
The asset pipeline is technically no longer a core feature of Rails 4, it has been extracted out of the framework into
the sprockets-rails gem. The asset pipeline is enabled by default.
You can disable the asset pipeline while creating a new application by passing the --skip-sprockets option.
rails new appname --skip-sprockets
Rails 4 automatically adds the sass-rails, coffee-rails and uglifier gems to your Gemfile, which are used by
Sprockets for asset compression:
gem 'sass-rails'
gem 'uglifier'
Page 22
gem 'coffee-rails'
Using the --skip-sprockets option will prevent Rails 4 from adding sass-rails and uglifier to Gemfile, so if you later
want to enable the asset pipeline you will have to add those gems to your Gemfile. Also, creating an application
with the --skip-sprockets option will generate a slightly different config/application.rb file, with a require statement
for the sprockets railtie that is commented-out. You will have to remove the comment operator on that line to later
enable the asset pipeline:
# require "sprockets/railtie"
To set asset compression methods, set the appropriate configuration options in production.rb config.assets.css_compressor for your CSS and config.assets.js_compressor for your Javascript:
config.assets.css_compressor = :yui
config.assets.js_compressor = :uglify
The sass-rails gem is automatically used for CSS compression if included in Gemfile and no
config.assets.css_compressor option is set.
Asset Tag Helpers
Asset tag helpers provide methods for generating HTML that link views to feeds, JavaScript, stylesheets, images,
videos and audios. There are six asset tag helpers available in Rails:

auto_discovery_link_tag

javascript_include_tag

stylesheet_link_tag

image_tag

video_tag

audio_tag
You can use these tags in layouts or other views, although the auto_discovery_link_tag, javascript_include_tag,
and stylesheet_link_tag, are most commonly used in the <head> section of a layout.
The asset pipeline is compiled by default.
You refer to assets using %= image_tag 'logo.png', :style => "border: 0px solid white" %>
And background-image: image-url('portalPage.jpg');
Improvements to the Sprockets Gem in 4.0
Rails 4 automatically adds the sass-rails, coffee-rails and uglifier gems to your Gemfile, which are
used by Sprockets for asset compression.
If you are upgrading from Rails 3, please take into account that assets under lib/assets or vendor/assets are
available for inclusion via the application manifests but no longer part of the precompile array. See Precompiling
Assets for guidance.
The config.assets.compress initialization option is no longer used in Rails 4 to enable either CSS or
JavaScript compression. Setting it will have no effect on the application. Instead, setting
config.assets.css_compressor and config.assets.js_compressor will control compression of
CSS and JavaScript assets.
Page 23
Rails 4 no longer sets default config values for Sprockets in test.rb, so test.rb now requies Sprockets
configuration. The old defaults in the test environment are: config.assets.compile = true,
config.assets.compress = false, config.assets.debug = false and
config.assets.digest = false.
Specifying ‘require’ in files processed by Sprockets
One of the facilities provided by Sprockets is the ‘require’ directive, which is placed into a special comment syntax
as follows:
/*
*= require_self
*= require_tree .
*/
This will allow inclusion of other files. For instance “require_tree .” brings in all of the other css or scss files in the
directory. There is a similar syntax for inclusion used in JavaScript files.
In earlier versions of the Twitter Bootstrap 3 Gem, we would specify “require bootstrap”. However, the
documentation of the gem recommended against this, in favor of writing an @import statement. The description for
this is located at https://github.com/twbs/bootstrap-sass/issues/79#issuecomment-4428595
Sprockets compiles each file individually, so mixins or variables to set in one file do not work in another; hence, all the mixins and variables
available via Bootstrap are not within the scope of your own files, so you can't use them.
Import basically imports the files together and then they are compiled, allowing you to override and use Bootstrap.
Starting with release 3.2.x of the gem, the @import approach must be used.
Writing Controllers
These handle the requests.
New features in Rails 4.0:
 Mass assignment protection in Active Record models (GitHub, Pull Request)
 ActiveRecord::SessionStore (GitHub, Pull Request)
 Active Record Observers (GitHub, Commit)
 Active Resource (GitHub, Pull Request, Blog)
Strong Parameters
In the model classes, we used to have
class Post < ActiveRecord::Base
attr_accessible :title, :body
validates :title, :presence => true,
:length => { :minimum => 5 }
has_many :comments, :dependent => :destroy
end
Now I have had to comment out the “attr_accessible” line. What these lines had been doing was creating something
almost like getters and setters for the fields.
In posts_controller, change:
@post = Post.new(params[:post])
to:
@post = Post.new(params.require(:post).permit(:title, :body))
The same is needed in the “update” method. What the new code does is call the equivalent of the setter methods for
title and body. Apparently this improves the strictness of access and setting of model fields, perhaps for validation
reasons.
Page 24
Routing
The Rails router recognizes URLs and dispatches them to a controller's action. It can also generate paths and URLs,
avoiding the need to hardcode strings in your views.
When your Rails application receives an incoming request for:
GET /patients/17
it asks the router to match it to a controller action. If the first matching route is:
get '/patients/:id', to: 'patients#show'
the request is dispatched to the patients controller's show action with { id: '17' } in params.
You can also generate paths and URLs. If the route above is modified to be:
get '/patients/:id', to: 'patients#show', as: 'patient'
and your application contains this code in the controller:
@patient = Patient.find(17)
and this in the corresponding view:
<%= link_to 'Patient Record', patient_path(@patient) %>
then the router will generate the path /patients/17. This reduces the brittleness of your view and makes your
code easier to understand. Note that the id does not need to be specified in the route helper.
The routes are specified in config.routes.rb of each Rails application. Prior to Rails 3, these were specified by
adding to the map.routes variable, but in Rails 3 and later there is a more declarative syntax used, which in turn
provides a way to create multiple related mappings quickly, such as those for a resource.
Resource-oriented routing declarations
RR016::Application.routes.draw do
resources :purchases
end
Inside the block for the draw method is the resources method. Collections of similar objects in Rails are
referred to as resources. This method defines the routes and routing helpers (such as the edit_purchase_path
method) to your purchases resources.
Table 1.1. Routing helpers and their routes
Helper
Route
purchases_path
/purchases
new_purchase_path
/purchases/new
edit_purchase_path /purchases/:id/edit
purchase_path
/purchases/:id
In this table, :id can be substituted for the ID of a record. Each routing helper has an alternative version that will
give you the full URL to the resource. Simply use the _url extension rather than _path, and you’ll get a URL
such as http://localhost:3000/purchases for purchases_url.
Page 25
From this table, two of these routes will act differently depending on how they’re requested. The first route,
/purchases, takes you to the index action of PurchasesController if you do a GET request. GET
requests are the standard type of requests for web browsers, and this is the first request you did to this application. If
you do a POST request to this route, it will go to the create action of the controller. This is the case when you
submit the form from the new view. Let’s go to http://localhost:3000/purchases/new now and look at the source of
the page. You should see the beginning tag for your form looking like the following listing.
<form action="/purchases" class="new_purchase" id="new_purchase" method="post">
The two attributes to note here are the action and method attributes. The action dictates the route to where
this form goes, and the method tells the form what kind of HTTP request to make.
How’d this tag get rendered in the first place? Well, as you saw before, the app/views/purchases/new.html.erb
template uses the form partial from app/views/purchases/_form.html.erb, which contains this as the first line:
<%= form_for(@purchase) do |f| %>
This one simple line generates that form tag. When we look at the edit action shortly, you’ll see that the output of
this tag is different, and you’ll see why.
The other route that responds differently is the /purchases/{id} route, which acts in one of three ways. You
already saw the first way: it’s the show action to which you’re redirected (a GET request) after you create a
purchase.
Ad-Hoc Routing Declarations
You can specify a name for any route using the :as option:
get 'exit', to: 'sessions#destroy', as: :logout
This will create logout_path and logout_url as named helpers in your application. Calling logout_path
will return /exit
You can also use this to override routing methods defined by resources, like this:
get ':username', to: 'users#show', as: :user
This will define a user_path method that will be available in controllers, helpers and views that will go to a route
such as /bob. Inside the show action of UsersController, params[:username] will contain the
username for the user. Change :username in the route definition if you do not want your parameter name to be
:username.
In general, you should use the get, post, put and delete methods to constrain a route to a particular verb. You
can use the match method with the :via option to match multiple verbs at once:
match 'photos', to: 'photos#show', via: [:get, :post]
You can match all verbs to a particular route using via: :all:
match 'photos', to: 'photos#show', via: :all
Routing both GET and POST requests to a single action has security implications. In general, you should avoid
routing all verbs to an action unless you have a good reason to.
You can also have wildcards in the match expression.
Page 26
Listing Existing Routes
To get a complete list of the available routes in your application, visit http://localhost:3000/rails/info/routes in
your browser while your server is running in the development environment. You can also execute the rake routes
command in your terminal to produce the same output.
Both methods will list all of your routes, in the same order that they appear in routes.rb. For each route, you'll see:
 The route name (if any)
 The HTTP verb used (if the route doesn't respond to all verbs)
 The URL pattern to match
 The routing parameters for the route
Common Code (i.e., Helpers)
This is what Grails called “services”.
Resources
A “resource” represents a data model and the infrastructure around it for fetching, editing, creating etc. For
instance, a User is a resource. Working outwards from the User resource, we can now use all of the key concepts
introduced so far and put them together.
For instance, at the back end, we are also starting to think of the operations supported by the back end in terms of
REST operations.
On the front end, there are several tools that will help create HTML form screens for the CRUD operations. But
first, a diversion to show how to display debug information.
Showing Debug Information
There is a built-in debug method and params variable. Here we added it to the main layout:
<!DOCTYPE html>
<html>
.
.
.
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>
Use CSS such as:
.debug_dump {
clear: both;
float: left;
width: 100%;
margin-top: 45px;
}
Rails environments
Rails comes equipped with three environments: test, development, and production. The default
environment for the Rails console is development:
$ rails console
Page 27
Loading development environment
>> Rails.env
=> "development"
>>
This facility is used in the debug(params) if Rails.env.development? statement.
Resource specifications in Routes
This is a shortcut for specifiying all of the CRUD operations on a given entity.
SampleApp::Application.routes.draw do
resources :users
root to: 'static_pages#home'
match '/signup',
.
.
.
End
to: 'users#new'
Using Factories
In order to make the necessary User model object, we could use Active Record to create a user with User.create,
but experience shows that user factories are a more convenient way to define user objects and insert them in the
database. We’ll be using the factories generated by the Factory Girl gem.
As with RSpec, Factory Girl defines a domain-specific language in Ruby, in this case specialized for defining Active
Record objects. The syntax is simple, relying on Ruby blocks and custom methods to define the attributes of the
desired object. For cases such as the one in this chapter, the advantage over Active Record may not be obvious, but
we’ll use more advanced features of factories below.
As with other Ruby gems, we can install Factory Girl by adding a line to the Gemfile (since Factory Girl is only
needed in the tests, we’ve put it in the :test group).
group :test do
gem 'factory_girl_rails', '1.4.0'
end
Then install as usual:
$ bundle install
We’ll put all our Factory Girl factories in the file spec/factories.rb, which automatically gets loaded by RSpec.
The code needed to make a User factory appears below:
FactoryGirl.define do
factory :user do
name
"Michael Hartl"
email
"[email protected]"
password "foobar"
password_confirmation "foobar"
end
end
By passing the symbol :user to the factory command, we tell Factory Girl that the subsequent definition is for a
User model object.
Page 28
Using Git with Rails
Git is not specific to Rails, however, its use is very common for Rails developers. In turn, Git is used to provide a
way to communicate code and test cases to the continuous integration server as part of the Agile development
model.
The Hartl book suggests using the following .gitignore file:
.bundle
db/*.sqlite3*
log/*.log
*.log
tmp/**/*
tmp/*
doc/api
doc/app
*.swp
*~
.DS_Store
This will have the result of skipping temp files, log files, doc files, sqlite db files, the .DS_Store files created by
MacOS utilities, etc.
What is maintained is:
 app – contains models, controllers, views, etc.
 config – contains all config information.
 db – contains migrations
 lib – contains supporting DLL’s, library files, etc. (I think)
 public – contains the static html files (but we should skip the outputs of the asset precompiler)
 script – contains command-line scripts
 test – contains the test specs
 vendor – contains vendor-supplied files and assets, typically for third-party purchased components.
 Gemfile – describes the dependencies
Using Gravatars
Having defined a basic user page in the previous section, we’ll now flesh it out a little with a profile image for each
user and the first cut of the user sidebar. When making views, we’ll focus on the visual appearance and not worry
too much about the exact structure of the page, which means that (at least for now) we won’t be writing tests.
We’ll start by adding a “globally recognized avatar”, or Gravatar, to the user profile. Originally created by Tom
Preston-Werner (cofounder of GitHub) and later acquired by Automattic (the makers of WordPress), Gravatar is a
free service that allows users to upload images and associate them with email addresses they control. Gravatars are
a convenient way to include user profile images without going through the trouble of managing image upload,
cropping, and storage; all we need to do is construct the proper Gravatar image URI using the user’s email address
and the corresponding Gravatar image will automatically appear.
Our plan is to define a gravatar_for helper function to return a Gravatar image for a given user, as shown below:
app/views/users/show.html.erb
<% provide(:title, @user.name) %>
Page 29
<h1>
<%= gravatar_for @user %>
<%= @user.name %>
</h1>
Because the gravatar_for method is undefined, the user show view is currently broken. (Catching errors of this
nature is perhaps the most useful aspect of view specs. This is why having some test of the view, even a minimalist
one, is so important.)
Using Helpers
By default, methods defined in any helper file are automatically available in any view, but for convenience we’ll put
the gravatar_for method in the file for helpers associated with the Users controller.
app/helpers/users_helper.rb
module UsersHelper
# Returns the Gravatar (http://gravatar.com/) for the given user.
def gravatar_for(user)
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end
Further details of implementing User Management
Now that we have good failing tests for user signup, we’ll start getting them to pass by making a form for signing up
users. We can accomplish this in Rails with the form_for helper method, which takes in an Active Record object
and constructs a form using the object’s attributes.
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(@user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
Using Flash
Before submitting a valid registration in a browser, we’re going to add a bit of polish common in web applications: a
message that appears on the subsequent page (in this case, welcoming our new user to the application) and then
disappears upon visiting a second page or on page reload. The Rails way to accomplish this is to use a special
variable called the flash, which operates like flash memory in that it stores its data temporarily. The flash variable
Page 30
is effectively a hash; you may even recall the console example in Section 4.3.3, where we saw how to iterate through
a hash using a strategically named flash hash:
$ rails console
>> flash = { success: "It worked!", error: "It failed." }
=> {:success=>"It worked!", error: "It failed."}
>> flash.each do |key, value|
?> puts "#{key}"
?> puts "#{value}"
>> end
success
It worked!
error
It failed.
We can arrange to display the contents of the flash site-wide by including it in our application layout, as shown
below:
<!DOCTYPE html>
<html>
.
.
.
<body>
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
.
.
.
</body>
</html>
The code above arranges to insert a div tag for each element in the flash, with a CSS class indicating the type of
message. For example, if flash[:success] = "Welcome to the Sample App!", then the code
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
Session Management
To save data across multiple requests, you can use either the session or the flash hashes. A flash hash stores a value
(normally text) until the next request, while a session stores data during the complete session.
In your controller:
session[:user] = @user
flash[:message] = "Data was saved successfully"
Page 31
In your view:
<%= link_to "login", :action => 'login' unless session[:user] %>
<% if flash[:message] %>
<div>
<%= h flash[:message] %>
</div>
<% end %>
Caching (improved in Rails 4)


Action Caching (GitHub, Pull Request)
Page Caching (GitHub, Pull Request)
Testing within Rails
In the Ruby world a huge emphasis is placed on testing, specifically on test-driven development (TDD) and
behavior-driven development (BDD). There are three commonly-used testing tools, Test::Unit, RSpec, and
Cucumber.
By learning good testing techniques now, you’ve got a solid way to make sure nothing is broken when you start to
write your first real Rails application. If you didn’t test, there’s no telling what could go wrong in your code.
TDD is a methodology consisting of writing a failing test case first (usually using a testing tool such as Test::Unit),
then writing the code to make the test pass, and finally refactoring the code. This process is commonly called redgreen-refactor. The reasons for developing code this way are twofold. First, it makes you consider how the code
should be running before it is used by anybody. Second, it gives you an automated test you can run as often as you
like to ensure your code is still working as you intended. We’ll be using the Test::Unit tool for TDD.
BDD is a methodology based on TDD. It is slightly higher-level, in that you write an automated test to check the
interaction between the different parts of the codebase rather than testing that each part works independently.
The two tools used for BDD are RSpec and Cucumber, both of which the Hartl book uses heavily.
Testing
The default test framework is called Test::Unit. However, in the Hartl book he focuses on RSpec, so when creating
the Rails project, add the --skip-test-unit attribute to the command line.
Add something like the following to the Gem file:
group :development, :test do
gem 'sqlite3', '1.3.5'
gem 'rspec-rails', '2.10.0'
end
Next, we need to configure Rails to use RSpec in place of Test::Unit. This can be accomplished with rails
generate rspec:install:
$ rails generate rspec:install
More information on testing is located below.
Debugging
Edit config/environments/development.rb, for instance to change the development env’s log level.
This is recommended. Simply add the line config.log_level = :warn to set WARN level. This will
greatly decrease the amount of logging performed.
Then you can use logger.warn or a similar call. Note that not all objects can be converted into string for display.
Page 32
Pagination
We cover this here since it combines views, controllers, and models.
The Kaminari gem, is a new breed of pagination gem written by Akira Matsuda, and is available for both Rails 3 and
4. After you install this gem, you’re given an interface on the models of your application, which allows you to make
calls like this:
@project.tickets.page(2).per(50)
This call would ask for the second page of tickets, with each page containing 50 tickets. It’s a very clean API.
Those familiar with will_paginate will be used to a syntax like this:
@project.tickets.paginate(:per_page => 50, :page => 2)
The syntax is a little longer, but it’s a little clearer what it’s doing to those who are familiar with it. You’ll use
Kaminari here just for something different. In your views, you can use the same paginate method, which is made
available by both gems:
<%= paginate @tickets %>
Using Modules
A module is a reusable component of code. It is created/opened by simply coding:
module MyModule
def first_module_method
end
end
Places all modules into the lib folder. If you want to organize your modules in the lib folder, you can put them
into modules themselves. For example, if you wanted a subfolder super_modules your modules would be
defined as follows:
module SuperModules
module MyModule
def first_module_method
end
end
end
When including the module in a class you can simply call the modules methods as if they were defined within the
class:
class MyClass
include MyModule
def some_method
first_module_method #calls module method
end
end
When to use Modules?
First, make sure that your module is really needed in every class of your application. If it isn't it makes sense to only
include it where it is need so as not to bloat the classes that don't need it anyways.
If you really want the module everywhere, include look at the class hierarchy of your classes in the app. Do you
want the module in all models? You could open ActiveRecord::Base and add your module there.
Page 33
Rack
The term ‘Rack” refers to the middleware that is the interface between Rails as an application framework, and the
facilities provided by the web server/application server.
Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping
HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web
frameworks, and software in between into a single method call.
Rack was first developed in Rails 2.3, and moved into a gem of its own. It allows the substitution of different web
servers. For instance, development may use WEBrick, but production may use Phusion Passenger or Unicorn.
Rack-based Applications
Rack is the underlying web server framework that powers the underlying request/response cycle found in Rails, but
it isn’t a part of Rails itself. It’s completely separate, with Rails requiring the parts of Rack it needs. When your
application is running, it’s running through a web server. When your web server receives a request, it will pass it off
to Rack.
It is possible to develop applications directly at the Rack level rather than Rails-level, by using lighter-weight
frameworks such as Sinatra. Such a framework has no ORM, no configuration, not even a project structure, but can
be light-weight for deployment of a supporting server, such as one with no screens but only REST-based interfaces,
for instance.
A Rack-based application is typically started using the command “rackup”.
As of fall 2013, we haven’t worked directly with the Rack layer, though we briefly looked at Sinatra in Spring 2012.
Performance Testing (improved in Rails 4)
Performance tests (GitHub, Pull Request)
Using RSpec for Tests
Here we extend upon the initial information given regarding testing from the above sections.
Caching (new in 4.0)
Make it super easy to do Russian Doll-caching through key-based expiration with automatic dependency
management of nested templates (explored first in the cache_digests plugin).
Turbolinks (new in 4.0)
There is a facility to speed up the client-side with Turbolinks, which essentially turns your app into a single-page
JavaScript application in terms of speed, but with none of the developmental drawbacks (except, maybe,
compatibility issues with some existing JavaScript packages).
What is does is revise all of your <a> tags to run JavaScript that makes a request to the server using Ajax for the
new page content, then changes the body of the current page to be that content. Hence, the amount of processing on
the browser side (which generally includes processing the full request, including processing of the headers,
including processing of the resources referenced in the headers) is greatly reduced.
The compatibility issues stem from the idea that most JavaScript in your application is written with the assumption
that it running as part of a fresh page load. Hence, reaction to and comments on this feature have been mixed in the
developer community. In general, if you are dealing with the standard CRUD update screens as generated by the
Rails generator you will probably be okay, and if you are working a page or app that was designed to use Ajax and
be a single-page web app you won’t need Turbolinks, and if you are in between these cases, you need to review your
JavaScript and libraries carefully for compliance.
As of this point, we have skipped over Turbolinks, and focused on better understanding of JavaScript frameworks
such as Backbone and Angular.
Page 34
Declarative eTags (new in 4.0)
Declarative etags makes it even easier to ensure you're taking advantage of HTTP freshness.
Spork
You may have noticed that the overhead involved in running a test suite can be considerable. This is because each
time RSpec runs the tests it has to reload the entire Rails environment. The Spork test server (the name is based on
the name of a combination spoon-fork) aims to solve this problem. Spork loads the environment once, and then
maintains a pool of processes for running future tests. Spork is particularly useful when combined with Autotest.
Configuring Spork and getting it to work can be difficult, and this is a rather advanced topic; in particular, as of this
writing Spork doesn’t officially support Rails 3, so this section is really just a collection of hacks. Nevertheless, the
performance boost due to Spork is considerable, so I recommend giving it a shot at some point. (You’ll have to rely
on the Spork website and Google searches if these directions don’t work for you.)
Engines
Engines are a new feature for Rails 3. They are sub-applications that are packaged as gems and can run inside a
standard Rails application. They give you most of the functionality of a standard rails app, including the controllers,
views, helpers, configuration, etc… A Rails application is just a “supercharged” engine, with the Rails:Application
class inheriting a lot of its behavior from Rails:Engine.
Engines allow Rails programmers to share common code between applications in an extremely easy fashion. It’s
entirely possible to use more than one engine in an application, and many people do. Engines are generally provided
as gems, and so they are managed like every other gem your application uses: by using Bundler.
With an Engine, all the code (this includes models, controllers, views, and assets) is kept separate from the
application and must be explicitly overridden in the application if that’s what is needed. When a new version of an
engine is released, it will only alter the code of the engine and not the application, making the upgrade process as
easy as changing a version number in a Gemfile.
The term is most similar to “plugin” within other frameworks, in fact the command to create an Engine is “rails
plugin new”.
Examples of Engines
Devise
Forem
Spree
RefineryCMS
The structure of an Engine can be seen to be a subset of the structure of a full Application.
Engines are stored in the same place as gems within the Ruby directory structure:
Ruby193/lib/ruby/gems/1.9.3/gems directory
We will not be discussing Engines directly in this document, but several of the gems mentioned in the Appendixes
are in fact Engines (Devise is a good example).
Modularity through Engines
An Engine provides a useful coding abstraction to compartmentalize a “functional module” of an application. Each
Engine contains its models, views, controllers, and assets.
Apparently, some large Rails applications are built in this way. From a coding standpoint, the identifiers within
each Engine are scoped to a different Ruby namespace to avoid collisions.
Observations and Open Issues
Controllers and Models are Ruby code, the Views are ‘erb’ code. This is in contrast to CodeIgniter where all are
.php files.
Page 35
The name of a file does not always match the name of its contained class. Ruby is quite flexible in this regard.
The command-line tools are quite useful. Bundle is used manage gems, rake is used to manage the db, and rails is
used to carry out the generator and the execution. Rails includes an application runner (WEBrick).
Ruby is a more comprehensive language than PHP, and has better object-oriented support.
Testing: the emphasis is on unit tests and integration tests, using RSpec, rather than functional testing. Hence, no
discussion of Selenium or WebDriver appears here.
Appendix A: Chronology
05/19/12 to 05/20/12
Installed Rails 3.2.3, with Ruby 1.9.3p194. Found files at RailsInstaller.org
Loaded supporting gems including the DevKit (this appeared to be needed in order to run the JSON marshaller). A
key piece was the MySQL adapter, since we were changing the programs to work with MySQL instead of SQLite.
Wrote simple programs, working from http://guides.rubyonrails.org/getting_started.html
Reviewed books.
Ran example program of web application.
Tested the scaffolding functions.
06/20/12
Re-ran the examples. Continued to use Eclipse with a “general project” for the development tools. Since this takes
up a good bit of memory, something else might be better.
06/22/12
Looked at sample programs, and test cases for them.
06/24/12
Development meeting with Bucksprout, learned about a number of useful Gems.
06/30/12
By this point the RR01, RR02, and RR03 programs were in place, and the RR03 was starting to use the specified
Gems.
07/01/12
Moved knowledge gained from RR03 into RR02. Updated all documents as a result.
07/13-14/12
Re-worked all of our Rails documentation. Also looked at IDE/editors such as RubyMine and Sublime Text.
08/10/12
Began to evaluate Rails-based CMS programs.
07/03/13
Updated to 3.2.11 (at the Human API hackathon)
Late September 2013 to mid-October 2013.
Re-ran all examples, updated to Rails 3.2.14 and then to Rails 4.0.0. Began to use the RubyMine plugin with IntelliJ
instead of Eclipse.
10/31/13 to 11/03/13
Since the sample applications were now using all of the basic functions within the Rails framework, we began to
review more advanced documentation, including material on Rack and Engines. Completed another literature
search.
Late 2013
Deployed main Squirrel Legend server using Rails 4.0
Page 36
08/01/14
At the Startup Weekend event, evaluated Rails 4.1, and switched to it.
11/02/14
Updated the sample programs RR02 and RR03 to Rails 4.1 and Twitter Bootstrap 3.2.0. Also found a large number
of improvements to make in each one.
12/13/14
First event that integrated Rails and AngularJS.
Appendix C: Sample Programs
RR01
This is the example program from the on-line guide that is a blog with posts and comments. Changes made were
limited to simple layout modifications and CSS modifications. Uses PostgreSQL so that it can be deployed to
Heroku.
RR02
Improvement to RR01 that has a data model of Challenges and Activities. Uses PostgreSQL so that it can be
deployed to Heroku. Contains Squirrel Legend Games graphics.
RR03
This is a modification of RR01, showing use of the most important gems for User management.
[done] add User domain object
[done] install Devise
[done] add the ability for User to log in
[done] install CanCan for authorization
[not started] define admin page and separate operations between roles
RR04
Puts all of the above together, including use of Amazon Web Services S3 for images. Uses PostgreSQL.
A simple version of QbeFit, with the domain objects such as: ActivityType, Activity, ActivityEvent, and User.
[done] set up the model files, including user, role, and userrole (rolify was reverse engineered to help on this)
[done] install Devise
[done] install CanCan for authorization
[in progress] create a home page for a user
[in progress] create a home page for an admin
[in progress] change to use Paperclip for attachments (probably store these on the file system for now, later S3)
[not started] create “add activity” screen for a user
[not started] create track screen for a user
RR05
Rails plus Angular example, derived from CodingHouse training session
[done] basic setup, to match the end of the course
[in progress] display set of answers to a given question
RR06
This is a subset of the Squirrel Legend Games server, with multiple games, each having a list of episodes, and access
rules/sequencing for the episodes. We also need to define admin screens for some analytic entities.
[in progress] basic setup
Page 37
Appendix C: Gems of Interest to Try out
AB/Testing: Split
Attachments: Paperclip – Paperclip is intended as an easy file attachment library for ActiveRecord. The intent
behind it was to keep setup as easy as possible and to treat files as much like other attributes as possible.
http://github.com/thoughtbot/paperclip/tree/master. See http://burm.net/2008/10/07/the-ruby-on-rails-paperclipplugin-tutorial-easy-image-attachments/
Authorization: CanCan. See http://railsapps.github.com/tutorial-rails-bootstrap-devise-cancan.html
AWS S3 management: aws, fog
Procedural query generation: Squeel
User registration: Devise (an alternative is auth_logic)
Appendix D: Devise Gem
Devise is a gem that adds user management, including registration, log in, log out, etc. It is a very flexible package
that includes email sending and validation. This gem is used for a large number of user-centric applications.
The current release is 2.1.2 (June 2012). In this version, all deprecations from 2.0 have been removed, so we should
focus on this version.
Installation steps
Add the gem to the gem file, then run bundle install && rails generate devise:install
The installation step will give additional instructions, such as setting up the mail address, adding a flash and
message area to your layout screen, and adding routing information.
Next run, rails generate devise User, which will change the User model class to have additional
devise fields. It is here that you turn on and off elements of the 8 or 9 different options. Also change the migrate
file to have fields commented and out.
Now run a db:migrate, and you can run the application. Manually go to the users/sign_up screen.
Next, we changed the main application layout to have the following on the main screen:
<% if user_signed_in? %>
Signed in as <%= current_user.email %>.
<%= link_to 'Sign out', destroy_user_session_path, :method => :delete %>
<% else %>
<%= link_to 'Register', new_user_registration_path %> or
<%= link_to 'Sign in', new_user_session_path %>
<% end %>
From here, we typically focused on the user/role management and the CanCan gem.
However, there is one more step which will allow customization of the views for user registration and more. Run
rails generate devise:views. This will create about 12 views in the views/devise folder that implement
the various operations. You can add and re-arrange fields on these views. For instance, we added firstname and
lastname to the signup screen.
In the above example, the controllers for handling operations such as register and sign_in are located in the Devise
gem’s set of controllers, and pointed by the routing instruction “devise_for :users”. If you want to implement your
own versions of these, you can either:
Page 38
1.
2.
Override the controller class names that are to be used for actions. For instance use devise_for :users,
:controllers => {:registrations => "Nregistrations"} Typically the new classes will extend
from the ones provided in Devise.
Change the “devise_for” instruction as shown below and implement your own versions of all controllers.
devise_for :users, :skip => :all
This parameter tells Devise to not generate any route at all. You can check that by executing bundle exec
rake routes. However, you may be wondering: why can’t we simply remove the devise_for call? If we
remove the route, Devise wouldn’t actually know that you have added Devise configuration to the User model, as all
models are lazy loaded. So we need the route to tell Devise it needs to setup the appropriate helpers for the user,
like authenticate_user!.
With Devise configured, we are ready to create the controllers and views on our own. In this blog post, we are going
to create the SessionsController as an example allowing us to sign in and sign out. First, let’s add our routes:
root :to => "sessions#new" post "/users/sign_in"
delete "/users/sign_out" => "sessions#destroy"
=> "sessions#create"
The controller implementation is quite straightforward. With the controller in hands, we just need to generate the
view for the new action at app/views/sessions/new.html.erb:
Page 39
The view shows a message if the user is signed in, otherwise it shows a sign in form. Now we are almost ready to
check if it works. First, we need to run the migrations:
bundle exec rake db:migrate
Remove the index page:
rm public/index.html
And create a user in the database so we can sign in. We can do that in rails console:
User.create!(:email => "[email protected]", :password => "123456")
Now, start the server and you are ready to sign in and sign out. You can also block user access in any controller by
calling authenticate_user! in a before filter. Just remember that, if you add the filter to your application
controller, remember to skip the filter on the sessions controller, otherwise you won’t be able to sign in in the first
place.
You can now freely proceed to implement the other controllers and views in your application. Keep in mind that if
you have devise :recoverable in your model, all the related methods like
User.send_reset_password_instructions will already be available in your model, so you can use them
straight away to implement your own reset password feature. Since Devise use all those methods internally, if you
have any questions about implementing your own reset password feature, you can always take a look at Devise’s
own controllers for some help (find them in the source code on GitHub).
Appendix E: CanCan Gem
This is a permission management system that determines what operations a user can carry out. CanCan is an
authorization library for Ruby on Rails which restricts what resources a given user is allowed to access. All
permissions are defined in a single location (the Ability class) and not duplicated across controllers, views, and
database queries.
The current release is 1.6.10 (May 2013)
Using CanCan
First, add the “cancan” gem.
To use CanCan we need to create a new class called Ability, which we’ll place in our /app/models directory.
The class needs to include the CanCan::Ability module and also an initialize method that takes a user
object as a parameter and it’s in this method that we’ll define the abilities for each type of user. CanCan includes a
Rails 3 generator for creating this class.
rails g cancan:ability
Here is an example:
class Ability
include CanCan::Ability
def initialize(user)
can :read, :all
end
end
The abilities are specified with the method ‘can’ which is at the heart of CanCan. This method takes two parameters:
the first is the action that we want to perform and the second is the model class that the action applies to.
Alternatively, to apply an action to all models we can pass :all.
In the view code for the article’s show action we can call the can? predicate to determine whether the current user
is authorized to perform the action that each link links to. Like can, can? takes two parameters, an action and a
model, in this case an Article. There is an inverse predicate called cannot?. We’ll use can? in the show view
so that the edit and destroy links are hidden unless the current user has the appropriate ability.
<% if can? :update, @article %>
Page 40
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
<% if can? :destroy, @article %>
<%= link_to 'Destroy', @article, method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
This has removed the operations from the screen, however the smart user could still access the method by typing in
the URL directly. Hence, we must also check in the controller class.
def edit
@article = Article.find(params[:id])
unauthorized! if cannot? :edit, @article
end
To stop the action being executed we call unauthorized! which will raise an exception. Obviously we only want
this exception raised if the user does not have the appropriate authorization. To check this we can use can? as we
did in the view or, as we have here, cannot? to check the authorization.
If we try to access the edit action directly now we’ll be stopped from doing so and an error will be raised (rather
crudely – with a long stack trace).
Setting this for every action can be tedious, therefore the load_and_authorize_resource method is
provided to automatically perform an authorization check on all actions in a RESTful style resource controller (i.e.,
CRUD/admin). It will use a before filter to load the resource into an instance variable and check the auth for every
action.
class ArticlesController < ApplicationController
load_and_authorize_resource
def show
# @article is already loaded and authorized
end
end
If the user authorization fails, a CanCan::AccessDenied exception will be raised. You can catch this and
modify its behavior in the ApplicationController.
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
end
Note: in Rails 4 you must use:
load_and_authorize_resource :except => [:create, :update]
Adding Abilities
Now that our application is secure we can start to define the abilities that each role will have. This is done back in
the Ability class we created earlier. The abilities we define in the initialize method will be reflected through the rest
of our application.
We pass in the current user to initialize so we can change the abilities according to the currently logged-in
user. We’ll start with the users in the administrator role who should be able to manage everything.
The user passed to initialize can be an object of any type which means that the authentication is completely
decoupled from the authorization. What defines a user as, say, an administrator entirely depends on the
authentication system used. We might, for example, have an admin? boolean field in our User model. In our
application a user can have many roles and we’ll have a role? method to tell us if a user is a member of a role.
We’ll use that method to set the abilities:
Page 41
class Ability
include CanCan::Ability
def initialize(user)
if user.role? :admin
can :manage, :all
else
can :read, :all
end
end
end
The actual code we are using in the User model (different from the RailsCast is)
has_many :user_roles, :dependent => :destroy, :uniq => true
has_many :roles, :through => :user_roles, :uniq => true
# does this user have the specified role in its role list?
def has_role?(role_sym)
roles.any? { |role| role.name.underscore.to_sym == role_sym.downcase }
end
Here is a more complex case of authorization checking (where the user ||= User.new statement handles there
not being a current user):
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role? :admin
can :manage, :all
else
can :read, :all
can :create, Comment
can :update, Comment do |comment|
comment.try(:user) == user
end
end
end
end
Writing the code to enable guest users to create comments is straightforward but the update code is a little trickier as
users should only be able to update comments they have written. To do this we pass can a block which will pass in
the instance of the model we’re checking. The block should return true or false depending on whether the
action should be allowed so in the block we’ll check that the comment’s user is the current user. There’s a
possibility that the comment might be nil so we’ll use Rails’ try method to read the user attribute so that nil is
returned if the comment is nil instead of an exception being raised.
If we log in as a user who has no roles now we can add a comment and update it but not the comments made by
anyone else. This leads to:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role? :admin
can :manage, :all
else
can :read, :all
Page 42
can :create, Comment
can :update, Comment do |comment|
comment.try(:user) == user || user.role?(:moderator)
end
if user.role?(:author)
can :create, Article
can :update, Article do |article|
article.try(:user) == user
end
end
end
end
end
Now we have all of our abilities defined for each user role. The nice thing about CanCan is that it allows us to
define all of the abilities in one location and the rest of the application will reflect these changes.
A prettier error page
If a user calls an action that they don’t have access to they will see a rather ugly error page showing an
AccessDenied exception. We can change this so that they see a better-looking custom error page instead.
Rails provides a method called rescue_from that we can place in our ApplicationController. We pass it an
exception and pass it either a method or a block. We’ll pass a block and inside it make the application show a flash
error message and redirect to the home page.
rescue_from CanCan::AccessDenied do |exception|
flash[:error] = "Access denied!"
redirect_to root_url
end
If a user without roles now tries to edit an article by typing the URL in directly they’ll be redirected to the home
page and told that they can’t do that.
Creating role selection checkboxes
Note: The simplest rule of thumb when declaring many –to-many relationship is that you should set up a has_many
:through relationship if you need to work with the relationship model as an independent entity. If you don’t need to
do anything with the relationship model, it may be simpler to set up a has_and_belongs_to_many relationship
(though you’ll need to remember to create the joining table in the database).
It is often asked: how do I create a list of checkboxes for managing a HABTM association (e.g.: User to Roles)?
In User/_form.html.erb add:
<% for role in Role.all %>
<div>
<%= check_box_tag "user[role_ids][]", role.id, @user.roles.include?(role) %>
<%=h role.name %>
</div>
<% end %>
<%= hidden_field_tag "user[role_ids][]", "" %>
If no checkboxes are checked, the params[:user][:role_ids] array is not getting set at all (it is nil). Instead, you want
this to be an empty array. To fix this problem, add this to your update action in UserController.rb:
def update
params[:user][:role_ids] ||= []
…
end
Page 43
The ||= is a little strange, but it makes sense once you get used to it. It works just like an equal sign, but it only sets
the value if the original is nil - this is very useful.
Since we have separate model called User_Role, in order to assign new roles to user we need to define method in
User.rb to do this:
# For assignment of roles using checkboxes when creating or updating a user model.
def role_ids=(role_ids)
# It destroys all entries from user_roles which have not been selected using
# checkboxes (i.e. those which have been removed) and then adds any new ones
user_roles.each do |usr_role|
usr_role.destroy unless role_ids.include? usr_role.role_id
end
role_ids.each do |role_id|
self.user_roles.create(:role_id=>role_id) unless user_roles.any?
{|r|r.role_id==role_id}
end
end
To work with the strong parameters of Ruby 4.x, you will need to add role_ids to the permitted params, as shown
below:
def user_params
params.require(:user).permit(
:email, :facebook_id, :locked, :score_points, :location_id, :role_ids => []
)
end
Appendix F: Paperclip Gem
Paperclip is intended as an easy file attachment library for Active Record. The intent behind it was to keep setup as
easy as possible and to treat files as much like other attributes as possible. This means they aren't saved to their final
locations on disk, nor are they deleted if set to nil, until ActiveRecord::Base#save is called. It manages validations
based on size and presence, if required. It can transform its assigned image into thumbnails if needed, and the
prerequisites are as simple as installing ImageMagick (which, for most modern Unix-based systems, is as easy as
installing the right packages). Attached files are saved to the filesystem and referenced in the browser by an easily
understandable specification, which has sensible and useful defaults.
The basics of Paperclip are quite simple: Declare that your model has an attachment with the
has_attached_file method, and give it a name.
Paperclip will wrap up four attributes regarding your image (all prefixed with that attachment's name, so you can
have multiple attachments per model if you wish) and give them a friendly front end. These attributes are:
 <attachment>_file_name
 <attachment>_file_size
 <attachment>_content_type
 <attachment>_updated_at
By default, only <attachment>_file_name is required for paperclip to operate. You'll need to add
<attachment>_content_type in case you want to use content type validation.
More information about the options to has_attached_file is available in the documentation of
Paperclip::ClassMethods.
For validations, Paperclip introduces several validators to validate your attachment:
 AttachmentContentTypeValidator
 AttachmentPresenceValidator
 AttachmentSizeValidator
Example of Usage:
Page 44
validates :avatar, :attachment_presence => true
validates_with AttachmentPresenceValidator, :attributes => :avatar
Validators can also be defined using the old helper style:
 validates_attachment_presence
 validates_attachment_content_type
 validates_attachment_size
Example Usage:
validates_attachment_presence :avatar
Lastly, you can also define multiple validations on a single attachment using validates_attachment:
validates_attachment :avatar, :presence => true,
:content_type => { :content_type => "image/jpg" },
:size => { :in => 0..10.kilobytes }
Storage System
By default, the images will be stored in the local file system. You can configure the path using the “path” attribute
of has_attached_file. Here is an example:
:path => ":attachment/:id/:timestamp_:style.:extension",
Each of the placeholders will be filled in. You can structure the storage hierarchy as desired.
If you include the “fog” gem, you can write to external storage systems such as Amazon S3. Here is a configuration
that writes to S3:
Paperclip::Attachment.default_options.update(
{
:path => ":attachment/:id/:timestamp_:style.:extension",
:storage => :fog,
:fog_credentials => {
:provider => 'AWS',
:aws_access_key_id => '<API_KEY>',
:aws_secret_access_key => '<SECRET_KEY>',
:persistent => false
},
:fog_directory => 'rr016',
:fog_public => true
}
)
Appendix G: Squeel Gem
Consider the case of a complex query, such as in a Product listing. The search code seems like a fairly simple thing
to write but the query in the Product model is quite complicated. We need to search only the products that have
been released, that aren’t discontinued, that are in stock and which have a name that matches the search term. Here
is a typical implementation:
def self.search(query)
where("released_at <= ? and (discontinued_at is null or discontinued_at > ?) and
stock >= ? and name like ?", Time.zone.now, Time.zone.now, 2, "%#{query}%")
end
A fairly long SQL query is being performed here and which has a number of variables appended at the end and these
need to correctly line up with the parameters in the query. There are a variety of ways that we could improve this
Page 45
query and the biggest improvement we could make would be to move parts of the query into named scopes and
search using those.
If we did this we’d still be using SQL so we’d still need to worry about database differences such as in the LIKE
clause in our query. In most databases this will perform a case-insensitive query so if we were to switch the
application’s database to PostgreSQL we’d need to change this to ILIKE. It would be nice if there was some
consistency here and if we could abstract these database queries out. This is the problem handled by Squeel.
Initial Examples
We’ll start by experimenting with Squeel in the console. Squeel allows us to pass a block of code to a where call
and we can use the Squeel DSL inside this block. We can call any column as a method inside this block, like this:
Product.where{released_at <= 3.months.ago}
Squeel uses more than ActiveRecord::Relation, though. It’s built on Arel and uses that to convert queries into
SQL. We can see this if we look at the Squeel README which has a table showing a list of the operators that Arel
supports along with the equivalent SQL operator. So, instead of using the < operator that Squeel provides we can
use Arel’s lt method directly to make the same query.
You can also use the & and | operators to form ‘and’ and ‘or’ conditions. Note that you will typically need to fill in
the parenthesis in this case so that the operator parsing works as desired.
Getting back to our Product query, translated into Squeel code it becomes this:
def self.search(query)
where do
(released_at <= Time.zone.now) &
((discontinued_at == nil) | (discontinued_at > Time.zone.now)) &
(stock >= 2) & (name =~ "%#{query}%")
end
end
Note that for the LIKE clause we use =~, similar to the regular expression operator, and this will perform a caseinsensitive search no matter what database is being used. Also to compare against NULL we use == nil instead
of is null.
It’s arguable as to whether this code is cleaner than what we had before but one definite improvement is that the
values are inline in the query instead of being tagged on at the end. Also as we’re now using Ruby code we can use
a multiple-line block to spread the query out to make it easier to read. When we try the search field out in the
browser now it brings back the same results as our SQL query did.
Another example was first written for one of our test programs. This returns all of the challenges that are currently
in effect:
# GET /challenges/open
def open
@challenges = Challenge.where { (starts_at <= Time.now) & (ends_at >= Time.now) }
end
Keeping Things in Context
It’s important to remember that Squeel uses instance_eval when it calls the block. This means that the current
context in our block will not be the Product class but a Squeel DSL instance instead. If we want to call a class
method inside the block we can’t call it directly as Squeel will interpret the method call as a column name. To get
around this we need to call my and pass in a block. Anything inside the block will then be evaluated in the original
context. To demonstrate this we’ll add a low_stock method to our class and use it in our search.
Page 46
class Product < ActiveRecord::Base
belongs_to :category
def self.search(query)
where do
(released_at <= Time.zone.now) &
((discontinued_at == nil) | (discontinued_at > Time.zone.now)) &
(stock >= my{low_stock}) & (name =~ "%#{query}%")
end
end
def self.low_stock
2
end
end
This will perform the same search that we had previously.
Extending Squeel
If we want to customize some of Squeel’s behavior there’s a generator provided that will create an initializer for
doing so.
$ rails g squeel:initializer
create config/initializers/squeel.rb
This creates a config file which contains comments explaining the various settings we can change. For example
uncommenting the line shown below will add methods to the Hash and Symbol classes to simulate the Metawhere
functionality which is useful if you’re transitioning an application from Metawhere to Squeel.
Composing Queries with Squeel
This is what we really want to do. Suppose that we had the following classes:
class User < ActiveRecord::Base
has_many :microposts
end
class Micropost < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
validates :content, length: { maximum: 140 }
end
Example 1: Squeel condition composition inside block similar to Criteria. Write this inside one of your controllers:
params = {content: "First Post%", id: [1,2,3,4,5]}
@userWithInitialPost = current_user.microposts.where do
conditions = {}
conditions[id.in] = params[:id] if params[:id]
conditions[content.matches] = params[:content] if params[:content]
conditions
end
Example 2: Other complex queries involving joins. Write this include your domain class:
def usersWithInitialPosts(firstPost)
userList = User.joins(:microposts).where {
{ microposts => ( ((id.in ([1,2,3])) | content.matches(firstPost)))) }
}
end
Page 47
Appendix H: Rails 12factor Gem
Makes running your Rails app easier on Heroku. Based on the ideas behind 12factor.net
What it does
Rails gets a lot right when it comes to twelve-factor apps, but it could still be better. The two biggest areas right
now are that in production logs should be directed to stdout and dev/prod parity while delivering assets.
This gem enables serving assets in production and setting your logger to standard out, both of which are required for
to run a Rails 4 application on a twelve-factor provider. The gem also makes the appropriate changes for Rails 3
apps.
Appendix I: Fog Gem
This is a cloud services interface layer. Whether you need compute, dns, storage, or a multitude of other services,
fog provides an accessible entry point and facilitates cross service compatibility. The main site is at http://fog.io/
By coding with fog from the start you avoid vendor lock-in and give yourself more flexibility to provide value.
Whether you are writing a library, designing a software as a service product or just hacking on the weekend this
flexibility is a huge boon.
Support for AWS and Rackspace, among others. For a summary from 2010, see http://www.rubyinside.com/fog-apowerful-cloud-services-gem-3375.html For a summary from 2012, see http://sevos.github.io/2012/12/31/basics-offog-and-aws-for-rails-apps.html
Example of use for Storage:
storage = Fog::Storage.new({
:local_root => '~/fog',
:provider
=> 'Local'
})
storage will now contain our storage object, configured to use the Local provider from our specified directory.
Now that you have cleared the preliminaries you are ready to start storing data. Storage providers in fog segregate
files into directories to make it easier to organize things. So lets create a directory so we can see that in action.
directory = storage.directories.create(
:key => 'data'
)
To make sure it was created you can always check in your filesystem, but we can also check from inside fog.
storage.directories
Progress! Now it is time to actually create a file inside our new directory.
file = directory.files.create(
:body => 'Hello World!',
:key => 'hello_world.txt'
)
Mocking for tests
As you might imagine, testing code using Fog can be slow and expensive, constantly turning on and and shutting
down instances. Mocking allows skipping this overhead by providing an in memory representation resources as you
make requests. Enabling mocking easy to use, before you run other commands, simply run:
Fog.mock!
Then proceed as usual, if you run into unimplemented mocks, fog will raise an error.
Page 48
Appendix J: Tagging Gem
We use acts-as-taggable-on
See http://railscasts.com/episodes/382-tagging for more details
Appendix K: TheRubyRacer Gem
Integrates the JavaScript V8 engine into your Rails application. This could be useful in the ChallengeEngine
backend, in which the behavior of earning an achievement is configured by the challenge designer using a
JavaScript expression that is stored into the database and run at eval time using the V8 engine.
Page 49