Gems of DockYard


Brian Cardarella

@bcardarella


Who?


Owner of @DockYard

Former organizer for BostonRB
Organizer for Boston OpenHack
Co-Organizer for Boston Ember.js


DockYard


Boston-based web consultancy
Rails, PostgreSQL, Ember.js

DRY => Open Source

http://dockyard.com
http://reefpoints.dockyard.com

Gems


  • ClientSideValidations
  • ValidAttribute
  • Capybara-Email
  • Postgres_ext
  • Dismissible Helpers
  • PartyFoul
  • ContextValidations





"Client Side Validations"



  • Automatically extract server-side validations and apply to client
  • When in doubt ignore validation and defer to server (conditionals, Procs)
  • Client-side validations render exactly the same as server-side rendered validations
  • "best practices" for client side validations
  • Support custom validations

# generator
rails g client_side_validations:install

# app/assets/javascripts/application.js
//= require rails.validations

# model
class User < ActiveRecord::Base
  validates :name, presence: true
end

# form
= form_for @user, validate: true do |f|
  = f.text_field :name



Plugins

Mongoid, MongoMapper, Formtastic, SimpleForm, Turbolinks, Ember

Plugins

Hosted at: http://github.com/dockyard

Gems


  • ClientSideValidations
  • ValidAttribute
  • Capybara-Email
  • Postgres_ext
  • Dismissible Helpers
  • PartyFoul
  • ContextValidations





"Valid Attribute"

# spec it { should validate_presence_of :name } it { should validate_numericality_of :age} # model validates_presence_of :name validates_numericality_of :age






  • "Double-end bookkeeping"
  • Tests tightly coupled to implementation
  • Not a good choice for BDD

Valid Attribute




# spec
it { should     have_valid(:name).when('Brian') }
it { should_not have_valid(:name).when(nil, '') }
it { should     have_valid(:age).when(21) }
it { should_not have_valid(:age).when('twenty-one') }

# model
validates_presence_of :name
validates_numericality_of :age

Valid Attribute





# spec
it { should     have_valid(:name).when('Brian') }
it { should_not have_valid(:name).when(nil, 'Bob') }

# model
validates_presence_of :name
validates_length_of :name, :greater_than => 3

Gems


  • ClientSideValidations
  • ValidAttribute
  • Capybara-Email
  • Postgres_ext
  • Dismissible Helpers
  • PartyFoul
  • ContextValidations





"Capybara-Email"

feature 'Emailer' do
  background do
    # will clear the message queue
    clear_emails
    visit email_trigger_path
    # Will find an email sent to test@example.com
    # and set `current_email`
    open_email('test@example.com')
  end

  scenario 'following a link' do
    current_email.click_link 'your profile'    page.should have_content 'Profile page'
  end

  scenario 'testing for content' do
    current_email.should have_content 'Hello Joe!'
  end

  scenario 'view the email body in your browser' do
    # the `launchy` gem is required
    current_email.save_and_open
  end
end

Gems


  • ClientSideValidations
  • ValidAttribute
  • Capybara-Email
  • Postgres_ext
  • Dismissible Helpers
  • PartyFoul
  • ContextValidations





"Postgres_ext"






  • Written by Dan McClain (@_danmcclain)
  • We <3 PostgreSQL
  • ActiveRecord has ok support
  • We've improved ActiveRecord 4.0







  • Arrays
  • INET, CIDR, MACADDR, UUID, CITEXT
  • Indexing
  • Querying

Array


create_table :items do |t|
  t.string :names, :array => true, :default => []
end

i = Item.new(names: ['Brian', 'Dan'])i.names += ['Doug', 'Amanda']i.savei.reloadi.names=> ['Brian', 'Dan', 'Doug', 'Amanda']

Array


# Find an item with 'Brian' as a name
Item.where.any(names: 'Brian')
=> []

# Overlap
ARRAY[1,2,3] && ARRAY[4,5,6]
-- f

ARRAY[1,2,3] && ARRAY[3,5,6]
-- t

Item.where.overlap(:names => ['Bob', 'Fred'])
=> [, ]

Other types


create_table :testing do |t|
  t.inet    :inet_column
  t.cidr    :cidr_column
  t.macaddr :macaddr_column
  t.uuid    :uuid_column
  t.citext  :citext_column
end

Indexes


add_index :table_name, :column, :where => 'column < 50'

Gems


  • ClientSideValidations
  • ValidAttribute
  • Capybara-Email
  • Postgres_ext
  • Dismissible Helpers
  • PartyFoul
  • ContextValidations





"Dismissible Helpers"
# routes.rb
dismissible_helpers_routes

# app/assets/javascripts/application.js
//= require dismissed_helpers

$(function(){
  $('.dismissible').dismissible();
});

# Template
<%= render_dismissible_helper 'sample_page.help_text' %>

With authenticated User


# Migration
class AddDismissedHelpersToAccounts < ActiveRecord::Migration
  def change
    add_column :accounts, :dismissed_helpers, :text
    
    # or if you are using postgres_ext
    add_column :accounts, :dismissed_healpers, :string, :array => true, :default => []
  end
end

# Model
class Account < ActiveRecord::Base
  # Not necessary if you are using postgres_ext
  serialize :dismissed_helpers, Array
end

Customize


$(function(){
  $('.dismissible').dismissible({
    success: function(helper){
      helper.slideUp();
    }
  });
});

Gems


  • ClientSideValidations
  • ValidAttribute
  • Capybara-Email
  • Postgres_ext
  • Dismissible Helpers
  • PartyFoul
  • ContextValidations





"Party Foul"

  • Attempt to find a matching issue in your GitHub repo
  • If no matching issue is found a new issue is created with a unique title, session information, and stack trace. The issue is tagged as a bug. A new comment is added with relevant data on the application state.
  • If an open issue is found the occurence count and time stamp is updated. A new comment is added with relevant data on the application state.
  • If a closed issue is found the occurence count and time stamp is updated. The issue is reopened and a regression tag is added. A new comment is added with relevant data on the application state.
  • If the issue is marked as wontfix the issue is not updated nor is a new issue created. No comments are added.





  • Supports background processors (Sidekiq, Resque, DelayedJob)
  • Custom labeling on issues
  • Tracking errors outside of HTTP request (i.e. in a Worker process)
  • Supports Github Enterprise

Gems


  • ClientSideValidations
  • ValidAttribute
  • Capybara-Email
  • Postgres_ext
  • Dismissible Helpers
  • PartyFoul
  • ContextValidations





"Context Validations"






The Controller is the context
class UserController < ApplicationController
  include ContextValidations::Controller

  def create
    @user = User.new(user_params)
    @user.validations = validations(:create)

    if @user.save
      # happy path
    else
      # sad path
    end
  end

  private
  def create_validations
    validates :password, :presence => true
  end

  def base_validations
    validates :first_name, :last_name, :presence => true
    validates :password, :confirmation => true
    validates :email, :uniqueness => true, :format => EmailFormat
  end
end

describe UserController do
  context 'create' do
    subject { User.new(:password => 'password', :validations => validations_for(:create)) }
    it { must have_valid(:name).when('Brian Cardarella') }
    it { wont have_valid(:name).when(nil, '') }
  end
end
    



Work With Us!

jobs@dockyard.com


(or even better)


Hire Us!

sales@dockyard.com




~ FIN ~

dockyard gems

By bcardarella

dockyard gems

  • 4,381