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
Slide 8
Slide 8 text
“I had to go through some
hoops to make this code
work.”
Paolo Perrotta
Metaprogramming Ruby
Slide 9
Slide 9 text
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
Slide 10
Slide 10 text
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
Slide 11
Slide 11 text
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
Slide 12
Slide 12 text
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!
Slide 13
Slide 13 text
“However, that wasn’t too
much work in exchange for
a flexible set of validation
Class Macros.”
Paolo Perrotta
Metaprogramming Ruby
Slide 14
Slide 14 text
work?
not too much
Slide 15
Slide 15 text
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
Slide 16
Slide 16 text
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
Slide 17
Slide 17 text
work!
too much
Slide 18
Slide 18 text
nisso?
como chegar
Slide 19
Slide 19 text
Source diving!
Slide 20
Slide 20 text
Active Model
Slide 21
Slide 21 text
@cantoniodasilva
Carlos Antonio
Slide 22
Slide 22 text
No content
Slide 23
Slide 23 text
Devise
maintainer
SimpleForm
maintainer
Slide 24
Slide 24 text
Rails
commiter
Slide 25
Slide 25 text
guru
SC
Slide 26
Slide 26 text
Active Model
aplicações melhores
escrevendo
com
Slide 27
Slide 27 text
Rails
2.3
Slide 28
Slide 28 text
Active Record
VALIDAÇÕES
SERIALIZAÇÃO JSON/XML
...
Slide 29
Slide 29 text
Active Resource
VALIDAÇÕES
SERIALIZAÇÃO JSON/XML
...
Slide 30
Slide 30 text
Mongoid
VALIDAÇÕES ?
SERIALIZAÇÃO ?
...
Slide 31
Slide 31 text
MyClass
VALIDAÇÕES ?
SERIALIZAÇÃO ?
...
Slide 32
Slide 32 text
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
Slide 33
Slide 33 text
! DRY
Slide 34
Slide 34 text
Frágil
Slide 35
Slide 35 text
Rails
3
Slide 36
Slide 36 text
Rails 3
Rewrite Everything!
Slide 37
Slide 37 text
Active Model
Slide 38
Slide 38 text
Active Model
VALIDAÇÕES
SERIALIZAÇÃO JSON/XML
...
Slide 39
Slide 39 text
Active Record
include
ActiveModel::*
Slide 40
Slide 40 text
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
Slide 41
Slide 41 text
Active Resource
include
ActiveModel::*
Slide 42
Slide 42 text
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
Slide 43
Slide 43 text
works
how it
Slide 44
Slide 44 text
Validations
Slide 45
Slide 45 text
class Report < ActiveRecord::Base
validates_presence_of :name
end
Active Record
Slide 46
Slide 46 text
report = Report.new
puts report.valid?
#=> false
puts report.errors.full_messages
#=> Name can't be blank
Active Record
Slide 47
Slide 47 text
class Report
include ActiveModel::Validations
attr_accessor :name
validates_presence_of :name
end
Active Model
Slide 48
Slide 48 text
class Report
include ActiveModel::Validations
attr_accessor :name
validates_presence_of :name
end
Active Model
include ActiveModel::Validations
validates_presence_of :name
Slide 49
Slide 49 text
report = Report.new
puts report.valid?
#=> false
puts report.errors.full_messages
#=> Name can't be blank
Active Model
Slide 50
Slide 50 text
Validator
Slide 51
Slide 51 text
class Report < ActiveRecord::Base
validates_with ReportValidator
end
Active Record
Slide 52
Slide 52 text
class ReportValidator < ActiveModel::Validator
def validate(report)
if report.name.blank?
report.errors.add :name, :blank
end
# More validations...
end
end
Active Record
Slide 53
Slide 53 text
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)
Slide 54
Slide 54 text
report = Report.new
puts report.valid?
#=> false
puts report.errors.full_messages
#=> Name can't be blank
Active Record
Slide 55
Slide 55 text
class Report
include ActiveModel::Validations
validates_with ReportValidator
attr_accessor :name
end
Active Model
Slide 56
Slide 56 text
class Report
include ActiveModel::Validations
validates_with ReportValidator
attr_accessor :name
end
Active Model
include ActiveModel::Validations
validates_with ReportValidator
Slide 57
Slide 57 text
report = Report.new
puts report.valid?
#=> false
puts report.errors.full_messages
#=> Name can't be blank
Active Model
Slide 58
Slide 58 text
Validations:
Nova Sintaxe
Slide 59
Slide 59 text
class Report
include ActiveModel::Validations
attr_accessor :name
# validates_presence_of :name
validates :name, presence: true
end
Active Model
Slide 60
Slide 60 text
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
Slide 61
Slide 61 text
Custom
Validator
Slide 62
Slide 62 text
class Report
include ActiveModel::Validations
attr_accessor :no_name
validates :no_name, absence: true
end
Active Model
Slide 63
Slide 63 text
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
Slide 64
Slide 64 text
class AbsenceValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value.present?
record.errors.add attribute, :absence
end
end
end
Active Model
Slide 65
Slide 65 text
class AbsenceValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value.present?
record.errors.add attribute, :absence
end
end
end
AbsenceValidator
Active Model
Slide 66
Slide 66 text
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)
Slide 67
Slide 67 text
Translation
Slide 68
Slide 68 text
# I18n:
activerecord:
attributes:
report:
name: 'Nome'
puts Report.human_attribute_name('name')
#=> "Nome"
Active Record
Slide 69
Slide 69 text
# I18n:
activemodel:
attributes:
report:
name: 'Nome'
Active Model
Slide 70
Slide 70 text
# I18n:
activemodel:
attributes:
report:
name: 'Nome'
activemodel:
Active Model
Slide 71
Slide 71 text
class Report
extend ActiveModel::Translation
end
puts Report.human_attribute_name('name')
#=> "Nome"
Active Model
Slide 72
Slide 72 text
Validations
+ Translation
Slide 73
Slide 73 text
# I18n:
activemodel:
attributes:
report:
name: 'Nome'
errors:
messages:
blank: 'deve ser preenchido'
Active Model
Slide 74
Slide 74 text
report = Report.new
puts report.valid?
#=> false
puts report.errors.full_messages
#=> Nome deve ser preenchido
Active Model
Slide 75
Slide 75 text
Callbacks
Slide 76
Slide 76 text
class Report < ActiveRecord::Base
before_save { puts "it works before" }
after_save { puts "it works after as well" }
end
Active Record
Slide 77
Slide 77 text
Report.new.save
#=> it works before
#=> ...saving...
#=> it works after as well
Active Record
Slide 78
Slide 78 text
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
Slide 79
Slide 79 text
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
Slide 80
Slide 80 text
Report.new.save
#=> it works before
#=> ...saving...
#=> it works after as well
Active Model
Slide 81
Slide 81 text
Serialization
Slide 82
Slide 82 text
report = Report.new
report.name = "Omglol"
puts report.to_json
#=> {"report":{"name":"Omglol"}}
Active Record
Slide 83
Slide 83 text
class Report
extend ActiveModel::Naming
include ActiveModel::Serializers::JSON
attr_accessor :name
def attributes
{ name: name }
end
end
Active Model
Slide 84
Slide 84 text
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
Slide 85
Slide 85 text
report = Report.new
report.name = "Omglol"
puts report.to_json
#=> {"report":{"name":"Omglol"}}
Active Model
Slide 86
Slide 86 text
report = Report.new
report.name = "Omglol"
puts report.to_xml
#=>
#=>
#=> Omglol
#=>
Active Record
Slide 87
Slide 87 text
class Report
extend ActiveModel::Naming
include ActiveModel::Serializers::Xml
attr_accessor :name
def attributes
{ name: name }
end
end
Active Model
Slide 88
Slide 88 text
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
Slide 89
Slide 89 text
report = Report.new
report.name = "Omglol"
puts report.to_xml
#=>
#=>
#=> Omglol
#=>
Active Model
Slide 90
Slide 90 text
Attribute
Methods
Slide 91
Slide 91 text
report = Report.new
puts report.name? #=> false
report.name = "Omglol"
puts report.name? #=> true
Active Record
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
Slide 94
Slide 94 text
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
Slide 95
Slide 95 text
report = Report.new
puts report.name? #=> false
report.name = "Omglol"
puts report.name? #=> true
Active Model
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
Slide 98
Slide 98 text
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
Slide 99
Slide 99 text
report.name = "Omglol"
puts report.name? #=> true
report.clear_name
puts report.name? #=> false
Active Model
class Invitation
attr_accessor :contacts, :message
def new_record?
true
end
def id
nil
end
end
Slide 115
Slide 115 text
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
Slide 116
Slide 116 text
...
there we go!
Slide 117
Slide 117 text
nisso?
como chegar
Slide 118
Slide 118 text
Source diving!
Slide 119
Slide 119 text
Rails
2.3
Slide 120
Slide 120 text
Action Pack
Active Record
Slide 121
Slide 121 text
Active Record?
Blargh!?!!
Slide 122
Slide 122 text
NoSQL FTW!!
Slide 123
Slide 123 text
Action Pack
Mongoid
Slide 124
Slide 124 text
monkey
Patch
Slide 125
Slide 125 text
Outro objeto
em um form?
Slide 126
Slide 126 text
monkey
Patch
Slide 127
Slide 127 text
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
Slide 128
Slide 128 text
! API
Slide 129
Slide 129 text
Frágil
Slide 130
Slide 130 text
Rails
3
Slide 131
Slide 131 text
Rails 3
Rewrite Everything!
Slide 132
Slide 132 text
Active Model
Slide 133
Slide 133 text
Action Pack
Active Model
Slide 134
Slide 134 text
Active Model
Active Record
Action Pack
Slide 135
Slide 135 text
Active Model
Mongoid
Action Pack
Slide 136
Slide 136 text
Outro objeto
em um form?
Slide 137
Slide 137 text
Active Model
OmgLol
Action Pack
Slide 138
Slide 138 text
works
how it
Slide 139
Slide 139 text
form_for @report do |f|
f.label :name
f.text_field :name
f.submit
end
Slide 140
Slide 140 text
Nome
Slide 141
Slide 141 text
Nome
como?
Slide 142
Slide 142 text
Nome
como?
Slide 143
Slide 143 text
Nome
como?
Slide 144
Slide 144 text
Nome
Nome
como?
Slide 145
Slide 145 text
Nome
Nome
como?
Slide 146
Slide 146 text
Nome
Nome
como?
Slide 147
Slide 147 text
Nome
como?
Slide 148
Slide 148 text
Nome
como?
Slide 149
Slide 149 text
Nome
como?
Slide 150
Slide 150 text
Nome
como?
Slide 151
Slide 151 text
Nome
como?
Slide 152
Slide 152 text
API
Active Model
Slide 153
Slide 153 text
ActiveModel
::Lint::Tests
Slide 154
Slide 154 text
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
Slide 155
Slide 155 text
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
Slide 156
Slide 156 text
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
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
Slide 161
Slide 161 text
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
Slide 162
Slide 162 text
class Report
include ActiveModel::Conversion
attr_accessor :id
def persisted?
id.present?
end
end
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
Slide 166
Slide 166 text
require 'minitest/autorun'
class OmglolTest < MiniTest::Unit::TestCase
include ActiveModel::Lint::Tests
def setup
@model = Omglol.new
end
end
Slide 167
Slide 167 text
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
Slide 168
Slide 168 text
require 'active_model'
class Omglol
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
def persisted?; false; end
end
Slide 169
Slide 169 text
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
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
Slide 233
Slide 233 text
Validations?
Slide 234
Slide 234 text
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?
Slide 235
Slide 235 text
Rails 4
SPOILER
Slide 236
Slide 236 text
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
Slide 237
Slide 237 text
require 'minitest/autorun'
class OmglolTest < MiniTest::Unit::TestCase
include ActiveModel::Lint::Tests
def setup
@model = Omglol.new
end
end
RAILS
4
Slide 238
Slide 238 text
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
Slide 239
Slide 239 text
require 'active_model'
class Omglol
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?; false; end
def errors; Hash.new([]); end
end
RAILS
4
Slide 240
Slide 240 text
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
Slide 241
Slide 241 text
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
require 'active_model'
class Omglol
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?; false; end
def errors; Hash.new([]); end
end
RAILS
4
Slide 252
Slide 252 text
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
Slide 253
Slide 253 text
ActiveModel
::Model
Slide 254
Slide 254 text
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
Slide 255
Slide 255 text
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
Slide 256
Slide 256 text
require 'active_model'
class Omglol
include ActiveModel::Model
end
RAILS
4
Slide 257
Slide 257 text
require 'active_model'
class Omglol
include ActiveModel::Model
end
RAILS
4
include ActiveModel::Model
Slide 258
Slide 258 text
form_for @omglol
Slide 259
Slide 259 text
render @omglol
Slide 260
Slide 260 text
respond_with @omglol
Slide 261
Slide 261 text
Active Model
<3 <3 <3
Slide 262
Slide 262 text
No content
Slide 263
Slide 263 text
Active Model
Attribute Methods
Callbacks
Dirty
Mass Assignment
Secure Password
Observing
Serialization
Validations Validator
Model
Conversion
Naming
Translation
Lint