$30 off During Our Annual Pro Sale. View Details »

Conhecendo Variants do Rails 4.1

Conhecendo Variants do Rails 4.1

O Rails está em uma fase evolutiva bastante interessante. Com releases menores e mais rápidos, está adicionando novas funcionalidades aos poucos. O Rails 4.1 trouxe uma funcionalidade chamada de variants, que permite definir views alternativas para uma mesma action e formato.

Nessa palestra vou mostrar como você pode renderizar views alternativas para dispositivos móveis, além de abstrair lógica das views sem muito esforço.

Nando Vieira

June 21, 2014
Tweet

More Decks by Nando Vieira

Other Decks in Programming

Transcript

  1. Rails Variants

  2. O Rails tem content negotiation faz tempo.

  3. class TasksController < ApplicationController def index @tasks = Task.all !

    respond_to do |format| format.html format.xml { render xml: @tasks } format.json { render json: @tasks } end end end
  4. Para renderizar cada formato, basta especificar o parâmetro :format.

  5. $ rake routes Prefix Verb URI Pattern Controller#Action root GET

    / site#index tasks GET /tasks(.:format) tasks#index POST /tasks(.:format) tasks#create new_task GET /tasks/new(.:format) tasks#new edit_task GET /tasks/:id/edit(.:format) tasks#edit task GET /tasks/:id(.:format) tasks#show PATCH /tasks/:id(.:format) tasks#update PUT /tasks/:id(.:format) tasks#update DELETE /tasks/:id(.:format) tasks#destroy
  6. O formato pode ser especificado para cada uma das rotas

    que você definiu.
  7. /tasks.json /tasks?format=json

  8. À partir do Rails 3 você pode otimizar o processo

    de content negotiation.
  9. class TasksController < ApplicationController respond_to :html, :json, :xml ! def

    index @tasks = Task.all respond_with(@tasks) end end
  10. Você pode acessar e definir explicitamente o formato de uma

    requisição.
  11. request.format request.format = :json

  12. Você pode criar responders personalizados que alteram o comportamento padrão

    do Rails.
  13. None
  14. None
  15. class TaskCreateResponder < ActionController::Responder delegate :t, :flash, to: :controller def

    to_html if resource.new_record? flash.notice = t('flash.tasks.create.notice') else flash.alert = resource.errors.full_messages .to_sentence end ! redirect_to navigation_location end end
  16. Para usar um responder, especifique a opção :responder.

  17. class TasksController < ApplicationController respond_to :html, :json ! def create

    @task = Task.create(task_params) respond_with @task, location: tasks_path, responder: TaskCreateResponder end end
  18. Variants

  19. O Rails Variants permite criar uma especialização para o formato

    que está sendo renderizado.
  20. A primeira ideia que vem à cabeça é renderizar um

    template específico para dispositivos móveis.
  21. class ApplicationController < ActionController::Base before_action :set_variant ! private ! def

    set_variant request.variant = :tablet if browser.tablet? request.variant = :mobile if browser.mobile? end end
  22. http://fnando.me/14l

  23. Caso uma dessas condições seja satisfeita, o template para aquela

    variante será usado.
  24. application.html.erb application.html+tablet.erb application.html+mobile.erb ! index.html.erb index.html+tablet.erb index.html+mobile.erb

  25. Você pode combinar respond_to com variantes.

  26. respond_to do |format| format.html do |variant| variant.none(&block) variant.tablet(&block) variant.mobile(&block) end

    ! format.json end
  27. Todos os exemplos de variantes são sempre baseados em detecção

    de dispositivos.
  28. Mas variantes podem ser usadas para abstrair a lógica de

    renderização.
  29. None
  30. User#security_mode none, card, sms, totp

  31. class SecurityModeController < ApplicationController def edit request.variant = SecurityMode.fetch(params[:security_mode]) !

    respond_to do |format| format.html do |variant| variant.none variant.card { initialize_card_security_mode } variant.sms { initialize_sms_security_mod } variant.totp { initialize_totp_security_mode } end end end end
  32. edit.html+card.erb edit.html+none.erb edit.html+sms.erb edit.html+totp.erb

  33. A inicialização dos objetos necessários para renderizar a view pode

    ser feita dinamicamente.
  34. class SecurityModeController < ApplicationController def edit security_mode = SecurityMode.fetch(params[:security_mode]) request.variant

    = security_mode ! initializer = "initialize_#{security_mode}_security_mode" send(initialize) if respond_to?(initializer, true) end end
  35. Instancie apenas um objeto no controller. Sandi Metz, http://fnando.me/14v

  36. class Dashboard def initialize(user) @user = user end ! def

    new_status @new_status ||= Status.new end ! def statuses Status.for(user) end ! def notifications @notifications ||= user.notifications end ! private ! attr_reader :user end
  37. class DashboardsController < ApplicationController before_filter :authorize ! def show @dashboard

    = Dashboard.new(current_user) end end
  38. <%= render 'profile' %> <%= render 'groups', groups: @dashboard.group %>

    ! <%= render 'statuses/form', status: @dashboard.new_status %> <%= render 'statuses', statuses: @dashboard.statuses %>
  39. Outros casos de uso Testes A/B Rollout para beta testers

    Logado vs não logado
  40. Evite adicionar tudo como variantes.

  41. request.variant = [:logged, :iphone].join('_').to_sym application.html+logged_iphone.erb

  42. A quantidade de combinações possíveis pode fugir do seu controle.

  43. Tenha bom senso.

  44. Obrigado.

  45. * * *

  46. http://howtocode.com.br