Curso rails

56
Rails for real people @kurenn @rkrdo89 @icalialabs 1

description

 

Transcript of Curso rails

Page 1: Curso rails

Rails for real people

@kurenn@rkrdo89@icalialabs

1

Page 2: Curso rails

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

Page 3: Curso rails

1. From bottom to top3

Page 4: Curso rails

$ 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

Page 5: Curso rails

$ 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

Page 6: Curso rails

$ 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

Page 7: Curso rails

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

Page 8: Curso rails

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

Page 9: Curso rails

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

Page 10: Curso rails

$ 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

Page 11: Curso rails

2. MVC to rule them all11

Page 12: Curso rails

MVC

MVC to rule them all!

From the M to the C

Database

Actions

Browser

Model

Controller

View

12

Page 13: Curso rails

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

Page 14: Curso rails

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

Page 15: Curso rails

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

Page 16: Curso rails

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

Page 17: Curso rails

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

Page 18: Curso rails

3. Deep into the CRUD18

Page 19: Curso rails

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

Page 20: Curso rails

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

Page 21: Curso rails

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

Page 22: Curso rails

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

Page 23: Curso rails

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

Page 24: Curso rails

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

Page 25: Curso rails

Deep into the CRUD

CRUDelete Syntax

bp = BlogPost.find(1)bp.destroy

BlogPost.destroy_all

25

Page 26: Curso rails

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

Page 27: Curso rails

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

Page 28: Curso rails

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

Page 29: Curso rails

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

Page 30: Curso rails

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

Page 31: Curso rails

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

Page 32: Curso rails

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

Page 33: Curso rails

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

Page 34: Curso rails

4. Sexy Validations34

Page 35: Curso rails

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

Page 36: Curso rails

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

Page 37: Curso rails

http://api.rubyonrails.org/37

Page 38: Curso rails

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

Page 40: Curso rails

5. Three or more is a crowd40

Page 41: Curso rails

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

Page 42: Curso rails

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

Page 43: Curso rails

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

Page 44: Curso rails

6. REST in peace44

Page 45: Curso rails

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

Page 46: Curso rails

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

Page 47: Curso rails

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

Page 48: Curso rails

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

Page 49: Curso rails

7. A bit of java49

Page 50: Curso rails

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

Page 51: Curso rails

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

Page 52: Curso rails

http://railscasts.com/52

Page 53: Curso rails

http://api.rubyonrails.org/53

Page 54: Curso rails

http://www.codeschool.com/54

Page 55: Curso rails

http://ruby.railstutorial.org/55

Page 56: Curso rails

http://guides.rubyonrails.org/56