2. “Building good software is not always easy,
but implementing agile practices with the
Ruby language and the Rails
framework can greatly simplify the
process.”
5. Iterative
Development
Working software is delivered to the client at regular,
short intervals. Client feedback is used to
make changes to the software specifications at any stage
in the development.
The client is asked to be fully engaged throughout the
development process.
6. Unrestricted communication between programmers and
clients.
Face to face communication is preferred over
specification documents.
The client can makes changes at anytime, and the
website can even be tested in production mode to get
user feedback.
Open
Collaboration
7. Changes to the software specifications
are welcome even in late stages of development.
Adaptability
14. 10.times do
puts "hola"
end
an_array.group_by {|a| a.type }
objects.each do |obj|
e.save!
end
[1,2,3,4,5,6,7].select{|x| x % 2 == 0}
File.open("config.txt") do |in|
in.each_line do |line|
process_config_line(line)
end
end
Making programming trulyMaking programming truly fun......
15. 10.times do
puts "hola"
end
an_array.group_by {|a| a.type }
objects.each do |obj|
e.save!
end
[1,2,3,4,5,6,7].select{|x| x % 2 == 0}
File.open("config.txt") do |in|
in.each_line do |line|
process_config_line(line)
end
end
Making programming trulyMaking programming truly fun......
class Product < ActiveRecord::Base
belogns_to :manufacturer
has_many :components
validates_presence_of :name, :price
validates_length_of :name, :maximum => 35
after_save :call_some_method
end
In Rails:
17. “Ruby” and “Ruby on Rails”
are not the same thing
Ruby
A Programming Language
1993 by Yukihiro “Matz” Matsumoto
18. “Ruby” and “Ruby on Rails”
are not the same thing
Ruby
A Programming Language
1993 by Yukihiro “Matz” Matsumoto
Ruby on Rails
Web Application Framework written in Ruby
2004 by David Heinemeier Hansson
19. Rubyis an Object Oriented scripting language.
Clean syntax.
Easy to learn.
Less and more redeable code.
Principle of Least Surprise (POLS).
Shorter development times.
Simple but powerful.
No compilation cycle.
21. Everything in Rails is
Ruby code
((SQLSQL andand JavaScriptJavaScript are abstracted)are abstracted)
22. ““Ruby successfully combines Smalltalk'sRuby successfully combines Smalltalk's
conceptual elegance, Python's ease of useconceptual elegance, Python's ease of use
and learning, and Perl's pragmatism.”and learning, and Perl's pragmatism.”
Curt Hibbs (O'Reilly Author)Curt Hibbs (O'Reilly Author)
““You can express ideas naturally andYou can express ideas naturally and
cleanly in Ruby code. This leads tocleanly in Ruby code. This leads to
programs that are easy to write and (just asprograms that are easy to write and (just as
importantly) are easy to read months later.”importantly) are easy to read months later.”
Dave Thomas (Agile Web Development withDave Thomas (Agile Web Development with
Rails)Rails)
23. Railsis an MVCweb framework where Models, views, and
controllers are fully integrated.
You automatically get all the benefits of an MVC design without the hassle of
explicitly configuring each component to play well with the others.
user@comp:~/$ rails myrailsapp
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create config/initializers
create db
create doc
create lib
create lib/tasks
...
24. ...
<% for client in @clients %>
<tr>
<td><%=h client.name %></td>
<td><%=h client.age %></td>
</tr>
<% end %>
...
Vapp/views/clients/index.html.erb
class Client < ActiveRecord::Base
#nothing here
end
Mapp/models/client.rb
class ClientsController < ApplicationController
def index
@clients = Client.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @clients }
end
end
...
end
Capp/controllers/clients_controller.rb
...
<tr>
<td>Damian Garcia</td>
<td>28</td>
</tr>
<tr>
<td>Gustavo Brey</td>
<td>28</td>
</tr>
...
Resulthttp://localhost:3000/clients
27. Instead of asking questions like:Instead of asking questions like:
“How do I get function x to call method y?”“How do I get function x to call method y?”
Developer is able to focus on how to do somethingDeveloper is able to focus on how to do something
He is freed to focus more on the general business logicHe is freed to focus more on the general business logic
of the application.of the application.
Rails uses simple naming conventions and clever useRails uses simple naming conventions and clever use
of reflection to make your work easier with near-zeroof reflection to make your work easier with near-zero
configurationconfiguration
29. Repeating code as little as possible makes it easier to make
changes later on in the development cycle.
If the code only exists in one place, it only needs to be changed in
one place.
32. exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/clients
exists app/views/layouts/
exists test/functional/
exists test/unit/
exists public/stylesheets/
create app/views/clients/index.html.erb
create app/views/clients/show.html.erb
create app/views/clients/new.html.erb
create app/views/clients/edit.html.erb
create app/views/layouts/clients.html.erb
identical public/stylesheets/scaffold.css
create app/controllers/clients_controller.rb
create test/functional/clients_controller_test.rb
create app/helpers/clients_helper.rb
route map.resources :clients
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/client.rb
create test/unit/client_test.rb
create test/fixtures/clients.yml
exists db/migrate
create db/migrate/20080812145516_create_clients.rb
Where the Templates Go
Within this directory, the
convention is to have a separate
subdirectory for the views of each
controller
By Convention:
usr@comp:~/myapp$ ruby script/generate scaffold client name:string age:integer comment:text
33. exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/clients
exists app/views/layouts/
exists test/functional/
exists test/unit/
exists public/stylesheets/
create app/views/clients/index.html.erb
create app/views/clients/show.html.erb
create app/views/clients/new.html.erb
create app/views/clients/edit.html.erb
create app/views/layouts/clients.html.erb
identical public/stylesheets/scaffold.css
create app/controllers/clients_controller.rb
create test/functional/clients_controller_test.rb
create app/helpers/clients_helper.rb
route map.resources :clients
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/client.rb
create test/unit/client_test.rb
create test/fixtures/clients.yml
exists db/migrate
create db/migrate/20080812145516_create_clients.rb
Where the Templates Go
Within this directory, the
convention is to have a separate
subdirectory for the views of each
controller
Each directory contains templates
named after the actions in the
corresponding controller
By Convention:
usr@comp:~/myapp$ ruby script/generate scaffold client name:string age:integer comment:text
34. Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
35. Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
app/models/client.rb
class Client < ActiveRecord::Base
end
36. Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
app/models/client.rb
class Client < ActiveRecord::Base
end
usr@comp:~/myapp$ ruby script/console
Loading development environment (Rails 2.3.2)
>>
37. usr@comp:~/myapp$ ruby script/console
Loading development environment (Rails 2.3.2)
>>
Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
app/models/client.rb
class Client < ActiveRecord::Base
end
38. usr@comp:~/myapp$ ruby script/console
Loading development environment (Rails 2.1.0)
>>
Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
app/models/client.rb
class Client < ActiveRecord::Base
end
client1 = Client.create(:name => "Gustavo Brey", :age =>
"28")
39. usr@comp:~/myapp$ ruby script/console
Loading development environment (Rails 2.1.0)
>>
Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
app/models/client.rb
class Client < ActiveRecord::Base
end
client1 = Client.create(:name => "Gustavo Brey", :age =>
"28")
=> #<Client id: 2, name: "Gustavo Brey", age: 28,
comments: nil, created_at: "2008-08-12 20:23:55",
updated_at: "2008-08-12 20:23:55">
>>
40. usr@comp:~/myapp$ ruby script/console
Loading development environment (Rails 2.1.0)
>>
Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
app/models/client.rb
class Client < ActiveRecord::Base
end
client1 = Client.create(:name => "Gustavo Brey", :age =>
"28")
=> #<Client id: 2, name: "Gustavo Brey", age: 28,
comments: nil, created_at: "2008-08-12 20:23:55",
updated_at: "2008-08-12 20:23:55">
>> client1.name
41. usr@comp:~/myapp$ ruby script/console
Loading development environment (Rails 2.1.0)
>>
Active Record doesn't requiere a mapping
file.
A developer doesn't need to code getters
and setters, or even the properties of the
class.
By Convention, ActiveRecord is
able to determine that the Client class will
map to the CLIENTS table in the DB, the
same with fields in table.
app/models/client.rb
class Client < ActiveRecord::Base
end
client1 = Client.create(:name => "Gustavo Brey", :age =>
"28")
=> #<Client id: 2, name: "Gustavo Brey", age: 28,
comments: nil, created_at: "2008-08-12 20:23:55",
updated_at: "2008-08-12 20:23:55">
>> client1.name
=> "Gustavo Brey"
42. exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/clients
exists app/views/layouts/
exists test/functional/
exists test/unit/
exists public/stylesheets/
create app/views/clients/index.html.erb
create app/views/clients/show.html.erb
create app/views/clients/new.html.erb
create app/views/clients/edit.html.erb
create app/views/layouts/clients.html.erb
identical public/stylesheets/scaffold.css
create app/controllers/clients_controller.rb
create test/functional/clients_controller_test.rb
create app/helpers/clients_helper.rb
route map.resources :clients
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/client.rb
create test/unit/client_test.rb
create test/fixtures/clients.yml
exists db/migrate
create db/migrate/20080812145516_create_clients.rb
When you generate a
controller Rails also
creates a layout for
that controller.
DRY, use Layouts
usr@comp:~/myapp$ ruby script/generate scaffold client name:string age:integer comment:text
You have the same look and
feel which needs to be
repeated in each of the
actions rhtml files.
The same functionality may
appear in multiple places.
Multiple pages may contain the
same snippets of rendered
HTML.
When Rails requests to render
a template within a controller, it
renders the one who you ask
for and also render a layout
template.
43. DRY, use Partials Partials ("partial views") are fragments of RHTML
that can be inserted into a view.
They exist to make the view logic simpler.
44. DRY, use Partials Partials ("partial views") are fragments of RHTML
that can be inserted into a view.
They exist to make the view logic simpler.
app/views/clients/edit.html.erb
<h1>Editing client</h1>
<% form_for(@client) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :age %><br />
<%= f.text_field :age %>
</p>
<p>
<%= f.label :comments %><br />
<%= f.text_area :comments %>
</p>
<p>
<%= f.submit “Update” %>
</p>
<% end %>
<%= link_to 'Back', clients_path %>
45. DRY, use Partials Partials ("partial views") are fragments of RHTML
that can be inserted into a view.
They exist to make the view logic simpler.
app/views/clients/edit.html.erb app/views/clients/new.html.erb
<h1>Editing client</h1>
<% form_for(@client) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :age %><br />
<%= f.text_field :age %>
</p>
<p>
<%= f.label :comments %><br />
<%= f.text_area :comments %>
</p>
<p>
<%= f.submit “Update” %>
</p>
<% end %>
<%= link_to 'Back', clients_path %>
<h1>New client</h1>
<% form_for(@client) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :age %><br />
<%= f.text_field :age %>
</p>
<p>
<%= f.label :comments %><br />
<%= f.text_area :comments %>
</p>
<p>
<%= f.submit “Create” %>
</p>
<% end %>
<%= link_to 'Back', clients_path %>
46. DRY, use Partials Partials ("partial views") are fragments of RHTML
that can be inserted into a view.
They exist to make the view logic simpler.
app/views/clients/edit.html.erb app/views/clients/new.html.erb
<h1>Editing client</h1>
<%= render :partial => 'form',
:locals => {:btn_text => "Update"} %>
<%= link_to 'Show', @client %> |
<%= link_to 'Back', clients_path %>
<h1>New client</h1>
<%= render :partial => 'form',
:locals => {:btn_text => "Create"} %>
<%= link_to 'Back', clients_path %>
47. DRY, use Partials Partials ("partial views") are fragments of RHTML
that can be inserted into a view.
They exist to make the view logic simpler.
app/views/clients/edit.html.erb app/views/clients/new.html.erb
<h1>Editing client</h1>
<%= render :partial => 'form',
:locals => {:btn_text => "Update"} %>
<%= link_to 'Show', @client %> |
<%= link_to 'Back', clients_path %>
<h1>New client</h1>
<%= render :partial => 'form',
:locals => {:btn_text => "Create"} %>
<%= link_to 'Back', clients_path %>
app/views/clients/_form.html.erb
<% form_for(@client) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :age %><br />
<%= f.text_field :age %>
</p>
<p>
<%= f.label :comments %><br />
<%= f.text_area :comments %>
</p>
<p>
<%= f.submit btn_text %>
</p>
<% end %>
48. Rails comes bundled with helpers capable of automating tasks such as
creating form fields, using Ajax, embedding assets such as JavaScript and CSS files,
etc.
Occasionally you’ll be looking for a helper that isn’t bundled with the documentation, one
capable of abstracting a task you’ll be using repeatedly in a view. You can do your own
Helper.
text_field(:post, :title, :size => 20)
<input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" />
hidden_field(:signup, :pass_confirm)
<input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]"
value="#{@signup.pass_confirm}" />
image_tag("icon")
<img src="/images/icon" alt="Icon" />
app/helpers/students_helper.rb
def result_img_tag(student)
student.result < 4 ? image_tag("red.png") : image_tag("green.png")
end
<table>
<% for student in @students %>
<tr>
<td><%=h student.name %></td>
<td><%=h student.age %></td>
<td><%= result_img_tag(student) %></td>
</tr>
<% end %>
</table>
49. Database agnosticism
Rails supports a wide array of databases, including all the
common production database platforms, MySQL, SQL Server,
DB2, Oracle, SQLite, etc.
54. class ClientsController < ApplicationController
...
# GET /clients/1
# GET /clients/1.xml
def show
@client = Client.find(params[:id])
respond_to do |format|
format.html # render show.html.erb
format.js # render show.js.rjs
format.xml { render :xml => @client }
end
end
...
end
Ajax call
In the RJS file you can express everything in Ruby code:
page.replace_html 'elementId', 'Replacement text'
page.remove 'elementId'
page.insert_html :top, 'myList', '<li>New list element<li>'
page.visual_effect :fade, 'elementId', :duration => 0.5
page[:someform].reset
page[:cart].update render(:partial => 'cart')
page[:list].reload #render list element with partial with the same name
page[:product].set_style :backgroundColor => '#f00'
page.delay(5.seconds) do
page[:something].visualEffect :puff
end
page << “(3).times( function(){ alert('hi!')});” # If you 'have to' use Javascript
page.draggable :product
page.drop_receiving :cart, :url => { :action => 'do_something'}
55. ReST (Representational State Transfer)
config/routes.rb
map.resource :clients
app/controllers/clients_controller.rb
class ClientsController < ActionController::Base
def index
respond_to do |format|
format.html
format.xml { render :xml => @clients }
end
end
def new ... end
def create ... end
def edit ... end
def update ... end
def destroy ... end
end
Action URL HTTP Method
index /clients GET
show /clients/2 GET
new /clients/new GET
create /clients POST
edit /clients/2/edit GET
update /clients/2 PUT
destroy /clients/2 DELETE
The core abstraction in REST is a remote resource instead of a remote procedure call.
Uses TCP/IP naming standards to name resources on the Web
Queries and manipulates those resources with HTTP
Uses standard text-based message formats like XML or HTML to structure data
56. TDD – Test Driven Development
- If you write tests before you write your code, you end up
writing better code.
- Forces you to think before you code.
- Code becomes is more focused and clear.
Write Tests
Write code until tests pass
Try optimizing the code
57. BDD – Behaviour Driven Development
- Less about writing tests, and more about writing specifications.
- Terminology focused on the behavioural aspects of the system
rather than testing.
- “Getting the words right”, this focus not only helps you and other
developers understand your application, but can be used to show your
client that the application is meeting their needs.
- The business, developers, testers, analysts and managers are not only
on the same page but using the same words.
- Developers gain confidence in the systems they build when the
behaviour of that system is confirmed.
“Enable better TDD, by focusing on behavior rather then testing”
Dan North (behaviour-driven.org)
RSpec
is a BDD framework for Ruby. It provides two frameworks for specify how your Ruby
application should behave:
- a Story Framework for describing behaviour at the application level
- a Spec Framework for describing behaviour at the object level
58. Capistrano
- A great tool for deploying your applications.
- It's not just a deploy tool, It lets you to execute commands on
multiple remote machines in parallel.
- Also lets you group your servers by role and specify tasks that
should only be executed for certain roles.
- Easy to extend. Capistrano is written in the Ruby
programming language, and may be extended easily by writing
additional Ruby modules.
- Interfaces with Git and Subversion.
- Is the tool of choice for many Rails developers for automating
deployment.
62. User
id
email
Built-in Database Schema Version Control
20080801031822_create_user.rb rake db:migrate
20080801122231_add_names_column.rb
Migration Files:
63. User
id
email
Built-in Database Schema Version Control
User
id
first_name
last_name
email
20080801031822_create_user.rb rake db:migrate
20080801122231_add_names_column.rb
Migration Files:
64. User
id
email
Built-in Database Schema Version Control
User
id
first_name
last_name
email
20080801031822_create_user.rb rake db:migrate
20080801122231_add_names_column.rb
Migration Files:
20080801442312_combine_name_columns.rb
65. User
id
email
Built-in Database Schema Version Control
User
id
first_name
last_name
email
20080801031822_create_user.rb rake db:migrate
20080801122231_add_names_column.rb
Migration Files:
20080801442312_combine_name_columns.rb
User
id
name
email
66. User
id
email
Built-in Database Schema Version Control
User
id
first_name
last_name
email
20080801031822_create_user.rb rake db:migrate
20080801122231_add_names_column.rb
Migration Files:
20080801442312_combine_name_columns.rb
User
id
name
email
20080801502802_rename_fullname.rb
67. User
id
email
Built-in Database Schema Version Control
User
id
first_name
last_name
email
20080801031822_create_user.rb rake db:migrate
20080801122231_add_names_column.rb
Migration Files:
20080801442312_combine_name_columns.rb
User
id
name
email
20080801502802_rename_fullname.rb
User
id
fullname
email
68. User
id
email
Built-in Database Schema Version Control
User
id
first_name
last_name
email
User
id
name
email
User
id
fullname
email
20080801031822_create_user.rb rake db:migrate
rake db:migrate:down
20080801122231_add_names_column.rb
20080801442312_combine_name_columns.rb
20080801502802_rename_fullname.rb
Migration Files:
69. Most popular choices for
Code Version Control and Tracking tool:
Centralized Repository:
SubversionSubversion + TrackTrack
Distributed Repository:
GitGit + LighthouseLighthouse
76. Comparison of same web application in Java and Rails:
Java Spring/Hibernate Rails
Lines of Code 3293 1164
Number of Classes: 62 55
Number of Methods: 549 126
Configuration Lines 1161 113
The Java app's configuration alone was nearly the size of the entire Rails codebase
Rails application was significantly (15%-30%) faster!
Source: http://www.theserverside.com/news/thread.tss?thread_id=33120
Some Numbers
84. 23 million unique visitors / month
2 million searches / day
More than 48 million requests / day
More than 1500 requests / sec
Source: http://assets.en.oreilly.com/1/event/6/Surviving%20the%20Big%20Rewrite_%20Moving
%20YELLOWPAGES_COM%20to%20Rails%20Presentation.pdf
YellowPages.comYellowPages.com
85. 10th most popular application on Facebook.
Nearly 600,000 active users.
Half a million unique visitors a day and growing fast.
300 million page views a month.
300% monthly growth rate, but that is plateauing.
2.1 million unique visitors in the past month
200 requests per second.
5TB of bandwidth per month.
Source: http://highscalability.com/friends-sale-architecture-300-million-page-view-month-facebook-ror-app
Friends for Sale (Facebook app)Friends for Sale (Facebook app)