Intro to Rails 4

33
Introduction to Rails 4 by Kartik Sahoo

Transcript of Intro to Rails 4

Page 1: Intro to Rails 4

Introduction to Rails 4by Kartik Sahoo

Page 2: Intro to Rails 4

Agenda1. Components of Rails (Overview)2. Environment Setup for Rails 4

a. What is RVM?b. What is Bundler?c. How to Setup

3. What’s added to Rails 44. What’s removed from Rails 45. Model Changes

a. Introduction of ARELb. Finders & Scopesc. Eager Loadingd. ‘concerns’ directory inside app/model/

6. Controller Changesa. Strong Parameters

7. View Changesa. Newly added form builder helper methodsb. HTML code is escaped by default

8. Routing Changesa. Modified use of ‘match’b. Introduction of PATCH verbc. Namespace, path, constraints, nested routes, shallow nestingd. Routing concerns

9. Migration Changesa. Reversible methodb. ‘change’ method

10.Turbolinks

Page 3: Intro to Rails 4

Components of Rails

● ActiveModel● ActiveRecord● ActiveResource● ActiveSupport● ActionPack● ActionController● ActionView● ActionMailer

Page 4: Intro to Rails 4

How to setup Environment●RVM●Bundler●Gemfile, Gemfile.lock●Setup

o rvm install 2.0.0omkdir rails_4ocd rails_4o rvm use 2.0.0@rails_4 --ruby-version --create

Page 5: Intro to Rails 4

What’s new in Rails 41.Model

a.AREL conceptb.‘concerns’ directory

2.Controllera.Strong Parameter

3.Routesa.PATCH HTTP verbb.Routing concerns

4.Viewsa.Few form builder helpersb.HTML escaped by default

5.Reversible method in Migration6.Turbolinks

Page 6: Intro to Rails 4

What’s removed from Rails 4●Observers●Protected model attributes●AR Session store●AR Resources●Finder with conditions (Deprecated)

What’s recommended● before_action to before_filter● update to update_attributes

Page 7: Intro to Rails 4
Page 8: Intro to Rails 4

Validation

RAILS-2class User validates_acceptance_of :terms_of_service validates_associated :books validates_format_of :email, :with => /\A[a-zA-Z]+\z/, :message => "Only letters allowed" validates_presence_of :login, :name, :address validates_exclusion_of :subdomain, :in => %w(www us ca jp)end

RAILS-4class User validates :terms_of_service, acceptance: true validates_associated :books validates :email, format: {with: /\A[a-zA-Z]+\z/, message: ‘Only

letters allowed’} validates :login, :name, :address, presence: true validates :subdomain, exclusion: {in: %w(www us ca jp)}end

Page 9: Intro to Rails 4

Introduction to AREL● An expressive and efficient way of method chaining to query data

through model.● Gives a feeling of object-oriented design.● Simplifies the generation of complex SQL queries.

class Post has_many :commentsend

class Comment belongs_to :postend

>Comment.all

returns an array of ActiveRecord objects in Rails 2

> Comment.all

returns an ActiveRecord::Relation object in Rails 4

> Comment.none

returns an empty ActiveRecord::Relation object.

Page 10: Intro to Rails 4

AREL continues..

Page 11: Intro to Rails 4

ActiveRecord Finders

RAILS-2Comment.find(:all, :conditions => {:commenter => nil})

There are many finder methods defined in ActiveRecord to retrieve objects from the Database, such as: where, group, having, offset, take, limit, joins, includes, order, readonly, select etc.

Each of these methods returns an instance of ActiveRecord::Relation class.

RAILS-4Comment.where(commenter: nil)

Comment.find(:first, :conditions => [‘commenter IS NOT NULL’], :order => ‘created_at DESC’)

Comment.where.not(commenter: nil).order(“created_at desc”).first

Comment.find_all(:conditions => [‘commented_at >= ?’, 2.days.ago], :limit => 5)

Comment.where(“commented_at >= ?”, 2.days.ago).limit(5)

Comment.find_by_commenter(“Tukuna”)

Comment.find_by_comenter(“Tukuna”)

Post.find(:all, :conditions => [“likes_count > ?”, min_likes], :include => :comments)

Post.where(“likes_count > ?”, min_likes).includes(:comments)

Comment.find(:first, :order => “commented_at DESC”)

Comment.order(:commented_at).last

Comment.find_by(commenter: “Tukuna”, body: nil)

Page 12: Intro to Rails 4

Finders Continues..● Model.take retrieves a record without any implicit ordering. Returns nil or array of AR objects.

Comment.take=> #<Comment id: 1, commenter: "Lifo">

Comment.take(2)=>[#<Comment id: 1, commenter: "Lifo">, #<Comment id: 3, commenter: "Donald">]

● Model.limit also retrieves records without any ordering. But it takes an arg and returns ActiveRecord::Relation object

Comment.limit(2)=> #<ActiveRecord::Relation [#<Comment id: 1, commenter: "Lifo">, #<Comment id: 2, commenter: "Donald">]>

● Model.first finds the first record ordered by the primary key. Also takes argument (e.g: Comment.first(10))

● Model.last finds the last record ordered by the primary key.

● Model.find_by finds the first record matching some conditions.

Comment.find_by(first_name: 'Lifo') => #<Comment id: 1, commenter: "Lifo">

Comment.find_by_first_name(‘Donald’) => #<Comment id: 2, commenter: "Donald"> Model.find_all_by_… method is deprecated

Page 13: Intro to Rails 4

Model.all vs Model.find_eachComment.all

● instructs Active Record to fetch the entire table in a single pass, build a model object per row, and then keep the entire array of model objects in memory.

● It may exceed the amount of memory available.

Comment.all.each do |c| c.post_to_facebook end

Model.find_each● Retrieves a batch of records and then yields each record to the block

individually as a model.● We can also specify batch size and starting point using :batch_size and :start

parameters

Comment.find_each(batch_size: 5000, start: 2000) do |c| c.post_to_facebook end

Page 14: Intro to Rails 4

Scopes

RAILS-2class Comment named_scope :recent, :conditions => [“created_at > ? AND created_at < ?”, 2.days.ago, Time.now] named_scope :published, :conditions => { :state => :published } named_scope :published_after, lambda { |time| { :conditions => [“published_at > ?”, time] } }end

RAILS-4class Comment scope :recent, -> { where(“created_at > ? AND created_at < ?”, 2.days.ago, Time.now) } scope :published, -> { where(state: :published) } scope :published_after, -> (time) { where(“published_at > ?”, time) }end

All scope methods will return an ActiveRecord::Relation object which will allow for further methods to be called on it.

But why? If server has started 5 days ago then this 2.days.ago would give value equal to 7.days.ago This has been rectified in Rails-4 using lambda syntax: scope :published, -> { where => {'created_at >= ?', 1.day.ago} }This runs at run-time not class loading time.

Page 15: Intro to Rails 4

Eager LoadingEager loading is the mechanism for loading the associated records of the objects returned by Model.find using as few queries as possible.

comments = Comment.limit(10)comments.each do |comment| puts comment.post.descriptionend

Q: How many queries does it perform?

Ans: 11 queries (1 for comments + 10 for fetching post from the comment) This is also known as N+1 queries problem.

Solution:

comments = Comment.includes(:post).limit(10) comments.each do |comment| puts comment.post.description end

This solution creates following 2 queries.

SELECT * FROM comments LIMIT 10; SELECT posts.* FROM comments WHERE post_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Page 16: Intro to Rails 4
Page 17: Intro to Rails 4

Controller Changes● Sessions are lazily loaded. If you don't access sessions in your action's code,

they will not be loaded. Hence you will never need to disable sessions, just not accessing them will do the job

● application.rb file is renamed to application_controller.rb● before_action should be used in place of before_filter

Flash Message Can assign a flash message to :notice, :alert or :flash as part of the redirection.

redirect_to post_url, notice: “Message is successfully created." redirect_to post_url, alert: "You're stuck here!" redirect_to post_url, flash: { referral_code: 1234 }

<p class=”notice”> <%= flash[:notice] %> </p> X

<p class=”notice”> <%= notice %> </p>

Page 18: Intro to Rails 4

Strong Parameters● With strong parameters, Action Controller parameters are forbidden to be used in Active

Model mass assignments until they have been whitelisted.● The basic idea is to move mass-assignment protection out of the model and into the

controller where it belongs.

class CommentsController < ApplicationController def create @comment = Comment.create(params[:comment]) end …………end

This will raise an ActiveModel::ForbiddenAttributes exception.

class CommentsController < ApplicationController def create @comment = Comment.create(comment_params) end ………… private def comment_params params.require(:comment).permit(:commenter, :body) endend

NOTE: comment_params is private. This new approach prevents an attacker from setting the model's attributes by manipulating the hash passed to the model.

Page 19: Intro to Rails 4

Nested Parameters (Skip)

params.permit(:name, { emails: [] }, friends: [:name, family: [:name], hobbies: [ ] ])

This declaration whitelists the name, emails and friends attributes. It is expected that● emails will be an array ● friends will be an array of resources with specific attributes

○ a name attribute ○ a family attribute which is restricted to having a name ○ a hobbies attribute as an array

Page 20: Intro to Rails 4
Page 21: Intro to Rails 4

View Changes● All strings are escaped by default. No need to use <%= h @post.description -%>

● <%= render partial: "comment", collection: @comments %> is same as <%= render @comments %>

● Rails determines the name of the partial to use by looking at the model name in the collection.

● In fact, we can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection.

● Spacer Template <%=render@products, spacer_template: "product_ruler"%> Rails will render the _product_ruler partial (with no data passed to it) between each pair of _product partials.

● Newly added Form Helpers (Details Later)○ date_select, select_day, select_hour○ collection_radio_buttons, collection_check_boxes○ country_select, time_zone_select○ video_tag, audio_tag○ search_field, telephone_field, date_field, color_field

Page 22: Intro to Rails 4

Partial Layout Partials now can have layouts of their own.

posts/_post.html.erb <%= div_for(post) do %> <p><%= post.body %></p> <% end %>

posts/show.html.erb <%= render partial: 'post', layout: 'box', locals: {post: @post} %>

posts/_box.html.erb <div class='box'> <%= yield %> </div>

OUTPUT:

<div class='box'> <div id='post_1'> <p>Partial Layouts are cool!</p> </div></div>

Page 23: Intro to Rails 4

How form_for(@object) works..● When dealing with RESTful resources, calls to form_for can get significantly easier

Creating a new comment

# long-style:form_for(@comment, url: comments_path)

# same thing, short-style (record identification gets used):form_for(@comment)

Editing an existing comment

# long-style:form_for(@comment, url: comment_path(@comment), html: { method: "patch" })

# short-style:form_for(@comment)

Page 24: Intro to Rails 4
Page 25: Intro to Rails 4

Routing ConcernsQ: match method is not safe, why?A: Because it matches all kinds of requests (PUT, GET, POST, PATCH & DELETE). We should use the verbs instead.

match '/items/:id/purchase', to: 'items#purchase'

 post '/items/:id/purchase', to: 'items#purchase' post '/items/:id/purchase', to: 'items#purchase', via: :post

resources :messages do resources :comments resources :categories resources :tagsend resources :posts do resources :comments resources :categories resources :tagsend resources :items do resources :comments resources :categories resources :tagsend

Routing concerns allows us to declare common routes that can be reused inside others resources and routes.

concern :sociable do resources :comments resources :categories resources :tagsend

resources :messages, concerns: :sociableresources :posts, concerns: :sociableresources :items, concerns: :sociable

Page 26: Intro to Rails 4

Namespaced Routes

Page 27: Intro to Rails 4

Nested Routes and Shallow Nesting

Page 28: Intro to Rails 4

Named Helper, Constraints and Redirection

Page 29: Intro to Rails 4
Page 30: Intro to Rails 4

Change Method

RAILS-2class CreateProducts < ActiveRecord::Migration def up create_table :products do |t| t.string :name t.text :description t.timestamps end end def down drop_table :products endend

RAILS-3/4class CreateProducts < ActiveRecord::Migration def change create_table :products do |t| t.string :name t.text :description t.timestamps end endend

up and down still works in Rails 4.

Page 31: Intro to Rails 4

Reversible Method

Page 32: Intro to Rails 4
Page 33: Intro to Rails 4

Why, How and Advantage