Title: Ruby
1Ruby Ruby on Rails trainingday three Ruby on
Rails
- RBC Dexia Investor Services
2Pre-requisites
2
3ActiveSupport
3
4ActiveSupport
- It consists in a lot of Ruby standard classes
extension - Integer
- Date, Time
- String
- Array
- Hash
- NilClass
-
- It makes the code far more simpler
5ActiveSupport
extensions to the Integer class 1.kilobyte
gt 1024 100.megabytes gt 104857600 1.odd?
gt true 1.even? gt false 1.day gt
86400 5.years gt 157788000 2.hours.from_now
gt Tue Dec 16 173035 ... 3.days.ago gt
Sat Dec 14 153035 ...
6ActiveSupport
extensions to the Date and Time
classes Date.today gt ltDate
4909619/2,0,2299161gt Time.now.yesterday gt
Mon Dec 15 182402 ... Time.now.tomorrow gt
Wed Dec 17 182409 .. Time.now.beginning_of_week
gt Mon Dec 15 000000 ... Time.now.last_year
gt Sun Dec 09 180342 Time.days_in_month(12)
gt 31
7ActiveSupport
extensions to the String class "2008-12-16".to_d
ate gt ltDate 4909663/2,0,2299161gt "2008-12-31
410 pm".to_time gt Wed Dec 31 161000 UTC
2008 "ruby on rails".starts_with? "ruby" gt
true "ruby on rails".ends_with? "ruby" gt
false "ruby on rails".at 5 gt
"o" "ruby".pluralize gt "rubies" "ruby_on_rai
ls".camelize gt "RubyOnRails" "ruby on
rails".titleize gt "Ruby On Rails"
8ActiveSupport
extension to the Array class "accounts",
"show", "1".to_param gt "accounts/show/1" 1,
2, 3.to_sentence gt "1, 2, and 3"
extensions to the Hash class "ruby" gt "rails"
.symbolize_keys gt ruby gt "rails"
ruby gt "rails" .symbolize_keys gt "ruby"
gt "rails"
9ActiveSupport
don't waste your time checking
these "".empty? gt true .empty? gt
true .empty? gt true nil.nil? gt
true use .blank? "".blank? gt
true .blank? gt true .blank? gt
true nil.blank? gt true
10Testing with Ruby on Rails
10
11Testing with Ruby on Rails
- Testing is an important part of software
development - Do you agree ? (you should !)
- Ruby on Rails encourages you to write tests
12Testing with Ruby on Rails
- Every time you generate a model, Rails creates
- A corresponding unit tests file
- A corresponding fixtures files
- Every time you generate a controller, Rails
creates - A corresponding functional tests file
13Testing unit tests
require File.dirname(__FILE__)
'/../test_helper' class BookTest lt
TestUnitTestCase fixtures books
Replace this with your real tests. def
test_truth assert true end end
14Testing fixtures
Read about fixtures at http//ar.rubyonrails.org
/classes/Fixtures.html first id 1 another
id 2
15Testing functional tests 1/2
require File.dirname(__FILE__)
'/../test_helper' require categories_controller'
Re-raise errors caught by the
controller. class CategoriesController def
rescue_action(e) raise e end end class
CategoriesControllerTest lt TestUnitTestCase
def setup _at_controller CategoriesController.n
ew _at_request ActionControllerTestRequest
.new _at_response ActionControllerTestRespo
nse.new end
16Testing functional tests 2/2
Replace this with your real tests. def
test_truth assert true end end
17Testing how to run the tests
- Tests can be run, file by file, from the command
line - ruby test/unit/book_test.rb for example
- They can be run from within the RadRails IDE
- Right-click, Run as test
- They can also be launched through rake tasks
- rake test, run all units and functionals tests
- rake testfunctionals, run the functional tests
- rake testunits, run the unit tests
18Testing exercise
- Prepare the test database
- rake dbtestclone_structure will help you
- Run the tests for the Book model from the IDE
- Run the same tests from the command line
19Testing how it works
- The test file is read
- For each parameter passed to the fixtures class
method - The corresponding table is emptied in the test
database - The records described in the fixtures file are
loaded -
- For each method starting with test_
- A rollback is performed
- The setup method is called
- The test method is executed
- The teardown method is called
20Testing testing the Book model
- The Book model has many validations
- Lets test the validates_presence_of title
21Testing testing the Book model
A better test testing exactly the
validation A book shouldn't save without a
title def test_shouldnt_save_without_a_title
book Book.new assert !book.save
assert_equal "can't be blank", book.errorstitle
end
22Testing testing the Book model
Some fixtures for the books table programming_ru
by id 1 title Programming Ruby isbn
9780974514055 pages 864 The_ruby_way id 2
title The Ruby Way isbn 9780672328848
pages 888
23Testing testing the Book model
The test as it should be A book shouldn't
save without a title def test_shouldnt_save_with
out_a_title book Book.find first
book.title nil assert !book.save
assert_equal 1, book.errors.size assert_equal
"can't be blank", book.errorstitle end
24Testing exercise
- Fill your fixtures with books of your own
- rake dbtestclone_structure will help you
- Write the other tests for the Book model
- Hints
- ri will report you which custom assertion methods
exist
25Back to our application
25
26Build our application
- Create a generic layout
- Create an authentication system
- Update routes to connect to login
- Create pages for categories
- Create pages for authors
- Update pages for books to include categories
authors
27Creating a basic layout
27
28Layout
- Use the provided layout
- Put in app/views/layouts/application.rhtml
- Delete specific layouts
- Use the provided images
- Put in public / images
29Creating a basic authentication system
29
30Authentication
- Everybody can connect to the application
- Everybody can visit every page of the
application - Create books
- Update books
- Delete books
-
- It requires an authentication system
31Authentication the User model
- Create a User model
- Having a login and a password
- Hints
- No hint
32Authentication the User model
-- in the database create table users ( id
integer primary key, login varchar(20),
password varchar(20) ) the model class User lt
ActiveRecordBase validates_presence_of
login, password validates_uniqueness_of
login end
33Authentication the Users controller
- Create a Users controller, with the standard
actions - Index, which calls the list action (used if no
action called) - List, which displays all the users
- Show, which displays a given user
- New, which displays a form to fill in a new user
- Create, which tries to create a new user
- Edit, which displays a form to modify a given
user - Update, which tries to update a given user
- Destroy, which tries to destroy a given user
- Hints
- No hint
34Authentication the Users controller
class UsersController lt ApplicationController
lists all the users if no action is called
def index list render action gt 'list'
end lists all the users def list
_at_users_pages, _at_users paginate users, per_page
gt 10 end
35Authentication the Users controller
displays a given user def show _at_user
User.find(paramsid) end requests to
create a new user def new _at_user User.new
end requests to edit a given user def edit
_at_user User.find(paramsid) end
36Authentication the Users controller
creates a new user def create _at_users
Users.new(paramsusers) if _at_users.save
flashnotice 'Users was successfully
created.' redirect_to action gt 'list'
else render action gt 'new' end end
37Authentication the Users controller
updates a user def update _at_users
Users.find(paramsid) if _at_users.update_attri
butes(paramsusers) flashnotice
'Users was successfully updated.'
redirect_to action gt 'show', id gt _at_users
else render action gt 'edit' end end
38Authentication the Users controller
destroy the given user def destroy
Users.find(paramsid).destroy redirect_to
action gt 'list' end end
39Authentication the Users views
- Create the corresponding views, in
app/views/users/, so - that you can populate the User model through
the - application
- Hints
- You can get inspired from what the other
controllers views contain
40Authentication the Users views
lt!-- index.rhtml --gt lth3gtListing all users in the
applicationlt/h3gt lttablegt lttrgt
ltthgtLoginlt/thgt ltthgtPasswordlt/thgt lt/trgt
41Authentication the Users views
lt!-- index.rhtml --gt lt _at_users.each do user
gt lttrgt lttdgtlth user.login gtlt/tdgt
lttdgtlt user.password gtlt/tdgt lttdgtlt link_to
'Show', action gt show, id gt user gtlt/tdgt
lttdgtlt link_to 'Edit', action gt edit, id gt
user gtlt/tdgt lttdgtlt link_to 'Destroy',
action gt destroy, id gt user , confirm gt
'Are you sure?', post gt true gtlt/tdgt lt/trgt lt
end gt lt/tablegt
42Authentication the Users views
lt!-- show.rhtml --gt ltpgt ltbgtloginlt/bgt lt
_at_user.login gt lt/pgt ltpgt ltbgtpasswordlt/bgt lt
_at_user.password gt lt/pgt lt link_to 'Edit',
action gt edit, id gt _at_user gt lt link_to
'Back', action gt index gt
43Authentication the Users views
lt!-- _form.rhtml --gt lt error_messages_for
'user' gt ltpgtltlabel for"user_login"gtLoginlt/label
gtltbr/gt lt text_field 'user', 'login'
gtlt/pgt ltpgtltlabel for"user_password"gtPasswordlt/la
belgtltbr/gt lt text_field 'user', 'password'
gtlt/pgt
44Authentication the Users views
lt!-- new.rhtml --gt lth3gtCreating a new
userlt/h3gt lt start_form_tag action gt create
gt lt render partial gt 'form' gt lt
submit_tag "Create" gt lt end_form_tag gt lt
link_to 'Back', action gt list gt
45Authentication the Users views
lt!-- new.rhtml --gt lth3gtEditing a userlt/h3gt lt
start_form_tag action gt update, id gt _at_user
gt lt render partial gt 'form' gt lt
submit_tag 'Edit' gt lt end_form_tag gt lt
link_to 'Show', action gt show, id gt _at_user gt
lt link_to 'Back', action gt index gt
46Authentication the login
- To allow users to log in, it requires
- A form so that they can enter their login and
password - An action to check if this pair is valid
- Theres already such a form (_form.rhtml)
- If the authentication succeed, where can the
information - be stored ?
47Authentication the login view
lt!-- login.rhtml --gt ltpgtlt flashnotice
-gtlt/pgt lt start_form_tag action gt login gt
lt render partial gt 'form' gt lt
submit_tag "Login" gt lt end_form_tag gt
48Authentication the login action
def login if request.post? first case the
action is called from the form _at_user
User.find_by_login_and_password
paramsuserlogin, paramsuserpassword
if _at_user.nil? flashnotice "Bad
authentication" else
flashnotice "Authentication successful"
sessionuser _at_user.id
redirect_to controller gt "books", action gt
"list" end
49Authentication the login action
else second case the request is a GET one, it
displays the login _at_user User.new end
end update the index method to display the
login screen def index render action gt
login' end
50Authentication cleanup
- To remove all sessions previously created
- Delete all ruby_sess. files under tmp/sessions
- rake tmpsessionsclear does the same thing
51Authentication protecting books
- To protect the Books controller action from
responding to - a user not authenticated
- The Books controller actions need to check
sessionuser - They must redirect to the login screen if
sessionuser is nil - This check can be shared in the Application
controller - Every each controller can use it to hide from
unknown visitors
52Authentication the shared method
class ApplicationController lt ActionControllerBa
se protected def check_user_is_authenticated
if sessionuser.nil?
flashnotice "You must be logged to access
this page" redirect_to(controller gt
"users", action gt login) end end end
53Authentication in BooksController
class BooksController lt ApplicationController
before_filter check_user_is_authenticated
... end
54Some considerations about routing
54
55Routing
- The config/routes.rb file contains information
to let the - dispatcher route the incoming request to the
right - controller and actions
- It also allows to define named routes
56Routing named routes
writing this route map.login 'login',
controller gt 'users', action gt 'login'
allows to replace redirect_to controller gt
'users', action gt 'login' by redirect_to
login_url
57Creating Categories Authors pages
57
58Categories Authors pages
- Create Categories Authors pages as Books
59Update the books paages
59
60Books pages
- Add a select box to select a category
- Add a select box to select an author
61_END_
61