Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rails 4 Countdown

Rails 4 Countdown

Rails 4 talk from the February 12, 2013 edition of the Toronto Ruby Brigade. This was a joint talk given by myself and Rida Al Barazi.

Kevin Faustino

February 12, 2013
Tweet

More Decks by Kevin Faustino

Other Decks in Technology

Transcript

  1. hash syntax # Previous Versions Post.find(:all, conditions: { published_on: 2.weeks.ago

    }, limit: 5) # Rails 4 Post.where(:published_on: 2.weeks.ago).limit(5)
  2. Rails 3 Way class PeopleController < ApplicationController def create ...

    @person = Person.create(params[:person]) ... end end class Person < ActiveRecord::Base attr_accessible :name, :age end
  3. Rails 4 Way class PeopleController < ApplicationController def create ...

    @person = Person.create(person_params) ... end private def person_params params.require(:person).permit(:name, :age) end end
  4. require(:key) Fetches the key out of the hash and raises

    a ActionController::ParameterMissing error if it's missing.
  5. permit(keys) Selects only the passed keys out of the parameters

    hash, and sets the permitted attribute to true.
  6. Available Now! 1. Add the strong_parameters gem to your Gemfile.

    2. Set config.active_record.whitelist_attributes = false in your application.rb. 3. Add include ActiveModel::ForbiddenAttributesProtection to your models. 4. Update your controllers to filter the params to your needs, for example: params.require(:person).permit(:name, :age).
  7. PUT vs. PATCH "In a PUT request, the enclosed entity

    is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version." RFC 5789
  8. What’s Changing? - PATCH requests are routed to the update

    action. (backwards compatible) - Forms will set the hidden field _method to :patch on edits.
  9. How does it work? Turbolinks will perform an HTTP Request

    just as the browser would, but then replaces the <title> and<body> currently loaded in the DOM with the response from the server.
  10. Available Now! 1. Add the turbolinks gem to your Gemfile.

    2. Require turbolinks in your JavaScript manifest: // app/assets/javascripts/ application.js //= require jquery //= require jquery_ujs //= require turbolinks //= require_tree .
  11. etag method class NotesController < ApplicationController etag { current_user.try :id

    } def show @note = Note.find(params[:id]) fresh_when(@note) end end
  12. *_action class ArticlesController < ApplicationController before_action :set_article, except: [:index, :new,

    :create] ... private def set_article @article = Article.find(params[:id]) end end
  13. The Rails 3 Way # app/controllers/users_controller.rb class UsersController < ApplicationController

    def create ... flash[:error] = "An error message for the user" redirect_to home_path end end # app/views/home/index <%= flash[:error] %>
  14. Like :notice & :flash # app/controllers/users_controller.rb class UsersController < ApplicationController

    def create ... redirect_to home_path, error: "An error message for the user" end end # app/views/home/index <%= error %>
  15. ActionController::Live class MyController < ActionController::Base include ActionController::Live def stream response.headers['Content-Type']

    = 'text/event-stream' 100.times { response.stream.write "hello world\n" sleep 1 } response.stream.close end end
  16. Requires 1. Code must be Threadsafe 2. A concurrent Ruby

    Web Server, ie. Puma 3. Headers must be written before anything is written to the client. 4. Streams must be closed
  17. The Rails 3 Way Older::Application.routes.draw do resources :projects do resources

    :comments end resources :tasks do resources :comments end resources :articles do resources :comments end end
  18. The Rails 4 Way Newer::Application.routes.draw do concern :commentable do resources

    :comments end resources :projects, concerns: :commentable resources :tasks, concerns: :commentable resources :articles, concerns: :commentable end
  19. Example class Team < ActiveRecord::Base has_many :members end class Member

    < ActiveRecord::Base belongs_to :team, touch: true end
  20. View <!-- app/views/teams/show.html.erb --> <% cache @team do%> <h1>Team: <%=

    @team.name %></h1> <%= render @team.members %> <% end %> <!-- app/views/members/_member.html.erb --> <% cache member do %> <div class='member'> <%= member.name %> <p><%= member.bio %></p> </div> <% end %>
  21. key = Model Cache Key + digest of the template

    and its dependencies views/members/1-20121220141922/74865fcb3e2752a0928fa4f89b3e4426 views/members/2-20121220141922/74865fcb3e2752a0928fa4f89b3e4426 views/teams/2-20121220141922/4277f85c137009873c093088ef609e60
  22. datetime_field & datetime_local_field The datetime_field form helper creates an input

    of type “datetype”, and accepts time in UTC. The datetime_local_field form helper is the exact same, minus its time is specified in local time.
  23. time_field The time_field form helper creates an input of type

    “time”. <%= f.time_field :daily_reminder_time %>
  24. color_field The color_field form helper allows users to set a

    color via hex values: <%= f.color_field :background_color %>
  25. collection_check_boxes collection_check_boxes(:post, :category_ids, Category.all, :id, :name) # Returns: # <input

    id="post_category_ids_1" name="post[category_ids][]" # type="checkbox" value="1" checked="checked" /> # <label for="post_category_ids_1">Ruby</label> # <input id="post_category_ids_2" name="post[category_ids][]" # type="checkbox" value="2" /> # <label for="post_category_ids_2">Javascript</label> # ... # <input name="post[category_ids][]" type="hidden" value="" /> #
  26. collection_radio_buttons collection_radio_buttons(:post, :category_ids, Category.all, :id, :name) # Returns: # <input

    id="post_category_ids_1" name="post[category_ids][]" # type="radio" value="1" checked="checked" /> # <label for="post_category_ids_1">Ruby</label> # <input id="post_category_ids_2" name="post[category_ids][]" # type="radio" value="2" /> # <label for="post_category_ids_2">Javascript</label> # ...
  27. ActiveModel::Model Classes that include ActiveModel::Model also get: - Model name

    introspections - Conversions - Translations - Validations
  28. Model class Contact include ActiveModel::Model attr_accessor :name, :email, :message validates

    :name, presence: true validates :email, presence: true validates :message, presence: true, length: { maximum: 300 } end
  29. View <h1>Contact Us</h1> <%= form_for @contact do |f| %> <%=

    f.label :name %> <%= f.text_field :name %> <%= f.label :email %> <%= f.email_field :email %> <%= f.label :message %> <%= f.text_area :message %> <%= f.submit 'Submit' %> <% end %>
  30. Controller class ContactsController < ApplicationController def new @contact = Contact.new

    end def create @contact = Contact.new(params[:contact]) if @contact.valid? ContactMailer.new_contact(@contact).deliver redirect_to root_path else render :new end end end
  31. The Rails 4 Way Article.where.not(title: 'Rails 3') # >> SELECT

    "articles".* FROM "articles" WHERE ("articles"."title" != 'Rails 3') Article.where.not(title: ['Rails 3', 'Rails 5']) # >> SELECT "articles".* FROM "articles" WHERE ("articles"."title" NOT IN ('Rails 3', 'Rails 5'))
  32. #destroy! Active Record now has a #destroy! method to compliment

    #create! If a record cannot be destroyed, an ActiveRecord::RecordNotDestroyed exception will be raised.
  33. Deprecated Team.includes(:members).where('members.name = ?', 'Batman') # Rails 3 SQL (0.7ms)

    SELECT "teams"."id" AS t0_r0, "teams"."name" AS t0_r1, "teams"."created_at" AS t0_r2, "teams"."updated_at" AS t0_r3, "members"."id" AS t1_r0, "members"."name" AS t1_r1, "members"."bio" AS t1_r2, "members"."team_id" AS t1_r3, "members"."created_at" AS t1_r4, "members"."updated_at" AS t1_r5 FROM "teams" LEFT OUTER JOIN "members" ON "members"."team_id" = "teams"."id" WHERE (members.name = 'Batman')
  34. hstore class AddHstoreExtension < ActiveRecord::Migration def up execute 'CREATE EXTENSION

    hstore' end def down execute 'DROP EXTENSION hstore' end end
  35. hstore class Comic < ActiveRecord::Base store_accessor :properties, :story_arc end comic

    = Comic.create comic.properties # => nil comic.story_arc = 'Throne of Atlantis' comic.save # => UPDATE "comics" SET "properties" = '"story_arc"=>"Throne of Atlantis"', "updated_at" = '2012-12-29 19:31:45.234882' WHERE "comics"."id" = 1
  36. Query hstore Comic.where("properties -> 'story_arc' = 'Throne of Atlantis'") #

    SELECT "comics".* FROM "comics" WHERE (properties -> 'story_arc' = 'Throne of Atlantis')
  37. Array support article.tags = ['rails'] article.save # UPDATE "articles" SET

    "tags" = '{"rails"}', "updated_at" = '2012-12-29 20:12:49.825980' WHERE "articles"."id" = 1 article.reload article.tags # => ["rails"]
  38. Other supported types uuid - Universally unique identifier (UUID) column

    type inet - IPv4 Address cidr - IPv6 Address macaddr - MAC addresses json - Nuff said. Ranges - int4range, int8range, numrange, tsrange, tstzrange, daterange