Rails 3 hints
Upcoming SlideShare
Loading in...5
×
 

Rails 3 hints

on

  • 1,265 views

Some hints extracted from my experience porting rails 2 applications to rails 3

Some hints extracted from my experience porting rails 2 applications to rails 3

Statistics

Views

Total Views
1,265
Views on SlideShare
1,265
Embed Views
0

Actions

Likes
0
Downloads
7
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Rails 3 hints Rails 3 hints Presentation Transcript

  • Rails 3Extra-hints
  • Summary● Rails 3 ○ Deprecations for Rails 4 ○ ActionMailer ○ Ajax in Rails 3 ○ General...● Formtastic (2.2) ○ Deprecations for V.3 ○ Custom Inputs● Acts as Paranoid● Will Paginate● Rspec● ViewModels● Inherited Resources● Delayed Job● Ruby 1.9● Assorted...
  • Rails 3 > DeprecationsPlugins will cease to existSolutions:● get the gem● insert plugin folder in /lib● insert somewhere else and bundle them in your gemfile: gem "view_models", "=2.0.1", :path => File.join(File. dirname(__FILE__), "/vendor/modified_gems/view_models- 2.0.1")
  • Rails 3 > DeprecationsActiveRecord ValidationsRails 2 validates_presence_of :attr validates_length_of :attr, :within => 2..60 validates_uniqueness_of :attr, :scope => [:assoc_id] …Rails 3 validates :attr, :presence => true, :length => {:within => 2..60}, :uniqueness => {:scope => :assoc_id}, ...
  • Rails 3 > DeprecationsAR queries● Rails 2ClassName.all(:conditions => ["blbla.id =?", 1])...● Rails 3 ○ Still supported, but it is just translating to ARel. Support in Rails 4 is still unknown.ClassName.where("blbla.id = ?", 1)
  • Rails 3 > Deprecationstable names● Rails 2:ClassName < ActiveRecord::Base set_table_name :bang ...end● Rails 3:ClassName < ActiveRecord::Base self.table_name = :bang ...end
  • Rails 3 > Deprecations● link_to :confirm option Rails2: link_to ... :confirm => “Sure?” Rails3: link_to ... :data => {:confirm => “Sure?”}● url helper accept :format option => :html, :js, :json, :xml, etc...● render accepts two extra options: :formats and :handlers template: app/views/homepage/index.html.haml name: :index / “index” / “homepage/index” … (extension out!) formats: :html handlers: :haml render :index, :formats => :html, :handlers => :haml if called in respond_to html block: render :index, :handlers => :haml if defined in environment that template engine is :haml: render :index
  • Rails 3 > Deprecationscomposed_of will be probably removed. Stillnot officially deprecated, but:http://blog.plataformatec.com.br/2012/06/about-the-composed_of-removal/
  • Rails 3 > ActionMailer● mail delivery: created before delivered:Mailer.deliver_registry #=> Mailer.registry.deliver● template extensions changed:template_name.text.plain.haml #=> template_name.text.hamltemplate_name.text.html.haml #=> template_name.html.haml
  • Rails 3 > Action Mailer- template variables are not passed explicitly tothe render@vars[:books] = ...body {:vars => @vars ...}#=>@books = ...
  • Rails 3 > General● avoid "include_something" scopes -> just use ARel method “includes” directlyClassName.include_books #=> ClassName.includes(:books)● RJS is gone ○ when writing ".js" templates, every ruby block inserted has to be explicitly escaped (escape_javascript)RAILS_ENV, RAILS_ROOT, RAILS_DEFAULT_LOGGER (Strings)Rails.env, Rails.root, Rails.logger (Pathnames)
  • Rails 3 > General● Rails.root can be joined directlyFile.join(Rails.root,‘bang’) #=> Rails.root.join(‘bang’)(note: Rails.root is from type Pathname. Quoting thedocumentation: "All functionality from File, FileTest, andsome from Dir and FileUtils is included, in an unsurprisingway. It is essentially a facade for all of these, and more".)
  • Rails 3 - General(Previous Rails 2 bug)Ajax (xhr) != "Script" (Content-Type)● JQuery’s $.get() does an asynchronous html request. Rails will build the response body in html format (assuming type is not given to $.get)● JQuery’s $.getScript() does an asynchronous script request. Rails will build the response in the js format● JQuery’s $.getJSON() does an asynchronous json request. Rails will build the response in the json format● ...● you get the idea● if you want to test if the request was asynchronous in the controller, use request.xhr?
  • Rails 3 > General● rendering flush logic changed: template calls with blocks that render something have to be marked with “=” ; others with “-” (Haml notation):in ERB: <%= form_for(...) do %> ... <% @elements.each do |element| %>
  • Rails 3 > General● URL helpers: clear distinction from url elements on explicit assignment ○ host : only host! ■ restorm.dev:3000 -> host is restorm.dev ○ subdomain : only subdomain! ■ choco.restorm.com -> subdomain is choco ■ us.members.restorm.com -> subdomain is us. members ○ port : only port! ■ restorm.dev:3000 -> port is 3000 ○ user ; password; ... you get the idea
  • Rails 3 > General● ActiveRecord errors handled differently: errors.on(:attr) #=> errors[:attr]● full asset paths: compute_asset_url(“/images/image.jpg”) #=> image_path(“/images/image.jpg”)● form calls where we want to define the variable name explicitly works differently in Rails 3: form_for :song, elem #=> form_for elem, :as => :song● Array “random” function was removed; use “sample” instead: [1, 2, 3].random #=> [1, 2, 3].sample
  • Rails 3 > GeneralArel and Scopes● everything is concatenated, not only the conditions (as in Rails 2)● avoid defining a condition like select(“table_name.*”); it does that already by default● (related to above) avoid defining “select” calls in scopes whenever possible; everytime you concatenate it with another “select” call, they will be joined “SELECT *, id FROM...“ #=> WRONG!● same thing for “order” calls, “group” calls, etc....
  • Rails 3 > GeneralArel and Scopes● Rails 3 ARel bug: if you have a “group” call in your ARel/scope definition and call “count” at the end, it will not return an Integer, but an OrderedHash (?), careful with thatRightclearing::Song.count #=> 15269Rightclearing::Song.group_by(:album_title).count #=>{""=>2410, " Little pieces for guitars and otherinstruments - Part I"=>15, " so black, so bright-instrumental"=>6, ... }
  • Rails 3 > GeneralModulesRails 2: module Bla def self.included(base) base.has_many …. base.send :include, InstanceMethods base.extend ClassMethods end module ClassMethods end module InstanceMethods def bang end end end
  • Rails 3 > GeneralModulesRails 3: module Bla extend ActiveSupport::Concern included do has_many # include InstanceMethods, but, it does this implicitly extend ClassMethods end module ClassMethods end def bang end end
  • Rails 3 > General● included from Concern module executes the code in the block in the scope of the element where the module is included (no more need for the “send :included” call that breaks visibility);● different order of inclusion (may be an issue in certain cases where we have hacked stuff for inherited resources and other gems...)● functions defined directly in the module will be instance methods implicitly in the class where the module is included (no more need for the explicit module InstanceMethods)
  • Formtastic > Deprecations● explicit value for input now inside input_html f.input :attr, :value => 3 f.input :attr, :input_html => { :value => 3 }● input for dates is now called :date_select● buttons defined differently: f.buttons do... #=> f.actions do ... f.commit_button #=> f.action :submit #=> <input type=submit...../> f.commit_button :button_html =>... #=> f.action : submit, :as => :button, :button_html => ...
  • Formtastic - Hints● nested “inputs” calls on the same builder do not work as before anymore: f.inputs do %li f.inputs do …. WRONG!● Notes: ● does not produce invalid HTML as before (good) ● produces nevertheless HTML, though unexpected (so so...) ● does not produce warning message (bad)
  • Formtastic - Hints● if an attribute is of type Integer, the resulting input will be of type number (HTML5)Main Issues with this: ○ Some JS code was dependent of the input type being "text"Ways to avoid it: ○ Provide a context to the element instead of depending of it directly; mark elements with a class.
  • Formtastic - Custom Inputs● Input Structure changed - Focus on modularity● All Standard Inputs include the Base Module● All Standard Inputs define the to_html which renders the input● Separate Modules defining input validations, labelling, content wrapping, errors, collection, etc...● Everything can be overwritten/redefined
  • Formtastic - Custom InputsCountry Select Box● Inherits From SelectInput, because it is a select box● Additionally caches the countries and calls them in the "collection" method, which is used by the parent to render the select box...Et Voilà!
  • Acts As Paranoid● Different Gem● Different Developers● Different code-basis!● More or less the same APInote: in order to use :with_deleted option for associationsin a class which is not paranoid itself, includeActsAsParanoid::Associations (seechange_tracking/change.rb model for an implementation)
  • Will Paginate● array pagination is not available implicitly; if you need it, you’ll have to require ‘will_paginate/array’ explicitly in the file using it● https://github. com/mislav/will_paginate/wiki/Backwards- incompatibility
  • RSpec● ‘double’ recommended instead of ‘mock’● Factory(:element) returns a stubbed model. They neither have an id anymore nor they can be saved anymore.● One cannot stub :id calls: ○ Factory(:model, :id => 23) is not valid!
  • ViewModels● module to include for view_model_for access changed:include ViewModels::Helpers::Railsinclude ViewModels::Helpers::Mapping● ViewModels gem is not being developed further... use a new gem in RC instead? (possible candidate: decorators)
  • Inherited Resources● loading helpers on server start; not reloading them on update; everytime you change something in the helpers, you’ll have to restart the server (Major downer...)● Deprecated; Gem creator recommends using the new Rails 3 controllers ; consider removal in RC?
  • Delayed Job● called differently: ○ send_later :bang #=> delay.bang
  • Ruby 1.9● the new file character encoding system. new to anyone? in new files that might not have been marked with the utf8 tag, please do. # -*- encoding : utf-8 -*-● to_a removed from the Object API something.to_a => Array(something)
  • Ruby 1.9● “require” calls must be made using the full path (or relative to the file where it is being called)● when you return something from a Proc, you are not returning it from the Proc, but instead from the scope where the Proc is being executed ○ no scope is returning now
  • Ruby 1.9● Array#to_s works differently: ○ Ruby 1.8 - [1, 2].to_s #=> “12” ○ Ruby 1.9 - [1.2].to_s #=> “[1, 2]” ○ use.join instead● procs now support splat arguments and default values for them: ○ proc {|id, args*, opts={}|...}
  • Assorted● forms that involve upload or possible upload (more explicitly contain files, non-ASCII data, and binary data) should be marked as multipart.● in cases where the method arguments are defined with a pointer (“def func(*args)”) and we want to extract the options hash from the last argument: opts = args.extract_options! opts = args.last.is_a?(Hash) ? args.pop : {}
  • Assorted● if there are functions that need to be shared between the controller and its respective template rendering scope (templates, helpers), use the helper_method method and define it only one time in the controller.● Avoid inclusion of helpers in controllers; either they are helpers and therefore should support the rendering, or they are controller mixins that are responsible for handling controller code (and may define helper functions using the helper_method method mentioned above)● use always t(“a.b.c.d”) instead of t(:d => :scope => [:a, :b, :c]) it is better to look for..and use always “” and not ‘’
  • Assorted● Avoid writing explicit scopes (unless you really really have too...)Class.where(“table_name.attribute = 1”) Class.where(:attribute => 1)● Why? ○ ARel sanitizes everything ○ ARel gets the table names and attribute names from the table structure by itself ○ (very important!) ARel quotes the table name, attribute name and value all by himself (something we seldom do).● Implicitly protects us from SQL injection, table name changing and usage of SQL reserved words.
  • More Hints?Check the documentation, and moreimportantly, pay attention to your developmentlog noise. Questions?