giant robots smashing into other giant robots

Written by thoughtbot

Episode 19: I have tons of guns and knives

We’re recording at RubyConf this week, cranking out of a ton of great interviews. We decided to release this one from the vault a little early as a special RubyConf bonus to all our listeners.

Ben Orenstein is joined by Aaron Patterson, Ruby Core team member, Rails Core team member, and a Señior Software Engineer at AT&T Interactive. Aaron and Ben discuss the upcoming features and excitement for Ruby 2.0 and some things Aaron would like to see in Ruby in the future that didn’t quite make it into Ruby 2.0. They also discuss how the Rails Core team differs from the Ruby Core team, how much effort it takes to write a detailed blog post and how many mistakes are involved, how he likes being a ruby celebrity, his involvement in Seattle.rb and what it teaches him. Finally, how awesome his job is and how he could do it forever, how he worries about Ruby or Rails becoming irrelevant and wants to stop that from happening, how he is happy all the time, and if he could wave a magic wand and change one thing about Rails, what it would be. This and so much more in this entertaining episode recorded at RubyConf 2012.

hrward

ActiveModel Form Objects

Submitting form data is a common feature of web applications — allowing users to submit their information and giving them feedback whether the information is valid or not.

ActiveRecord comes with a powerful set of validators for attributes on a persisted data model. When data is not persisted, or used for other non-active record purposes, Active Model Helper Modules reduce the complexity of validations on your plain old Ruby objects.

Routing

Create the routes needed for displaying the form object and posting the data

  • Restrict resources to the routes you need using only:
# config/routes.rb
resources :registration, only: [:new, :create]

Controller and Actions

Create a controller with new and create actions.

  • respond_with will re-render the new action if there are any validation errors on the model
  • If there are no errors on the model the visitor will be redirected to show the current resource. In this case the user will be redirected to some_other_success_path
# app/controllers/registration_controller.rb
class RegistrationsController < ApplicationController
  respond_to :html

  def new
    @registration = Registration.new
  end

   def create
    @registration = Registration.new(registration_params)
    @registration.register

    respond_with @registration, location: some_success_path
  end

  private

  def registration_params
    # ...
  end
end

View with Registration Form

The view renders a web form with fields to submit.

  • Use the ActiveModel object @registration in the form
  • Form generates the endpoint registration_path and method of delivery post
  • Validation errors will display inline within the form just like ActiveRecord
# app/views/registration/new.html.erb
<%= form_for @registration do |f| %>
  <%= f.label :first_name, 'First Name' %>:
  <%= f.text_field :first_name %>
  …
  <%= f.submit %>
<% end %>

Object with ActiveModel Conversion, Naming, and Validations

Use any of the ActiveRecord Validations in the model.

  • Command pattern used when calling register method.
  • ActiveRecord validation syntax on attributes.
  • ActiveModel::Model mixin includes modules, and includes an initialization method.
# app/models/registration.rb
class Registration
  include ActiveModel::Model

  attr_accessor(
    :company_name,
    :email,
    :first_name,
    :last_name,
    :terms_of_service
  )

  validates :company_name, presence: true
  validates :email, presence: true, email: true
  validates :first_name, presence: true
  validates :last_name, presence: true
  validates :terms_of_service, acceptance: true

  def register
    if valid?
      # Do something interesting here
      # - create user
      # - send notifications
      # - log events, etc.
    end
  end

  private
  
  def create_user
    # ...
  end
end

Takeaways

  • Keep business logic out of the Controller and Views
  • Add validation support to plain Ruby object using ActiveModel includes
  • Display data validation errors in the form
  • Use ActiveModel naming conventions for generating form endpoints

Written by Harlow Ward

Episode #14: Say goodbye to that big guy

Ben Orenstein is joined by Prem Sichanugrist, a developer at thoughtbot and the #31 top Rails contributor. Ben and Prem walk through the major changes that will be introduced in Rails 4, including strong parameters, the new built in queue, cache_digest, changes in ActiveRecord::Relation, and ActiveResource. The also discuss what people can do to ease contribution and issue submission to Rails, how can people get their first commit into Rails, and much more.

Podcast Episode #14, “Say goodbye to that big guy”

adarshp

Don’t Repeat Your Ruby Constants in Javascript

Constants help us avoid Magic Numbers and repeated code, which violates the DRY principle.

Recently, I needed to count down the the remaining characters in a text field.

I limited the length of the attribute using a constant:

class Event < ActiveRecord::Base
  NAME_MAX_LENGTH = 70

  validates :name, length: { maximum: NAME_MAX_LENGTH }

  # ...
end

Then I repeated myself in the JavaScript:

# app/assets/javascripts/countdown_event_name.js
var max = 70

“This is a nasty scenario - I’ve got the same value in two places!”, says I. How else could I access the constant more cleanly from my Event model in the JavaScript?

Answer

I discovered you can use ERB in JavaScript if you change file extensions and trigger preprocessing like so:

# Rename countdown_event_name.js → countdown_event_name.js.erb
var max = <%= Event::NAME_MAX_LENGTH %>

Appending .js.erb to the filename initiates asset pipeline preprocessing. Processing occurs in order, right-to-left, so make sure to keep things in order. For example, .js.coffee.erb is processed as ERB first, then processed as CoffeeScript, then served as a JavaScript file for the browser to interpret.

lolconomy

Hidden gems: suspenders

Have you seen our suspenders? It is a Rails app generator that includes a set of Ruby gems and common code that we use on every project.

Suspenders Boy

Install it

gem install suspenders

This will install gems with C code, which means you need your OS set up for that. On Debian you need rubygems and build-essential; on OS X you can use the laptop script.

Suspenders will also install capybara-webkit by default. Read the instructions for setting up your OS for it, or use the --webkit false option with the following command.

Create a Rails app

suspenders demo

This makes a demo app. See the difference between it and a bare Rails app.

Gems

The gems are a mix of production libraries like newrelic, development libraries like foreman, and testing libraries like timecop. The full list often changes, so see templates/Gemfile_additions for the exact list.

We selected these gems because we use them on most apps, they have tests, and they are maintained. Some of them are ours but most are from others in the community.

Common code

Suspenders includes a Guardfile, flash and Javascript partials, configuration for Heroku, Factory Girl, Bourbon, Postgres, and more:

  • An email address validator so you can do validates :login, email: true
  • A list of HTTP and SMTP exceptions that we have gathered through trial and error.
  • Prefilled form inputs using JavaScript for a nice user experience:

    <input type="text" class="prefilled" title="Email" name="user[email]" />

Even better Suspenders

Create Heroku staging and production apps with the --heroku option:

suspenders demo --heroku true

Create a Github project with the --github option:

suspenders demo --github organization/project

Use a different authentication library or no auth at all with the --clearance option:

suspenders demo --clearance false

Opt out of the capybara-webkit dependencies with the --webkit option:

suspenders demo --webkit false

Or, combine options:

 suspenders demo --heroku true --github organization/project --webkit false

That was easy

Suspenders should make your life easier. Reduce the tedious decisions, add the one-liners you wish you had, and set up the infrastructure common to every codebase.

Use suspenders for your next Rails app!