Rails 3 hints

  • 913 views
Uploaded on

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
913
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
7
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Rails 3Extra-hints
  • 2. 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...
  • 3. 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")
  • 4. 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}, ...
  • 5. 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)
  • 6. Rails 3 > Deprecationstable names● Rails 2:ClassName < ActiveRecord::Base set_table_name :bang ...end● Rails 3:ClassName < ActiveRecord::Base self.table_name = :bang ...end
  • 7. 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
  • 8. Rails 3 > Deprecationscomposed_of will be probably removed. Stillnot officially deprecated, but:http://blog.plataformatec.com.br/2012/06/about-the-composed_of-removal/
  • 9. 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
  • 10. Rails 3 > Action Mailer- template variables are not passed explicitly tothe render@vars[:books] = ...body {:vars => @vars ...}#=>@books = ...
  • 11. 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)
  • 12. 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".)
  • 13. 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?
  • 14. 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| %>
  • 15. 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
  • 16. 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
  • 17. 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....
  • 18. 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, ... }
  • 19. 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
  • 20. 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
  • 21. 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)
  • 22. 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 => ...
  • 23. 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)
  • 24. 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.
  • 25. 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
  • 26. 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à!
  • 27. 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)
  • 28. 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
  • 29. 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!
  • 30. 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)
  • 31. 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?
  • 32. Delayed Job● called differently: ○ send_later :bang #=> delay.bang
  • 33. 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)
  • 34. 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
  • 35. 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={}|...}
  • 36. 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 : {}
  • 37. 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 ‘’
  • 38. 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.
  • 39. More Hints?Check the documentation, and moreimportantly, pay attention to your developmentlog noise. Questions?