Curso rails
-
Upload
icalia-labs -
Category
Documents
-
view
816 -
download
0
description
Transcript of Curso rails
Rails for real people
@kurenn@rkrdo89@icalialabs
1
Table of contents
Rails for real people
01 From bottom to top
07 A bit of java
06 Rest in peace
05 Three or more is a crowd
02 MVC to rule them all!
04 Sexy Validation
03 Deep into the CRUD
2
1. From bottom to top3
$ railsUsage: rails new APP_PATH [options]
Options: -O, [--skip-active-record] -d, [--database=DATABASE]# Skip Active Record files# Preconfigure database# Default: sqlite3 -j, [--javascript=JAVASCRIPT] # Preconfigure JavaScript library # Default: jqueryRuntime options: -f, [--force] # Overwrite files that already exist -p, [--pretend] # Run but do not make any changes
Example:rails new ~/Code/Ruby/weblog
Creating rails app
From bottom to top4
$ rails
createcreate Gemfilecreate appcreate app/controllers/application_controller.rbcreate app/mailerscreate app/modelscreate app/views/layouts/application.html.erbcreate configcreate logcreate public/index.htmlcreate script/rails
This will create the skeleton for a Rails appin a new nerd_blog directory
new nerd_blog
run bundle install
Creating rails app
From bottom to top5
$ rails new nerd_blog
Fetching source index for http://rubygems.org/Installing rake (0.9.2)Using activesupport (3.1)Using rack (1.3.0)Using actionpack (3.1)Using actionmailer (3.1)Using activerecord (3.1)Using bundler (1.0.15)Installing coffee-script (2.2.0)Installing jquery-rails (1.0.12)Using rails (3.1)Installing sqlite3 (1.3.3) with native extensionsYour bundle is complete!
run bundle install
Creating rails app
From bottom to top6
Rails Commands
From bottom to top
$ cd nerd_blog $ rails
Usage: rails COMMAND [ARGS]
The most common rails commands are:generate Generate new code (short-cut alias: "g")console Start the Rails console (short-cut alias: "c")server Start the Rails server (short-cut alias: "s")dbconsole Start a console for the db in config/database.yml (short-cut alias: "db") All commands can be run with -h for more information.
Lists commands
7
Starting the server
From bottom to top
$ rails server Starts a basic development server
=> Booting WEBrick=> Rails 3.1 app in development on http://0.0.0.0:3000=> Call with -d to detach=> Ctrl-C to shutdown server[2011-06-30 16:44:43] INFO WEBrick 1.3.1[2011-06-30 16:44:43] INFO ruby 1.9.2[2011-06-30 16:44:43] INFO WEBrick::HTTPServer#start: port=3000
Shortcut
$ rails s
http://localhost:3000
8
Using generators
From bottom to top
$ rails generate Creates template files
Shortcut
$ rails g
Usage: rails generate <GENERATOR> [args]
Please choose a generator below.Rails: helper mailer migration model scaffold
9
$ rails console Loads the rails project console
Running the console
From bottom to top
Loading development environment (Rails 3.2)> User.create(email: ‘[email protected]’) SQL (15.2ms) INSERT INTO "users" ("email") VALUES(?) [["email", “[email protected]”]] => #<User id: 1, email: “[email protected]”>
Shortcut
$ rails c
10
2. MVC to rule them all11
MVC
MVC to rule them all!
From the M to the C
Database
Actions
Browser
Model
Controller
View
12
MVC to rule them all!
Controllers in the wild
$ rails g controller static_pages Creates a controller for static pages
‣ app/controllers/static_pages.rb
class StaticPagesController < ApplicationControllerend
Let’s add some actions
WTF! class StaticPagesController < ApplicationController
def homeend def aboutend
end
13
MVC to rule them all!
$ rails g controller static_pages home about
You kidding me?
Rails generates a views directory with the same name as the controller to bind them
Same concept for the actionsand views
def homeend def aboutend
get 'static_pages/home' get 'static_pages/about'
‣ config/routes.rb
Controllers in the wild
14
MVC to rule them all!
Views at sight
<!DOCTYPE html><html><head> <title>NerdBlog</title></head><body> <%= yield %></body></html>
‣ app/views/layouts/application.html.erb ‣ app/views/static_pages/home.html.erb
<h1>Home page</h1>
<p>You can find me in app/views/static_pages/home.html.erb
</p>
The views are rendered or yieldedinto the application layout
15
MVC to rule them all!
Views at sight
nerd_blog
app
views
layouts
static_pages
application.html.erb
home.html.erb
about.html.erb
This is the main layout
Renders the home template
Renders the about template
16
MVC to rule them all!
Helping views out!
‣ app/views/layouts/application.html.erb
<!DOCTYPE html><html> <head> <title><%= full_title(yield(:title)) %></title> </head> <body> <%= yield %> </body></html>
‣ app/views/static_pages/home.html.erb
<% provide(:title, "Home") %><h1>Pages#about</h1>
‣ app/helpers/application_helper.rb
module ApplicationHelper def full_title(page_title) "Blog | #{page_title}" endend
Helpers are intended to kill the logic in the views
17
3. Deep into the CRUD18
Deep into the CRUD
Spicy models
$ rails g model blog_post title:string content:text Creates a blog_post model
field type
BlogPost‣ app/models/blog_post.rb
class BlogPost < ActiveRecord::Base...end
id title content
1 Rails from scratch Lorem ipsum Lorem ipsum...
2 My first blog post Bacon ipsum Bacon ipsum Bacon ipsum...
3 How to make money Hipster ipsum Hipster ipsum Hipster ipsum...
blog_postsMaps the class to the table in plural
19
Deep into the CRUD
Create Read Update Delete
Create
bp = BlogPost.new
Read
Updatebp = BlogPost.find(5)
Delete bp.destroy
bp.title = "Learning Rails from scratch"bp.save
bp.title = "Updating title"bp.save
bp = BlogPost.find(5)
BlogPost.find(5)
20
Deep into the CRUD
Spicy models
But before you start run the migrations
$ rake db:create:all$ rake db:migrate
We’ll come back later on this
21
Deep into the CRUD
Create - RUD Syntax
bp = BlogPost.newbp.title = "Learning Rails from scratch"bp.save
Alternate Syntax
bp = BlogPost.new(title: "My blog is awesome", content: 'Lorem ipsum...')
BlogPost.create(title: "My blog is awesome", content: 'Lorem ipsum...')
Notice we never set the id, it gets
automatically set
bp.save
22
Deep into the CRUD
CRead - UD Syntax
BlogPost.find(1) # Returns single blog post with id 1
BlogPost.find(1, 2, 3) # Returns an array of blog posts with id 1,2 and 3
BlogPost.all # Returns an array with all blog posts
BlogPost.order(:created_at) # Returns an array of blog posts ordered by date of creation
BlogPost.limit(5) # Only five records
BlogPost.where(:status => "Draft") # Returns only blog posts on draft
BlogPost.where(:status => "Draft").order(:created_at).limit(5)
BlogPost.count # Returns the number of blog posts
All chained up!
23
Deep into the CRUD
CRUpdate - D Syntax
bp = BlogPost.find(1)bp.title = "Learning Rails from scratch"bp.save
bp.attributes = { title: "My blog is awesome", content: 'Lorem ipsum...' }
bp = BlogPost.find(1)
bp.save
bp.update_attributes( title: 'My blog is more awesome', status: 'Published')
bp = BlogPost.find(1)
24
Deep into the CRUD
CRUDelete Syntax
bp = BlogPost.find(1)bp.destroy
BlogPost.destroy_all
25
Deep into the CRUD
REST - 7 actions
Index GETHTTP
def index @blog_posts = BlogPost.all
respond_to do |format| format.html # index.html.erb end end
‣ app/controllers/blog_posts_controller.rb
‣ config/routes.rb
get '/blog_posts', to: 'blog_posts#index'
26
Deep into the CRUD
REST - 7 actions
Show :idPARAMS
def show @blog_post = BlogPost.find(params[:id])
respond_to do |format| format.html # show.html.erb end end
‣ app/controllers/blog_posts_controller.rb
‣ config/routes.rb
get '/blog_posts/:id', to: 'blog_posts#show'
GETHTTP
27
Deep into the CRUD
REST - 7 actions
New GETHTTP
def new @blog_post = BlogPost.new
respond_to do |format| format.html # new.html.erb end end
‣ app/controllers/blog_posts_controller.rb
‣ config/routes.rb
get '/blog_posts/new', to: 'blog_posts#new'
28
Deep into the CRUD
REST - 7 actions
Create POSTHTTP
‣ app/controllers/blog_posts_controller.rb
‣ config/routes.rb
post '/blog_posts', to: 'blog_posts#create'
def create @blog_post = BlogPost.new(params[:blog_post]) respond_to do |format| if @blog_post.save flash[:notice] = 'Blogpost was successfully created.' format.html { redirect_to(blog_posts_path) } else format.html { render "new" } end end end
X29
Deep into the CRUD
REST - 7 actions
Edit :idPARAMS
‣ app/controllers/blog_posts_controller.rb
‣ config/routes.rb
get '/blog_posts/:id/edit', to: 'blog_posts#edit'
GETHTTP
def edit @blog_post = BlogPost.find(params[:id]) respond_to do |format| format.html # edit.html.erb end end
30
Deep into the CRUD
REST - 7 actions
Update PUTHTTP
‣ app/controllers/blog_posts_controller.rb
‣ config/routes.rb
put '/blog_posts/:id', to: 'blog_posts#update'
def update @blog_post = BlogPost.find(params[:id])
respond_to do |format| if @blog_post.update_attributes(params[:blog_post]) flash[:notice] = 'Blogpost was successfully updated.' format.html { redirect_to(@blog_post) } else format.html { render "edit" } end end end
X31
Deep into the CRUD
REST - 7 actions
Destroy DELETEHTTP
‣ app/controllers/blog_posts_controller.rb
‣ config/routes.rb
delete '/blog_posts/:id', to: 'blog_posts#destroy' X
def destroy @blog_post = BlogPost.find(params[:id]) @blog_post.destroy
respond_to do |format| format.html { redirect_to(blog_posts_path) } end end
32
Deep into the CRUD
Point the path and I’ll follow it Syntax‣ config/routes.rb
get '/blog_posts', to: 'blog_posts#index' get '/blog_posts/:id', to: 'blog_posts#show' get '/blog_posts/new', to: 'blog_posts#new' post '/blog_posts', to: 'blog_posts#create' get '/blog_posts/:id/edit', to: 'blog_posts#edit' put '/blog_posts/:id', to: 'blog_posts#update' delete '/blog_posts/:id', to: 'blog_posts#destroy'
resources :blog_posts
blog_posts GET /blog_posts(.:format) blog_posts#index GET /blog_posts/:id(.:format) blog_posts#showblog_posts_new GET /blog_posts/new(.:format) blog_posts#new POST /blog_posts(.:format) blog_posts#create GET /blog_posts/:id/edit(.:format) blog_posts#edit PUT /blog_posts/:id(.:format) blog_posts#update DELETE /blog_posts/:id(.:format) blog_posts#destroy
$ rake routes
blog_posts GET /blogposts(.:format) blogposts#index
POST /blogposts(.:format) blogposts#create new_blog_post GET /blogposts/new(.:format) blogposts#newedit_blog_post GET /blogposts/:id/edit(.:format) blogposts#edit blog_post GET /blogposts/:id(.:format) blogposts#show
PUT /blogposts/:id(.:format) blogposts#update DELETE /blogposts/:id(.:format) blogposts#destroy
Rails flavor
33
4. Sexy Validations34
Sexy Validation
U shall not pass!
‣ app/models/blog_post.rb
class BlogPost < ActiveRecord::Base attr_accessible :content, :title validates_presence_of :titleend
> bp = BlogPost.new=> #<BlogPost id: nil, title: nil, content: nil>
$ rails console
> bp.save => false
> bp.error_messages => { title: ["can't be blank"] }
35
Sexy Validation
U shall not pass!
validates_presence_of :title
validates_numericality_of :words_count
validates_uniqueness_of :email
validates_confirmation_of :password
validates_format_of :email, with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates_acceptance_of :terms
And many many more...
..
.
36
Sexy Validation
Gemfile and Bundler
source 'https://rubygems.org'
gem 'rails', '3.2.12'
gem 'sqlite3'
# Gems used only for assets and not required# in production environments by default.group :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3'end
gem 'jquery-rails'
# To use debugger gem 'debugger'
‣ Gemfile
source 'https://rubygems.org'
gem 'rails', '3.2.12'
gem 'sqlite3'
# Gems used only for assets and not required# in production environments by default.group :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3' gem 'zurb-foundation', '~> 4.0.0'end
gem 'jquery-rails'
# To use debugger gem 'debugger'
$ rails g foundation:install
$ bundle install
38
http://foundation.zurb.com/docs/rails.html39
5. Three or more is a crowd40
Three or more is a crowd
A BlogPost has many comments A Comment belongs to a BlogPost
‣ app/models/blog_post.rb ‣ app/models/comment.rb
class BlogPost < ActiveRecord::Base
end has_many :comments
class Comment < ActiveRecord::Base
end belongs_to :blog_post
Plural Singularid title content
1 Rails from scratch Lorem ipsum Lorem ipsum...
2 My first blog post Bacon ipsum Bacon ipsum Bacon ipsum...
3 How to make money Hipster ipsum Hipster ipsum...
blog_posts
id content blog_post_id
1 It’s awesome 1
2 U shall not pass! 2
3 Sucks! 3
comments
41
Three or more is a crowd
What about then?
> bp = BlogPost.find(1)
A BlogPost has many comments
=> #<BlogPost id: 1, title: ‘Hello World’, content: ‘Lorem ipsum...’>
> c = Comment.create(content: ‘It works!’, blog_post: bp)=> #<Comment id: 1, content: ‘It works!’, blog_post_id: 1>
> c.blog_post=> #<BlogPost id: 1, title: ‘Hello World’, content: ‘Lorem ipsum...’>
> c.blog_post.title=> “Hello World”
> bp = BlogPost.find(1)=> #<BlogPost id: 1, title: ‘Hello World’, content: ‘Lorem ipsum...’>
> bp.comments.count=> 1
> bp.comments=>[#<Comment id: 1, content: ‘It works!’, blog_post_id: 1>]
42
Three or more is a crowd
What about then?
Using the belongs_to/has_many association, Rails provides construct methods
Method Purpose
comment.blog_post
blog_post.comments
blog_post.comments.create(args)
blog_post.comments.build(args)
Return the blog post associated to the comment
Return an array of the blog post’s comments
Create a comment(blog_post_id = blog_post.id)
Return a new comment instance(blog_post_id = blog_post.id)
43
6. REST in peace44
REST in peace
Let’s comment out
$ rails g controller Comments index new show edit
‣ app/config/routes.rb
resources :comments
resources :blog_posts do resource :comments end
A little bit more restful
$ rake routes
45
REST in peace
Controlling comments
‣ app/controllers/comments_controller.rb def create
end
@blog_post = BlogPost.find(params[:blog_post_id])@comment = @blog_post.comments.build(params[:comment])if @comment.save redirect_to blog_post_path(@blog_post_path), flash: { notice: 'Your comment was posted'}else redirect_to blog_post_path(@blog_post_path), flash: { error: 'Failes to post your comment, ja!'}end
1. We first fetch the blog post from the blog_post_id
2. Then build the comment through the blog post
3. Finally save the comment and redirect
46
REST in peace
And the views apa!‣ app/views/blog_posts/show.html.erb
<%= form_for [@blog_post, @comment] do |f| %> <div id="fields"> <%= f.label :content %> <%= f.text_area :content %> </div> <div id="actions"> <%= f.submit 'Post' %> </div><% end %>
Renders like this
Because our resources are nested we need the blog post for the comment
controller to find it in the create action through the blog_post_id
47
REST in peace
More on helpers!
form_for(record, options = {}, block)
text_field(object_name, method, options = {})
submit(value = nil, options = {})
truncate(text, options = {})
pluralize(count, singular, plural = nil)
titleize(word)
time_ago_in_words(from_time, include_seconds = false)
number_to_currency(number, options = {})
48
7. A bit of java49
A bit of java
Let’s have a bit of ajax‣ app/views/blog_posts/show.html.erb
<%= form_for [@blog_post, @comment], remote: true do |f| %> ...<% end %>
‣ app/controllers/comments/comments_controller.rb
I will respond to javascript
if @comment.save
else end
format.html { redirect_to blog_post_path(@blog_post_path)...
format.html { redirect_to blog_post_path(@blog_post_path)... format.js
respond_to do |format|
end
‣ app/views/comments/create.js.erb
$('#comments').append('<%= j render(@comment) %>');$('form').reset();
50
A bit of java
‣ app/views/comments/_comment.html.erb
<div class="comment"> <%= comment.content %></div>
The underscore means to render a partial
‣ app/views/comments/create.js.erb
$('#comments').append('<%= j render(@comment) %>');$('form').reset();
‣ app/views/blog_spots/show.html.erb
<div id="comments"> <%= render @blog_post.comments %></div>
Rails identify if object is an array or a single object when rendering like this
Let’s have a bit of ajax
51