Title: Intro' to Ruby
1Intro. to Ruby Intro. to Rails
- CS 98-10/CS 198-10
- Web 2.0 Programming Using Ruby on Rails
- Armando Fox
2Administrivia
- 5um signup!!
- Lab 0
- Self-diagnostic quiz on web page
- Hack sessions Th 4-5, Fri 1-2
- place, staffing TBA on webpage
- Books
- more or less required Agile Web Development with
Rails, 1st or 2nd ed. - Programming Ruby (free, online at
rubycentral.org/book) - or The Ruby Way by Fulton
- Online resources coming soon
3CS61A Keywords of the Day
4Review MVC
- Goal separate organization of data (model) from
UI presentation (view) by introducing
controller - mediates user actions requesting access to data
- presents data for rendering by the view
- Web apps are sort of MVC by design
Controller
View
Model
5Review CRUD in SQL
- 4 basic operations on a table row Create, Read,
Update attributes, Destroy - INSERT INTO students (last_name, ucb_sid,
degree_expected) VALUES (Fox, 99999,
1998-12-15), Â Â Â Â Â Â Â (Bodik, 88888,
2009-06-05) - SELECT FROM students WHERE (degree_expected lt
2000-01-01) - UPDATE students SET degree_expected2008-06-05
WHERE last_nameBodik) - DELETE FROM students WHERE ucb_sid99999
6Review C/C
- If data model is called Student
- model (Ruby class) is app/models/student.rb
- SQL table is students
- table row object instance
- columns object attribute
- controller methods live in app/controllers/student
_controller.rb - views are app/views/student/.rhtml
7Review C/C scaffolding
- Model Student implies...
- class StudentsController in students_controller.rb
- views in app/view/students/, ....
- table students, primary key id, column names
match Student classs attributes - 2 ways to scaffold your controller views
- metaprogramming makes it happen
8While were on SQL...whats a primary key anyway?
- Column whose value must be unique for every table
row - Why not just use (e.g.) last name or SID?
- SQL AUTO_INCREMENT function makes it easy to
specify an integer primary key - If using migrations to create tables
(recommended), Rails takes care of creating an
autoincrement primary key field called ID
CREATE TABLE students ( id INT NOT NULL
AUTO_INCREMENT, last_name VARCHAR(255),
first_name VARCHAR(255), ucb_sid INT(11)
DEFAULT 9999)
class CreateStudentsltActiveRecordMigration def
self.up create_table students do tbl
tbl.column last_name, string tbl.column
first_name, string tbl.column ucb_sid,
integer, nullgtfalse, defaultgt9999
end end def self.down drop_table students
endend
9Using ri and irb from the shell
- Ruby is interpreted (for now)
- irb is an interactive Ruby interpreter
- follow along with the examples!
- ri (Ruby info) is like man
- ri Comparable
- ri gsub
- ri Stringgsub
- Note, need to be in a shell that has PATH and
environment variables set correctly - See www.ruby-doc.org for more good documents
10Rubys Distinguishing Syntax Characteristics
- Syntax features
- Whitespace is not significant (unlike Python)
- Statements separated by semicolons or carriage
returns - Statement can span a newline
- Parentheses can often be omitted
- when unambiguous to parser use caution!!
- raise "D'oh!" unless valid(arg)
- raise "D'oh!" unless valid(arg)
- raise "D'oh!" unless valid(arg)
- Advice from your elders use a good text editor
11Naming conventions
- ClassNames
- class NewRubyProgrammer ... end
- method_names and variable_names
- def learn_conventions ... end
- predicate_like_methods?
- def is_faculty_member? ... end
- dangerous_methods!
- def brainwash_with_ruby! ... end
- symbols
- favorite_framework rails
- SOME_CONSTANTS or OtherConstants
- result in warning if reassigned after init
12Everything is an object (almost) everything is a
method call
- Everything is an object
- Even integers (try 57.methods)
- Even nil (try nil.respond_to?(to_s))
- (almost) every operator is really a method call
- my_str.length gt my_str.send(length)
- mymethod(foo) gt self.send(mymethod, foo)
- 1 2 gt 1.send(, 2)
- arr4 gt arr.send(, 4)
- arr3 foo gt arr.send(, 3, foo)
- if (x 3) gt if (x.send(, 3))
- in particular, things like implicit conversion
on comparison are done by the class methods, not
in the language (unlike, e.g., Perl)
13Variables Methods
- Variables have no type objects do
- variables spring into existence on first
assignment - nil,false are Boolean false everything else true
- Everything is passed-by-reference
- can use clone method to effect pass-by-value
- except Fixnums...
- Defining methods
- def foo(x) x,x1 end
- def foo(x)
- x,x1
- end
- def foo(x)
- return x,x1
- end
14Arrays
- x 3, 'a', "third", blah, last
- x0 gt 3
- x-1 gt last
- x-2 gt blah
- x-3..-1 gt "third", blah, last
- y 1,2
- y 3,4 gt 1,2,3,4
- y ltlt 5 gt 1,2,3,4,5
- y ltlt 6,7 gt 1,2,3,4,5,6,7
- Note! These are nearly all instance methods of
Arraynot language operators!
15Hashes
- h "key" gt 1, value gt "foo"
- h.has_key?("key") gt true
- h"not a key" gt nil (not an error!)
- h.delete(value) gt "key" gt 1
- h.merge( key2 gt "3", "hi" gt blah )gt
"key"gt 1, "key2" gt 3, hi gt blah - Ruby Rails idioms
- omitting braces when a function takes a hash as
its last argument - omitting parens around function arguments
- link_to "Edit student", controllergt'students',
actiongt'edit' - link_to("Edit student", controllergt'students',
actiongt'edit') - Warning! if ambiguous parse...better safe than
sorry!
16Classes Methods
- Methods for MyBank.com
- class Account
- _at__at_bank_name "MyBank.com"
- constructor is always called initialize
- def initialize(starting_balance0)
- _at_balance starting_balance
- end
- instance methods
- def balance
- _at_balance
- end
- def deposit(amount)
- _at_balance amount
- end
- def withdraw(amount)
- _at_balance - amount
- end
- A class method
- def self.bank_name
17Instance methods, not instance variables
- Lets try a few...
- my_account._at_balance
- my_account.balance
- my_account.balance 100
- _at__at_bank_name
- other_account Account.new(0)
- other_account.bank_name
- ...got it?
18Instance variables shortcut
- class Foo
- def initialize(bar,baz)
- _at_bar,_at_bazbar,baz
- end
- def bar _at_bar end
- def baz _at_baz end
- def bar(newbar) _at_barnewbar end
- def baz(newbaz) _at_baznewbaz end
- end
19Instance variables shortcut
- class Foo
- def initialize(bar,baz)
- _at_bar,_at_bazbar,baz
- end
- attr_accessor bar, baz
-
- end
20REMEMBER!
- a.b means call method b on object a
- a is the receiver to which you send the method
call, assuming a will respond to that method - does not mean b is an instance variable of a
- does not mean a is some kind of structure of
which b is a member - Understanding this distinction will save you from
much grief and confusion
21There are (almost) no Loops
- Objects manage their own traversal
- (1..10).each x ... gt range traversal
- my_array.each elt ... gt array traversal
- hsh.each_key key ... hsh.each_pair
key,val .. gt hash traversal - 10.times ... gt iterator of arity zero
- 10.times do ... end
- ... is a synonym for do...end
22What is duck typing?
- Ruby type set of values set of operations
- A ruby module defines...
- a collection of behaviors
- that depend only on the presence of one or more
specific existing behaviors
- i.e. If it looks like a duck and walks like a
duckgt it responds to the same methods as a
duck. - Note, a module ? a class
- but module methods can get mixed in to classes
23Mix-in example Comparable
- Define ltgt method for your class
- include Comparable
- methods in Comparable assume that objects of
target class (into which youre includeing)
respond to ltgt - doesnt actually matter what the class is!
- Get lt lt gt gt between? for free
- and, your class can now be sorted (by mixing in
Enumerable...what do you suppose it assumes?) - Enumerable also provides all?, any?, collect,
find, include?, inject, map, partition, ....
24Hashes and function calls
- Immediate hash (any object can be a key, any
object can be an attribute) - my_hsh foo gt 1, "x" gt nil, 3 gt 'a',4
- my_hshnonexistent_key returns nil
- Parens can be omitted from function calls if
parsing is unambiguous - x foo(3, "no") ? x foo 3, "no"
- Braces can be omitted from hash if parsing is
unambiguous - x foo( agt1,bgt2) ? x foo(agt1,bgt2)
- easy way to do keyword arguments
- Caveat passing immediates to a function that
accepts multiple hashes as its arguments
25Summary Rubys Distinguishing Features
- Object-oriented with single inheritance
- everything is an object
- almost everything is a method call
- Modules play a role similar to Javas interfaces
and enable duck typing - Dynamically typed
- Objects have types variables dont
- very few operators in the language most are
defined as instance methods on objects - Idiomatically, and () sometimes optional
26Active Record what is it?
- A class library that provides an
object-relational model over a plain old RDBMS - Deal with objects attributes rather than rows
columns - SELECT result rows ? enumerable collection
- (later) object graph ? join query
27More on Student Example
- object attributes are just instance methods (a
la attr_accessor) - so can already say stu.last_name, stu.ucb_sid,
etc. - what line in what file makes this happen?
- ActiveRecord accessors/mutators
- default attr_accessor for each table column
- perform type-casting as needed
- can be overridden, virtualized, etc.
28Example a short tour
Predicate-like method names often end with
question mark
self (like Java this) not strictly necessary here
Some useful class methods of Date
Interpolation of expressions into strings
29Virtual attributes example simple authentication
- Assume we have a table customers with columns
salt and hashed_password...
Defines the receiver method for password
Why do we want to use self here?
Wheres the accessor for password?
30Constructors
- Method named initialize, but invoked as new
- (at least) 3 ways to call it...
31New ! Create
- Call s.save to write the object to the database
- s.create(args) ? s.new(args) s.save
- s.update_attributes(hash) can be used to update
attributes in place - s.new_record? is true iff no underlying database
row corresponds to s - save does right thing in SQL (INSERT or UPDATE)
- Convention over configuration
- if id column present, assumes primary key
- if updated_at/created_at columns in table,
automatically are set to update/creation timestamp
32find() ? SQL SELECT
- To find an arbitrary single record
- s Student.find(first) returns a Student
instance - To find all records
- students Student.find(all) returns
enumerable! - find by 'id' primary key (Note! throws
RecordNotFound) - book Book.find(1235)
- Find a whole bunch of things
- ids_array get_list_of_ids_from_somewhere()
- students Student.find(ids_array)
- To find by column values
- armando Student.find_by_last_name('Fox') may
return nil - a_local_grad Student.find_by_city_and_degree_exp
ected('Berkeley', Date.parse('June 15,2007') - To find only a few, and sort by an attribute
- many_localgrads Student.find_all_by_city_and_deg
ree_expected('Berkeley', Date.parse('June
15,2007'),limitgt30,ordergtlast_name)
33Find by conditions
- Use ? for values from parameters. Rails will
sanitize the SQL and prevent any SQL injection - You will want to learn some minimal SQL syntax
You can also specify ordering and use arbitrary
SQL operators
Using SQL conditions books Book.find(all,
conditions gt pub_date between ? and ?,
paramsstart_date, paramsend_date,
order gt pub_date DESC)
34Find by conditions
- Use ? to substitute in condition values
- not mandatory, but a good idea!
- You can include other SQL functionality
- You can roll your own
- s Student.find_by_sql("SELECT FROM students
...")
Using SQL conditions books Book.find(all,
conditions gt pub_date between ? and ?,
paramsstart_date, paramsend_date,
order gt pub_date DESC)
35Advanced Find
You can also specify limits and offsets, and oh
so much more
- books Book.find(all,
- conditions gt pub_date between ? and ?,
- paramsstart_date, paramsend_date,
- limit gt 10, offset gt paramspage.to_i
10)
- lock - Holds lock on the records (default share
lock) - select - Specifies columns for SELECT (default
) - group - (used with select) to group
- readonly - load as read-only (object cant be
saved) - include - Prefetches joined tables (try include
first more about this in Section 4) - Note use SQL-specific features at your own
risk....
36Caveat!
- The result of a find-all operation mixes in
Enumerable - Enumerable defines methods find and find_all
- Not to be confused with ActiveRecordBasefind!
37- Caveats for using self.
- gt local variable, method, methodmissing
- so need self. even for mutators
- activerecord accessors/setters are lazy
memoized - dymamic finders are never memoized!
38Action View
- A template for rendering views of the model that
allows some code embedding - commonly RHTML also RXML, HAML, RJS
- note...too much code breaks MVC separation
- convention views for model foo are in
app/views/foo/ - Helper methods for interacting with models
- model values?HTML elements (e.g. menus)
- HTML form input?assignment to model objects
- DRY (Dont Repeat Yourself) support
- Layouts capture common page content at
application level, model level, etc.
(app/views/layouts/) - Partials capture reusable/parameterizable view
patterns
39Helper Methods for Input Output
- Review we saw a simple view already...
- Anatomy lt code gt lt output gt
- But these form tags are generic...what about
model-specific form tags? - In the RHTML template
- lt text_field 'student', 'last_name' gt
- In HTML delivered to browser
- ltinput id"student_last_name" name"studentlast_n
ame" size"30" type"text" value"Fox" /gt - What happened? For that we have to look at
partial.
40Action Controller
- Each incoming request instantiates a new
Controller object with its own instance variables - Routing (Sec. 4) determines which method to call
- Parameter unmarshaling (from URL or form sub.)
into params hash - ...well, not really a hash...but responds to ,
- Controller methods set up instance variables
- these will be visible to the view
- controller has access to models class methods
idiomatically, often begins with Model.find(...) - Lets see some examples...
41Then we render...
- Once logic is done, render the view
- exactly one render permitted from controller
method (1 HTTP request ? 1 response) - Convention over configuration implicit render
- if no other render specified explicitly in action
method - looks for template matching controller method
name and renders with default layouts (model, app)
42What about those model-specific form elements?
- Recallltinput type"text" id"student_last_name"
name"studentlast_name"/gt - Related form elements for student attributes will
be named studentattr - marshalled into params as paramsstudentlast_n
ame, paramsstudentdegree_expected, etc. - i.e, paramsstudent is a hash
last_namegtstring, degree_expectedgtdate, etc. - and can be assigned directly to model object
instance - helpers for dates and other complex
types...magic
43What else can happen?
- redirect_to allows falling through to different
action without first rendering - fallthrough action will call render instead
- works using HTTP 302 Found mechanism, i.e.
separate browser roundtrip - example create method
- success redirect to list action
- fail render the new action (without
redirect)...why?
44The Session Hash
- Problem HTTP is stateless (every request totally
independent). How to synthesize a session
(sequence of related actions) by one user? - Rails answer session is a magic persistent
hash available to controller - Actually, its not really a hash, but it quacks
like one - Managed at dispatch level using cookies
- You can keep full-blown objects there, or just
ids (primary keys) of database records - Deploy-time flag lets sessions be stored in
filesystem, DB table, or distributed in-memory
hash table
45The Flash
- Problem Im about to redirect_to somewhere, but
want to display a notice to the user - yet that will be a different controller instance
with all new instance variables - Rails answer flash
- contents are passed to the next action, then
cleared - to this action flash.nownotice
- visible to views as well as controller
- Strictly speaking, could use session clear it
out yourself
46Summary
- ActiveRecord provides (somewhat-)database-independ
ent object model over RDBMS - ActionView supports display input of model
objects - facilitates reuse of templates via layouts
partials - ActionController dispatches user actions,
manipulates models, sets up variables for views - declarative specifications capture common
patterns for checking predicates before executing
handlers
47Lab 1
- Create a simple 1-model RoR app with basic CRUD
MVC - Create database
- Create the table using migrations
- Create scaffolding using generator
- Find and fix a bug in the code provided to you
-o - Hack sessions, forums will help