Ruby on Rails

Download Report

Transcript Ruby on Rails

Ruby on Rails
Barry Burd
Drew University
[email protected]
Copy of these slides: http://www.burd.org/RoR.ppt
1
Agenda
• Ruby language
• Creating a Web application with Ruby on
Rails
• Fine tuning the Web application
• Doing other neat things
2
What is …?
• Ruby
– A simple, elegant, loosely typed, reflective,
interpreted programming language.
• Rails
– An add-on to Ruby for web/database
handling.
– Model-View-Controller
– Convention over configuration
– DRY philosophy
3
Ruby on Rails
• Advantage
– Lightning-fast prototyping
• Disadvantages(?)
– Development is not as fast with legacy db
– Development is not as fast if you customize
– Ruby programmers use Ruby idioms
– Difficult to deploy
– Security model isn’t as mature as Java EE
4
Hello world program
C:\ruby>irb --prompt simple
>> puts "Hello"
Hello
=> nil
>> exit
C:\ruby>
5
Defining and calling a method
C:\ruby>irb --prompt simple
>> def show(what)
>>
"You typed " + what + "."
>> end
=> nil
>> show("Hello")
=> "You typed Hello.“
>> puts show("Hello")
You typed Hello.
=> nil
6
Expression interpolation
>> def show(what)
>>
"You typed #{what}."
>> end
=> nil
>> puts show("Hello")
You typed Hello.
=> nil
>> def show(what)
>>
'You typed #{what}.'
>> end
=> nil
>> puts show("Hello")
You typed #{what}.
=> nil
7
Ruby is dynamically typed
(“duck typing”)
>> i = 7
=> 7
>> puts i, "\n"
7
=> nil
>> i = "Hello"
=> "Hello"
>> puts i
Hello
=> nil
8
Regular Expressions
>> line = "Perl"
=> "Perl"
>> if line =~ /Perl|Python/
>>
puts "Scripting language mentioned: #{line}"
>> end
Scripting language mentioned: Perl
=> nil
>>
=>
>>
>>
>>
=>
line = "Java"
"Java"
if line =~ /Perl|Python/
puts "Scripting language mentioned: #{line}"
end
nil
9
Blocks
>> def call_block
>>
puts "1"
>>
yield
>>
yield
>>
puts "3"
>> end
=> nil
>> call_block {puts "2"}
1
2
2
3
=> nil
10
Blocks with parameters
>> def call_block
>>
puts "1"
>>
yield(42)
>>
yield(79)
>>
puts "3"
>> end
=> nil
>> call_block {|x| puts x}
1
42
79
3
=> nil
11
>> 5.times {puts "*"}
*
*
*
*
*
=> 5
>> 3.upto(6) {|i| puts i}
3
4
5
6
=> 3
>> ('a'..'e').each {|char| puts char}
a
b
c
d
e
=> "a".."e"
12
Another Ruby program
C:\>type fact.rb
def fact(n)
return 1 if n == 0
f = 1
n.downto(1) do |i|
f *= i
end
return f
end
print fact(ARGV[0].to_i), "\n"
C:\>ruby fact.rb 10
3628800
C:\>ruby fact.rb 5
120
13
Ruby’s integers (and other things)
are of arbitrary size
C:\>ruby fact.rb 155
4789142901463393876335775239063022722
176295591337767174070096339929153381
622433264146569329274347655956110484
372311586936020749175429076661003216
274382475477806479918110524333880196
139452687559896255940215628508414806
740389616633144934400000000000000000
000000000000000000000
14
Ruby is object-oriented
class Point
def initialize(x, y)
@x = x; @y = y
self
end
def to_s
sprintf("%d@%d", @x, @y)
end
end
list1 = [10, 20, Point.new(2, 3), Point.new(4, 5)]
list2 = [20, Point.new(4, 5), list1]
print("list1: ", list1.inspect, "\n")
print("list2: ", list2.inspect, "\n")
C:\>ruby list3.rb
list1: [10, 20, #<Point:0x2867a48 @y=3, @x=2>,
<Point:0x2867a30 @y=5, @x=4>]
list2: [20, #<Point:0x28679e8 @y=5, @x=4>, [10, 20,
#<Point:0x2867a48 @y=3, @x=2>, #<Point:0x2867a30 @y=5,
@x=4>]]
15
Ruby has unit testing
class Adder
def initialize(number)
@number = number
end
def add(number)
return @number + number
end
end
require 'test/unit'
require 'adder'
class TC_Adder < Test::Unit::TestCase
def setup
@adder = Adder.new(5)
end
def test_add
assert_equal(7, @adder.add(2),
"Should have added correctly")
end
def teardown
@adder = nil
end
16
end
Class with a constructor
(from “Programming Ruby”)
class Song
def initialize(name, artist, duration)
@name = name
@artist = artist
@duration = duration
end
end
song = Song.new("Bicylops","Fleck",260)
17
Getters
# This code can come immediately after the previous
# slide’s code.
class Song
def name
@name
end
def artist
@artist
end
def duration
@duration
end
end
puts song.name
18
Quick way to create getters
class Song
attr_reader :name, :artist, :duration
end
puts song.name
19
>> class MyClass
>> end
=> nil
>> MyClass.methods
=> ["send", "name", "class_eval", "object_id", "new", "singleton_methods",
"__se
nd__", "private_method_defined?", "equal?", "taint", "frozen?",
"instance_variab
le_get", "constants", "kind_of?", "to_a", "instance_eval", "require",
"ancestors
", "const_missing", "type", "instance_methods", "protected_methods", "extend",
"
protected_method_defined?", "eql?", "public_class_method", "const_get",
"instanc
e_variable_set", "hash", "is_a?", "autoload", "to_s", "class_variables",
"class"
, "tainted?", "private_methods", "public_instance_methods", "instance_method",
"
require_gem_with_options", "untaint", "included_modules",
"private_class_method"
, "const_set", "id", "<", "inspect", "<=>", "==", "method_defined?", ">",
"===",
"clone", "public_methods", "protected_instance_methods", ">=", "respond_to?",
"
display", "freeze", "<=", "module_eval", "autoload?", "allocate", "__id__",
"=~"
, "methods", "require_gem", "method", "public_method_defined?", "superclass",
"n
il?", "dup", "private_instance_methods", "instance_variables", "include?",
"call
20
_block", "const_defined?", "instance_of?"]
Ruby is Reflective (1)
class Myclass
def mymethod
puts "Hello"
end
end
x = 'mymethod'
Myclass.new.send(x)
Hello
21
Ruby is Reflective (2)
class MyStuff
def announce
puts "I'm being announced.\n"
end
def method_missing(method_name)
puts "I don't know how to do #{method_name}.\n"
end
end
m = MyStuff.new
m.announce
m.xyz
I'm being announced.
I don't know how to do xyz.
22
Creating a web-based database application
in about a dozen steps…
23
Rails naming conventions
• company application
• company_development database
• employees table
• generate model Employee
• generate controller Employee
• employee_controller.rb
• EmployeeController class
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Using the Model to Validate Input
43
44
45
46
47
48
49
50
51
52
53
54
55
Many-to-many relationships
require "rubygems"
require_gem "activerecord"
ActiveRecord::Base.establish_connection(
:adapter=> "mysql",
:host => "localhost",
:database => "company2_development")
class Task<ActiveRecord::Base
has_and_belongs_to_many :employees
end
56
Many-to-many relationships
class Employee < ActiveRecord::Base
has_and_belongs_to_many :tasks
def acquire_task(task)
tasks.push_with_attributes(task)
end
def show_task(i)
puts tasks.find(i).description
end
def show_tasks
for task in tasks
puts task.description
end
end
end
57
Many-to-many relationships
emp1 = Employee.new
emp1.name = 'Barry Burd'
emp1.salary = 100000000.0
emp1.fulltime = false
emp1.level = 10
emp1.hiredate = '2006-08-22‘
emp1.save
task = Task.new
task.description = "Clean the office"
task.save
task2 = Task.new
task2.description = "Scoop the cat litter"
task2.save
58
Many-to-many relationships
emp = Employee.find(1)
emp.acquire_task(Task.find(1))
emp.acquire_task(Task.find(2))
emp2.show_tasks
Clean the office
Scoop the cat litter
59
Ajax
60
In the controller...
def show_body
@comment = Comment.find(params[:id])
render :text => @comment.body
end
61
In the view...
<head>
<%= javascript_include_tag "prototype" %>
</head>
...
<% for comment in @comments %>
<tr>
<td><%= comment.title %></td>
<td>
<div id="comment_<%= comment.id.to_s %>">
<%= link_to_remote( "Show Body",
:update => "comment_#{comment.id.to_s}",
:url => { :action => :show_body,
:id => comment }) %>
</div>
</td>
62
Sending Email
63
The Message Model
class CreateMessages < ActiveRecord::Migration
def self.up
create_table :messages do |t|
t.column :subject, :string
t.column :custname, :string
t.column :amount, :float
t.column :recipients, :string
t.column :sender, :string
end
end
def self.down
drop_table :messages
end
end
64
Configuring the mailer
ActionMailer::Base.server_settings = {
:address => "mail.cheapprovider.net",
:domain => "burdbrain.com",
}
65
The Mailer class
class MyMailer < ActionMailer::Base
def setup(message, sent_at = Time.now)
@subject
= message.subject
@body['custname'] = message.custname
@body['amount']
= message.amount
@recipients = message.recipients
@from
= message.sender
@sent_on
= sent_at
@headers
= {}
end
end
66
Email template
<head>
<style type="text/css">
p.indent { margin-left: 60px }
</style>
</head>
<h1>Third Notice!</h1>
Dear <%= @custname %>,<p>
Your bill is overdue. Please pay
<%= number_to_currency(@amount) %> immediately.<p>
<p class="indent">Signed,<br>Your
<i><b>friends</b></i>
at Burd Brain Consulting</p>
67
How to mail a message
def create
@message = Message.new(params[:message])
my_message = MyMailer::create_setup(@message)
my_message.set_content_type 'text/html'
MyMailer::deliver my_message
if @message.save
flash[:notice] = 'Message was successfully
created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end
68
Creating a Web Service
69
Describing the Web Service
class TimeServiceApi <
ActionWebService::API::Base
api_method :get_time, :expects => [:bool],
:returns => [:time]
end
70
The Time Service
require 'time'
class TimeServiceController <
ApplicationController
wsdl_service_name 'TimeService'
web_service_scaffold :use_service
def get_time(gmt)
(gmt)?(Time.now.getgm):(Time.now)
end
end
71
Add-Ons
• LoginGenerator
http://wiki.rubyonrails.com/rails/pages/LoginGenerator
• Payment
http://payment.rubyforge.org/
• ActiveSearch
http://julik.nl/code/active-search/index.html
• Active Merchant
http://home.leetsoft.com/am/
• …and lots more!
72
References
• Home:
http://www.rubyonrails.com
• THE books:
Programming Ruby:
http://www.rubycentral.com/book/index.html
Agile Web Development with Rails
http://www.pragmaticprogrammer.com/title/rails/
• My book:
Ruby on Rails For Dummies
http://www.amazon.com/blah-blah-blah...
• Resources:
http://www.rubyquiz.com/
http://www.ruby-doc.org/
http://www.rubycentral.com/
http://railsmanual.org/
http://www.freeonrails.com/
http://tryruby.hobix.com/
• Rails Web hosting:
http://railsplayground.com/
http://www.railshosting.org/#free
http://www.rubyonrailswebhost.com/
73
END
74