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

Escrevendo Aplicações Melhores @ RubyConf Brasil

Escrevendo Aplicações Melhores @ RubyConf Brasil

Carlos Antonio

September 05, 2012
Tweet

More Decks by Carlos Antonio

Other Decks in Programming

Transcript

  1. Active Model
    l
    escrevendo
    aplicações melhores
    com

    View Slide

  2. http://pragprog.com/book/ppmetr/metaprogramming-ruby

    View Slide

  3. Rails
    2.3.2

    View Slide

  4. Active
    Record

    View Slide

  5. Validações

    View Slide

  6. obj = MyClass.new
    obj.attr = 'test'
    puts obj.valid?
    # => true
    obj.attr = 'tst'
    puts obj.valid?
    # => false

    View Slide

  7. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end

    View Slide

  8. “I had to go through some
    hoops to make this code
    work.”
    Paolo Perrotta
    Metaprogramming Ruby

    View Slide

  9. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end
    What?
    ActiveRecord::Base # autoload all modules

    View Slide

  10. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end
    def save; end
    def save!; end
    LOL

    View Slide

  11. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end
    def new_record?; true; end
    trolling

    View Slide

  12. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    there we go!

    View Slide

  13. “However, that wasn’t too
    much work in exchange for
    a flexible set of validation
    Class Macros.”
    Paolo Perrotta
    Metaprogramming Ruby

    View Slide

  14. work?
    not too much

    View Slide

  15. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end
    ActiveRecord::Base # autoload all modules
    def save; end
    def save!; end
    def new_record?; true; end

    View Slide

  16. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4

    View Slide

  17. work!
    too much

    View Slide

  18. nisso?
    como chegar

    View Slide

  19. Source diving!

    View Slide

  20. Active Model

    View Slide

  21. @cantoniodasilva
    Carlos Antonio

    View Slide

  22. View Slide

  23. Devise
    maintainer
    SimpleForm
    maintainer

    View Slide

  24. Rails
    commiter

    View Slide

  25. guru
    SC

    View Slide

  26. Active Model
    aplicações melhores
    escrevendo
    com

    View Slide

  27. Rails
    2.3

    View Slide

  28. Active Record
    VALIDAÇÕES
    SERIALIZAÇÃO JSON/XML
    ...

    View Slide

  29. Active Resource
    VALIDAÇÕES
    SERIALIZAÇÃO JSON/XML
    ...

    View Slide

  30. Mongoid
    VALIDAÇÕES ?
    SERIALIZAÇÃO ?
    ...

    View Slide

  31. MyClass
    VALIDAÇÕES ?
    SERIALIZAÇÃO ?
    ...

    View Slide

  32. require 'activerecord'
    ActiveRecord::Base # autoload all modules
    class MyClass
    def save; end
    def save!; end
    def new_record?; true; end
    include ActiveRecord::Validations
    attr_accessor :attr
    validates_length_of :attr, :minimum => 4
    end

    View Slide

  33. ! DRY

    View Slide

  34. Frágil

    View Slide

  35. Rails
    3

    View Slide

  36. Rails 3
    Rewrite Everything!

    View Slide

  37. Active Model

    View Slide

  38. Active Model
    VALIDAÇÕES
    SERIALIZAÇÃO JSON/XML
    ...

    View Slide

  39. Active Record
    include
    ActiveModel::*

    View Slide

  40. module ActiveRecord
    class Base
    extend ActiveModel::Naming
    # Uses ActiveModel::Translation
    extend Translation
    # Uses ActiveModel::MassAssignmentSecurity
    include AttributeAssignment
    include ActiveModel::Conversion
    # Uses ActiveModel::Validations
    include Validations
    # Uses ActiveModel::AttributeMethods
    include AttributeMethods
    # Uses ActiveModel::Callbacks
    include Callbacks
    include ActiveModel::Observing
    include ActiveModel::SecurePassword
    # Uses ActiveModel::Serialization
    include Serialization
    # ...
    end
    end

    View Slide

  41. Active Resource
    include
    ActiveModel::*

    View Slide

  42. module ActiveResource
    class Base
    extend ActiveModel::Naming
    # Uses ActiveModel::Observing
    include Observing
    # Uses ActiveModel::Validations
    include Validations
    include ActiveModel::Conversion
    include ActiveModel::Serializers::JSON
    include ActiveModel::Serializers::Xml
    # ...
    end
    end

    View Slide

  43. works
    how it

    View Slide

  44. Validations

    View Slide

  45. class Report < ActiveRecord::Base
    validates_presence_of :name
    end
    Active Record

    View Slide

  46. report = Report.new
    puts report.valid?
    #=> false
    puts report.errors.full_messages
    #=> Name can't be blank
    Active Record

    View Slide

  47. class Report
    include ActiveModel::Validations
    attr_accessor :name
    validates_presence_of :name
    end
    Active Model

    View Slide

  48. class Report
    include ActiveModel::Validations
    attr_accessor :name
    validates_presence_of :name
    end
    Active Model
    include ActiveModel::Validations
    validates_presence_of :name

    View Slide

  49. report = Report.new
    puts report.valid?
    #=> false
    puts report.errors.full_messages
    #=> Name can't be blank
    Active Model

    View Slide

  50. Validator

    View Slide

  51. class Report < ActiveRecord::Base
    validates_with ReportValidator
    end
    Active Record

    View Slide

  52. class ReportValidator < ActiveModel::Validator
    def validate(report)
    if report.name.blank?
    report.errors.add :name, :blank
    end
    # More validations...
    end
    end
    Active Record

    View Slide

  53. class ReportValidator < ActiveModel::Validator
    def validate(report)
    if report.name.blank?
    report.errors.add :name, :blank
    end
    # More validations...
    end
    end
    Active Record
    ReportValidator < ActiveModel::Validator
    def validate(report)

    View Slide

  54. report = Report.new
    puts report.valid?
    #=> false
    puts report.errors.full_messages
    #=> Name can't be blank
    Active Record

    View Slide

  55. class Report
    include ActiveModel::Validations
    validates_with ReportValidator
    attr_accessor :name
    end
    Active Model

    View Slide

  56. class Report
    include ActiveModel::Validations
    validates_with ReportValidator
    attr_accessor :name
    end
    Active Model
    include ActiveModel::Validations
    validates_with ReportValidator

    View Slide

  57. report = Report.new
    puts report.valid?
    #=> false
    puts report.errors.full_messages
    #=> Name can't be blank
    Active Model

    View Slide

  58. Validations:
    Nova Sintaxe

    View Slide

  59. class Report
    include ActiveModel::Validations
    attr_accessor :name
    # validates_presence_of :name
    validates :name, presence: true
    end
    Active Model

    View Slide

  60. class Report
    include ActiveModel::Validations
    attr_accessor :name
    # validates_presence_of :name
    validates :name, presence: true
    end
    Active Model
    include ActiveModel::Validations
    validates :name, presence: true

    View Slide

  61. Custom
    Validator

    View Slide

  62. class Report
    include ActiveModel::Validations
    attr_accessor :no_name
    validates :no_name, absence: true
    end
    Active Model

    View Slide

  63. class Report
    include ActiveModel::Validations
    attr_accessor :no_name
    validates :no_name, absence: true
    end
    include ActiveModel::Validations
    validates :no_name, absence: true
    Active Model

    View Slide

  64. class AbsenceValidator < ActiveModel::EachValidator
    def validate_each(record, attribute, value)
    if value.present?
    record.errors.add attribute, :absence
    end
    end
    end
    Active Model

    View Slide

  65. class AbsenceValidator < ActiveModel::EachValidator
    def validate_each(record, attribute, value)
    if value.present?
    record.errors.add attribute, :absence
    end
    end
    end
    AbsenceValidator
    Active Model

    View Slide

  66. class AbsenceValidator < ActiveModel::EachValidator
    def validate_each(record, attribute, value)
    if value.present?
    record.errors.add attribute, :absence
    end
    end
    end
    AbsenceValidator
    Active Model
    AbsenceValidator < ActiveModel::EachValidator
    def validate_each(record, attribute, value)

    View Slide

  67. Translation

    View Slide

  68. # I18n:
    activerecord:
    attributes:
    report:
    name: 'Nome'
    puts Report.human_attribute_name('name')
    #=> "Nome"
    Active Record

    View Slide

  69. # I18n:
    activemodel:
    attributes:
    report:
    name: 'Nome'
    Active Model

    View Slide

  70. # I18n:
    activemodel:
    attributes:
    report:
    name: 'Nome'
    activemodel:
    Active Model

    View Slide

  71. class Report
    extend ActiveModel::Translation
    end
    puts Report.human_attribute_name('name')
    #=> "Nome"
    Active Model

    View Slide

  72. Validations
    + Translation

    View Slide

  73. # I18n:
    activemodel:
    attributes:
    report:
    name: 'Nome'
    errors:
    messages:
    blank: 'deve ser preenchido'
    Active Model

    View Slide

  74. report = Report.new
    puts report.valid?
    #=> false
    puts report.errors.full_messages
    #=> Nome deve ser preenchido
    Active Model

    View Slide

  75. Callbacks

    View Slide

  76. class Report < ActiveRecord::Base
    before_save { puts "it works before" }
    after_save { puts "it works after as well" }
    end
    Active Record

    View Slide

  77. Report.new.save
    #=> it works before
    #=> ...saving...
    #=> it works after as well
    Active Record

    View Slide

  78. class Report
    extend ActiveModel::Callbacks
    define_model_callbacks :save
    before_save { puts "it works before" }
    after_save { puts "it works after as well" }
    def save
    run_callbacks :save do
    puts "saving..."
    end
    end
    end
    Active Model

    View Slide

  79. class Report
    extend ActiveModel::Callbacks
    define_model_callbacks :save
    before_save { puts "it works before" }
    after_save { puts "it works after as well" }
    def save
    run_callbacks :save do
    puts "saving..."
    end
    end
    end
    extend ActiveModel::Callbacks
    define_model_callbacks :save
    before_save { puts "it works before" }
    after_save { puts "it works after as well" }
    run_callbacks :save do
    puts "saving..."
    end
    Active Model

    View Slide

  80. Report.new.save
    #=> it works before
    #=> ...saving...
    #=> it works after as well
    Active Model

    View Slide

  81. Serialization

    View Slide

  82. report = Report.new
    report.name = "Omglol"
    puts report.to_json
    #=> {"report":{"name":"Omglol"}}
    Active Record

    View Slide

  83. class Report
    extend ActiveModel::Naming
    include ActiveModel::Serializers::JSON
    attr_accessor :name
    def attributes
    { name: name }
    end
    end
    Active Model

    View Slide

  84. class Report
    extend ActiveModel::Naming
    include ActiveModel::Serializers::JSON
    attr_accessor :name
    def attributes
    { name: name }
    end
    end
    Active Model
    include ActiveModel::Serializers::JSON
    def attributes
    { name: name }
    end

    View Slide

  85. report = Report.new
    report.name = "Omglol"
    puts report.to_json
    #=> {"report":{"name":"Omglol"}}
    Active Model

    View Slide

  86. report = Report.new
    report.name = "Omglol"
    puts report.to_xml
    #=>
    #=>
    #=> Omglol
    #=>
    Active Record

    View Slide

  87. class Report
    extend ActiveModel::Naming
    include ActiveModel::Serializers::Xml
    attr_accessor :name
    def attributes
    { name: name }
    end
    end
    Active Model

    View Slide

  88. class Report
    extend ActiveModel::Naming
    include ActiveModel::Serializers::Xml
    attr_accessor :name
    def attributes
    { name: name }
    end
    end
    include ActiveModel::Serializers::Xml
    def attributes
    { name: name }
    end
    Active Model

    View Slide

  89. report = Report.new
    report.name = "Omglol"
    puts report.to_xml
    #=>
    #=>
    #=> Omglol
    #=>
    Active Model

    View Slide

  90. Attribute
    Methods

    View Slide

  91. report = Report.new
    puts report.name? #=> false
    report.name = "Omglol"
    puts report.name? #=> true
    Active Record

    View Slide

  92. report = Report.new
    puts report.name? #=> false
    report.name = "Omglol"
    puts report.name? #=> true
    report.name? #=> false
    report.name = "Omglol"
    report.name? #=> true
    Active Record

    View Slide

  93. class Report
    include ActiveModel::AttributeMethods
    attribute_method_suffix '?'
    define_attribute_methods [:name]
    attr_accessor :name
    private
    def attribute?(attr)
    send(attr).present?
    end
    end
    Active Model

    View Slide

  94. class Report
    include ActiveModel::AttributeMethods
    attribute_method_suffix '?'
    define_attribute_methods [:name]
    attr_accessor :name
    private
    def attribute?(attr)
    send(attr).present?
    end
    end
    include ActiveModel::AttributeMethods
    attribute_method_suffix '?'
    define_attribute_methods [:name]
    def attribute?(attr)
    send(attr).present?
    end
    Active Model

    View Slide

  95. report = Report.new
    puts report.name? #=> false
    report.name = "Omglol"
    puts report.name? #=> true
    Active Model

    View Slide

  96. report = Report.new
    puts report.name? #=> false
    report.name = "Omglol"
    puts report.name? #=> true
    report.name? #=> false
    report.name = "Omglol"
    report.name? #=> true
    Active Model

    View Slide

  97. class Report
    include ActiveModel::AttributeMethods
    attribute_method_prefix 'clear_'
    define_attribute_methods [:name]
    attr_accessor :name
    private
    def clear_attribute(attr)
    send "#{attr}=", nil
    end
    end
    Active Model

    View Slide

  98. class Report
    include ActiveModel::AttributeMethods
    attribute_method_prefix 'clear_'
    define_attribute_methods [:name]
    attr_accessor :name
    private
    def clear_attribute(attr)
    send "#{attr}=", nil
    end
    end
    Active Model
    include ActiveModel::AttributeMethods
    attribute_method_prefix 'clear_'
    define_attribute_methods [:name]
    def clear_attribute(attr)
    send "#{attr}=", nil
    end

    View Slide

  99. report.name = "Omglol"
    puts report.name? #=> true
    report.clear_name
    puts report.name? #=> false
    Active Model

    View Slide

  100. report.name = "Omglol"
    puts report.name? #=> true
    report.clear_name
    puts report.name? #=> false
    report.name? #=> true
    report.clear_name
    report.name? #=> false
    Active Model

    View Slide

  101. DRY !

    View Slide

  102. Active Model
    <3 <3 <3

    View Slide

  103. isso...
    Enquanto

    View Slide

  104. 2.3.OMG
    Rails:

    View Slide

  105. Invitation
    Feature:

    View Slide

  106. class Invitation
    attr_accessor :contacts, :message
    end

    View Slide

  107. <% form_for @invitation do |f| %>
    ...
    <% end %>

    View Slide

  108. View Slide

  109. WTF!?!

    View Slide

  110. action="/invitations/%23%3CInvitation:
    0x1060c2b08%3E"
    class="edit_invitation"
    id="edit_invitation_2198214020"
    method="post">
    ...

    View Slide

  111. action="/invitations/%23%3CInvitation:
    0x1060c2b08%3E"
    class="edit_invitation"
    id="edit_invitation_2198214020"
    method="post">
    ...

    action="/invitations/%23%3CInvitation:
    0x1060c2b08%3E"
    What?

    View Slide

  112. action="/invitations/%23%3CInvitation:
    0x1060c2b08%3E"
    class="edit_invitation"
    id="edit_invitation_2198214020"
    method="post">
    ...

    class="edit_invitation"
    edit? LOL

    View Slide

  113. action="/invitations/%23%3CInvitation:
    0x1060c2b08%3E"
    class="edit_invitation"
    id="edit_invitation_2198214020"
    method="post">
    ...

    id="edit_invitation_2198214020"
    troll number

    View Slide

  114. class Invitation
    attr_accessor :contacts, :message
    def new_record?
    true
    end
    def id
    nil
    end
    end

    View Slide

  115. class Invitation
    attr_accessor :contacts, :message
    def new_record?
    true
    end
    def id
    nil
    end
    end
    def new_record?
    true
    end
    def id
    nil
    end

    View Slide

  116. action="/invitations"
    class="new_invitation"
    id="new_invitation"
    method="post">
    ...

    there we go!

    View Slide

  117. nisso?
    como chegar

    View Slide

  118. Source diving!

    View Slide

  119. Rails
    2.3

    View Slide

  120. Action Pack
    Active Record

    View Slide

  121. Active Record?
    Blargh!?!!

    View Slide

  122. NoSQL FTW!!

    View Slide

  123. Action Pack
    Mongoid

    View Slide

  124. monkey
    Patch

    View Slide

  125. Outro objeto
    em um form?

    View Slide

  126. monkey
    Patch

    View Slide

  127. class Invitation
    attr_accessor :contacts, :message
    def new_record?
    true
    end
    def id
    nil
    end
    end
    def new_record?
    true
    end
    def id
    nil
    end

    View Slide

  128. ! API

    View Slide

  129. Frágil

    View Slide

  130. Rails
    3

    View Slide

  131. Rails 3
    Rewrite Everything!

    View Slide

  132. Active Model

    View Slide

  133. Action Pack
    Active Model

    View Slide

  134. Active Model
    Active Record
    Action Pack

    View Slide

  135. Active Model
    Mongoid
    Action Pack

    View Slide

  136. Outro objeto
    em um form?

    View Slide

  137. Active Model
    OmgLol
    Action Pack

    View Slide

  138. works
    how it

    View Slide

  139. form_for @report do |f|
    f.label :name
    f.text_field :name
    f.submit
    end

    View Slide

  140. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    View Slide

  141. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    id="new_report" method="post">
    como?

    View Slide

  142. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    id="new_report" method="post">
    como?

    View Slide

  143. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    id="new_report" method="post">
    como?

    View Slide

  144. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    Nome
    como?

    View Slide

  145. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    Nome
    como?

    View Slide

  146. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    Nome
    como?

    View Slide

  147. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    name="report[name]" type="text" />
    como?

    View Slide

  148. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    name="report[name]" type="text" />
    como?

    View Slide

  149. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    name="report[name]" type="text" />
    como?

    View Slide

  150. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    value="Criar Relatório" />
    como?

    View Slide

  151. id="new_report" method="post">
    Nome
    name="report[name]" type="text" />
    value="Criar Relatório" />

    value="Criar Relatório" />
    como?

    View Slide

  152. API
    Active Model

    View Slide

  153. ActiveModel
    ::Lint::Tests

    View Slide

  154. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end

    View Slide

  155. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages

    View Slide

  156. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages
    Naming

    View Slide

  157. class Report
    extend ActiveModel::Naming
    end

    View Slide

  158. puts Report.model_name
    #=> "Report"
    puts Report.model_name.singular
    #=> report
    puts Report.model_name.plural
    #=> reports
    puts Report.model_name.param_key
    #=> report

    View Slide

  159. puts Report.model_name
    #=> "Report"
    puts Report.model_name.singular
    #=> report
    puts Report.model_name.plural
    #=> reports
    puts Report.model_name.param_key
    #=> report
    model_name
    "Report"
    model_name.singular
    report
    model_name.plural
    reports
    model_name.param_key
    report

    View Slide

  160. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages
    Conversion

    View Slide

  161. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages
    Implementar

    View Slide

  162. class Report
    include ActiveModel::Conversion
    attr_accessor :id
    def persisted?
    id.present?
    end
    end

    View Slide

  163. report = Report.new
    report.id = 1
    puts report.persisted?
    #=> true
    puts report.to_key
    #=> [1]
    puts report.to_param
    #=> '1'

    View Slide

  164. report = Report.new
    report.id = 1
    puts report.persisted?
    #=> true
    puts report.to_key
    #=> [1]
    puts report.to_param
    #=> '1'
    report.persisted?
    #=> true
    report.to_key
    #=> [1]
    report.to_param
    #=> '1'

    View Slide

  165. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages
    Validations

    View Slide

  166. require 'minitest/autorun'
    class OmglolTest < MiniTest::Unit::TestCase
    include ActiveModel::Lint::Tests
    def setup
    @model = Omglol.new
    end
    end

    View Slide

  167. require 'minitest/autorun'
    class OmglolTest < MiniTest::Unit::TestCase
    include ActiveModel::Lint::Tests
    def setup
    @model = Omglol.new
    end
    end
    include ActiveModel::Lint::Tests
    def setup
    @model = Omglol.new
    end

    View Slide

  168. require 'active_model'
    class Omglol
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    include ActiveModel::Validations
    def persisted?; false; end
    end

    View Slide

  169. require 'active_model'
    class Omglol
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    include ActiveModel::Validations
    def persisted?; false; end
    end
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    include ActiveModel::Validations
    def persisted?; false; end

    View Slide

  170. $ ruby activemodel_test.rb
    Run options: --seed 9998
    # Running tests:
    ........
    Finished tests in 0.029155s, 274.3955
    tests/s, 1303.3785 assertions/s.
    8 tests, 38 assertions, 0 failures, 0
    errors, 0 skips

    View Slide

  171. $ ruby activemodel_test.rb
    Run options: --seed 9998
    # Running tests:
    ........
    Finished tests in 0.029155s, 274.3955
    tests/s, 1303.3785 assertions/s.
    8 tests, 38 assertions, 0 failures, 0
    errors, 0 skips

    View Slide

  172. Action Pack?

    View Slide

  173. form_for @report

    View Slide

  174. form_for @report do |f|
    f.label :name
    f.text_field :name
    f.submit
    end

    View Slide

  175. class="new_report" id="new_report"
    method="post">
    class="edit_report" id="edit_report_1"
    method="post">
    new
    edit

    View Slide

  176. url_for @report

    View Slide

  177. url_for @report
    @report.persisted?

    View Slide

  178. url_for @report
    @report.persisted?
    @report.to_param

    View Slide

  179. url_for @report
    /reports
    /reports/1

    View Slide

  180. dom_class @report

    View Slide

  181. dom_class @report
    @report.class.
    model_name.param_key

    View Slide

  182. dom_class @report
    @report.class.
    model_name.param_key
    “report”

    View Slide

  183. dom_class @report, :new

    View Slide

  184. dom_class @report, :new
    “new_report”

    View Slide

  185. dom_id @report

    View Slide

  186. dom_id @report
    dom_class @report

    View Slide

  187. dom_id @report
    dom_class @report
    new_report / edit_report

    View Slide

  188. dom_id @report

    View Slide

  189. dom_id @report
    @report.to_key

    View Slide

  190. dom_id @report
    @report.to_key
    edit_report_1

    View Slide

  191. f.label :name

    View Slide

  192. f.label :name
    model_name.param_key

    View Slide

  193. f.label :name
    model_name.param_key
    “report_name”

    View Slide

  194. f.label :name

    View Slide

  195. f.label :name
    @report.class.
    human_attribute_name

    View Slide

  196. f.label :name
    @report.class.
    human_attribute_name
    “Nome”

    View Slide

  197. f.label :name
    Nome

    View Slide

  198. f.text_field :name

    View Slide

  199. f.text_field :name
    model_name.param_key

    View Slide

  200. f.text_field :name
    model_name.param_key
    “report_name”

    View Slide

  201. f.text_field :name
    model_name.param_key
    “report_name”
    “report[name]”

    View Slide

  202. f.text_field :name
    name="report[name]" type="text" />

    View Slide

  203. f.submit

    View Slide

  204. f.submit
    @report.persisted?

    View Slide

  205. f.submit
    @report.persisted?
    “Criar” ou “Atualizar”

    View Slide

  206. f.submit

    View Slide

  207. f.submit
    model_name.human

    View Slide

  208. f.submit
    model_name.human
    “Relatório”

    View Slide

  209. f.submit
    value="Criar Relatório" />

    View Slide

  210. form_for @report

    View Slide

  211. form_for @report
    url_for
    dom_id
    dom_class

    View Slide

  212. form_for @report

    View Slide

  213. form_for @report
    model_name
    persisted?
    to_key

    View Slide

  214. link_to “...”, @report

    View Slide

  215. link_to “...”, @report
    url_for @report

    View Slide

  216. div_for @report

    View Slide

  217. div_for @report
    dom_id @report

    View Slide

  218. div_for @report
    dom_id @report
    dom_class @report

    View Slide

  219. render @report
    render @reports

    View Slide

  220. render @report

    View Slide

  221. render @report
    app/views/
    reports/_report.html.erb

    View Slide

  222. render @report

    View Slide

  223. render @report
    @report.to_partial_path

    View Slide

  224. render @report
    @report.to_partial_path
    reports/_report

    View Slide

  225. respond_to :html, :json
    respond_with @report

    View Slide

  226. respond_to :html, :json

    View Slide

  227. respond_to :html, :json
    html?
    json?

    View Slide

  228. respond_with @report

    View Slide

  229. respond_with @report
    success?
    failure?

    View Slide

  230. respond_with @report

    View Slide

  231. respond_with @report
    @report.errors.empty?

    View Slide

  232. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages

    View Slide

  233. Validations?

    View Slide

  234. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages
    Validations?

    View Slide

  235. Rails 4
    SPOILER

    View Slide

  236. module ActiveModel::Lint::Tests
    def test_to_key; end
    def test_to_param; end
    def test_to_partial_path; end
    def test_valid?; end
    def test_persisted?; end
    def test_model_naming; end
    def test_errors_aref; end
    def test_errors_full_messages; end
    end
    RAILS
    4
    to_key
    to_param
    to_partial_path
    valid?
    persisted?
    model_naming
    errors_aref
    errors_full_messages

    View Slide

  237. require 'minitest/autorun'
    class OmglolTest < MiniTest::Unit::TestCase
    include ActiveModel::Lint::Tests
    def setup
    @model = Omglol.new
    end
    end
    RAILS
    4

    View Slide

  238. require 'minitest/autorun'
    class OmglolTest < MiniTest::Unit::TestCase
    include ActiveModel::Lint::Tests
    def setup
    @model = Omglol.new
    end
    end
    RAILS
    4
    include ActiveModel::Lint::Tests
    def setup
    @model = Omglol.new
    end

    View Slide

  239. require 'active_model'
    class Omglol
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?; false; end
    def errors; Hash.new([]); end
    end
    RAILS
    4

    View Slide

  240. require 'active_model'
    class Omglol
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?; false; end
    def errors; Hash.new([]); end
    end
    RAILS
    4
    def errors; Hash.new([]); end

    View Slide

  241. require 'active_model'
    class Omglol
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?; false; end
    def errors; Hash.new([]); end
    end
    RAILS
    4
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?; false; end
    def errors; Hash.new([]); end
    def errors; Hash.new([]); end

    View Slide

  242. $ ruby activemodel_master_test.rb
    Run options: --seed 10850
    # Running tests:
    ......
    Finished tests in 0.002590s, 2316.6023
    tests/s, 11583.0116 assertions/s.
    6 tests, 30 assertions, 0 failures, 0
    errors, 0 skip

    View Slide

  243. $ ruby activemodel_master_test.rb
    Run options: --seed 10850
    # Running tests:
    ......
    Finished tests in 0.002590s, 2316.6023
    tests/s, 11583.0116 assertions/s.
    6 tests, 30 assertions, 0 failures, 0
    errors, 0 skip

    View Slide

  244. API !

    View Slide

  245. Active Model
    <3 <3 <3

    View Slide

  246. Review

    View Slide

  247. DRY
    Active Model

    View Slide

  248. API
    Active Model

    View Slide

  249. Bônus Track!

    View Slide

  250. Rails
    4
    SPOILER

    View Slide

  251. require 'active_model'
    class Omglol
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?; false; end
    def errors; Hash.new([]); end
    end
    RAILS
    4

    View Slide

  252. require 'active_model'
    class Omglol
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?; false; end
    def errors; Hash.new([]); end
    end
    RAILS
    4
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?; false; end
    def errors; Hash.new([]); end

    View Slide

  253. ActiveModel
    ::Model

    View Slide

  254. module Model
    def self.included(base) #:nodoc:
    base.class_eval do
    extend ActiveModel::Naming
    extend ActiveModel::Translation
    include ActiveModel::Validations
    include ActiveModel::Conversion
    end
    end
    def initialize(params={})
    params.each do |attr, value|
    self.public_send("#{attr}=", value)
    end if params
    end
    def persisted?
    false
    end
    end
    RAILS
    4

    View Slide

  255. module Model
    def self.included(base) #:nodoc:
    base.class_eval do
    extend ActiveModel::Naming
    extend ActiveModel::Translation
    include ActiveModel::Validations
    include ActiveModel::Conversion
    end
    end
    def initialize(params={})
    params.each do |attr, value|
    self.public_send("#{attr}=", value)
    end if params
    end
    def persisted?
    false
    end
    end
    RAILS
    4
    extend ActiveModel::Naming
    extend ActiveModel::Translation
    include ActiveModel::Validations
    include ActiveModel::Conversion
    def persisted?
    false
    end

    View Slide

  256. require 'active_model'
    class Omglol
    include ActiveModel::Model
    end
    RAILS
    4

    View Slide

  257. require 'active_model'
    class Omglol
    include ActiveModel::Model
    end
    RAILS
    4
    include ActiveModel::Model

    View Slide

  258. form_for @omglol

    View Slide

  259. render @omglol

    View Slide

  260. respond_with @omglol

    View Slide

  261. Active Model
    <3 <3 <3

    View Slide

  262. View Slide

  263. Active Model
    Attribute Methods
    Callbacks
    Dirty
    Mass Assignment
    Secure Password
    Observing
    Serialization
    Validations Validator
    Model
    Conversion
    Naming
    Translation
    Lint

    View Slide

  264. plataformatec/
    mail_form

    View Slide

  265. http://pragprog.com/book/jvrails/crafting-rails-applications

    View Slide

  266. WITH GREAT
    MOUSTACHE
    COMES GREAT
    RESPONSIBILITY

    View Slide

  267. Estamos contratando!
    plataformatec.com.br

    View Slide

  268. View Slide

  269. APLICAÇÕES MELHORES
    ACTIVE MODEL
    @cantoniodasilva
    Obrigado!

    View Slide