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

ActiveModel::Niceties

cfcosta
September 14, 2012

 ActiveModel::Niceties

My presentation at Codeminer 42 Tech Talk on 08/28/2012

cfcosta

September 14, 2012
Tweet

Other Decks in Technology

Transcript

  1. ActiveModel::Niceties
    Tuesday, August 28, 12

    View Slide

  2. $ whoami
    Cainã Costa
    @cfcosta_
    Developer at Codeminer42
    $
    Tuesday, August 28, 12

    View Slide

  3. Let’s say we have a
    form...
    Tuesday, August 28, 12

    View Slide

  4. <%= form_for @contact do |f| %>
    <%= f.label :name %>
    <%= f.text_field :name %>
    <%= f.label :email %>
    <%= f.text_field :email %>
    <%= f.label :body %>
    <%= f.text_area :body %>
    <%= f.submit %>
    <% end %>
    Tuesday, August 28, 12

    View Slide

  5. class ContactController < ApplicationController
    def new
    @contact = Contact.new
    end
    def create
    @contact = Contact.new(params[:contact])
    if @contact.valid?
    # Code to send the contact mail
    else
    render 'new'
    end
    end
    end
    Tuesday, August 28, 12

    View Slide

  6. class Contact
    end
    Tuesday, August 28, 12

    View Slide

  7. Does that work?
    Tuesday, August 28, 12

    View Slide

  8. Nope!
    Tuesday, August 28, 12

    View Slide

  9. ActiveModel::Naming to
    the rescue!
    Tuesday, August 28, 12

    View Slide

  10. class ContactForm
    extend ActiveModel::Naming
    end
    Tuesday, August 28, 12

    View Slide

  11. Not yet...
    Tuesday, August 28, 12

    View Slide

  12. class ContactForm
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    end
    Tuesday, August 28, 12

    View Slide

  13. What now?
    Tuesday, August 28, 12

    View Slide

  14. class ContactForm
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    def persisted?
    false
    end
    end
    Tuesday, August 28, 12

    View Slide

  15. Looks like the problem is
    on our code now...
    Tuesday, August 28, 12

    View Slide

  16. class ContactForm
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    attr_accessor :name, :email, :body
    def initialize(attributes = {})
    attributes.each_pair do |k,v|
    send(:”#{k}=”, v)
    end
    end
    def persisted?
    false
    end
    end
    Tuesday, August 28, 12

    View Slide

  17. But when we try to
    save it...
    Tuesday, August 28, 12

    View Slide

  18. Ok, Let’s add some
    validations to it!
    Tuesday, August 28, 12

    View Slide

  19. FactoryGirl.define do
    factory :contact_form do
    name { Faker::Name.name }
    email { Faker::Internet.email }
    body { Faker::Lorem.paragraphs(3).join("\n") }
    end
    end
    But some tests first...
    Tuesday, August 28, 12

    View Slide

  20. Factories are not only for
    database models!
    Tuesday, August 28, 12

    View Slide

  21. require 'spec_helper'
    describe Contact do
    subject { build :contact }
    it "is valid with valid attributes" do
    should be_valid
    end
    it "is not valid without name" do
    subject.name = nil
    should_not be_valid
    end
    it "is not valid without (or with invalid) email" do
    subject.email = nil
    should_not be_valid
    subject.email = "invalid email"
    should_not be_valid
    end
    it "is not valid without body" do
    subject.body = nil
    should_not be_valid
    end
    end
    Tuesday, August 28, 12

    View Slide

  22. class Contact
    extend ActiveModel::Naming
    include ActiveModel::Conversion
    include ActiveModel::Validations
    attr_accessor :name, :email, :subject, :body
    validates :name, :email, :body, presence: true
    validates :email, format: { with: %r{.+@.+\..+} }, allow_blank: true
    def initialize(attributes = {})
    attributes.each do |k, v|
    send("#{k}=", v)
    end
    end
    def persisted?
    false
    end
    end
    Tuesday, August 28, 12

    View Slide

  23. Does it work?
    You can bet your sorry ass that it does.
    Tuesday, August 28, 12

    View Slide

  24. But what about Mass-
    assignment Security?
    Tuesday, August 28, 12

    View Slide

  25. Let’s do it on the right
    place!
    THE CONTROLLER!
    Tuesday, August 28, 12

    View Slide

  26. class ContactsController < ApplicationController
    include ActiveModel::MassAssignmentSecurity
    attr_accessible :name, :email, :password
    # #new removed for briefness
    def create
    @contact = Contact.new(contact_params)
    if @contact.valid?
    # blabla
    else
    render 'new'
    end
    end
    private
    def contact_params
    params[:contact] ||= {}
    sanitize_for_mass_assignment(params[:contact])
    end
    end
    Tuesday, August 28, 12

    View Slide

  27. What about roles?
    def contact_params
    role = current_user.admin? ? :user : :admin
    params[:contact] ||= {}
    sanitize_for_mass_assignment(params[:contact], as: role)
    end
    Tuesday, August 28, 12

    View Slide

  28. Rails have a lot of
    things ready for use.
    Just use them.
    Tuesday, August 28, 12

    View Slide

  29. Questions?
    Tuesday, August 28, 12

    View Slide