Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

JT Archie

Posts By

PIVOTAL LABS
[NYC][Standup] 09/27/12: Protect all your attributes

Interestings

attr_accessible is gone

The strong_parameters gem has been integrated into rails edge by DHH and replaces attr_accessible.

https://github.com/rails/rails/commit/c49d959e9d40101f1712a452004695f4ce27d84c

Capybara's should_not have_css visibility: false

Capybara's "should_not have_css "#whatevs", visibility: false" results in flaky tests if the content in question is being hidden after a process completes (such as an AJAX request).

An alternative is "should_not have_selector "#whatevs", visible: false". This results in substantially less flaky integration tests.

PIVOTAL LABS
[Standup][NYC] 09.24.2012 Moral support for the pub and sub

Interestings

ActiveSupport::Notifications implements Pub/Sub

iOS6 Safari Caching POSTs

Workarounds needed until bug is fixed.

http://arstechnica.com/apple/2012/09/developers-claim-safari-in-ios-6-breaks-web-apps-with-aggressive-caching/

Events

Tuesday: NYC.rb Hackfest

Tuesday: Brown bag on ThreeJS (WebGL)

LABS
merging scopes with STI models

Introduction

On a client project recently, we ran into a domain problem that didn't fit into the ActiveRecord standard conventions. The following is the thought process taken to get to our solution, so it gets detailed in some areas.

ActiveRecord has a great feature called Single Table Inheritance. It allows a model to have multiple types while using a single database table for the storage. Those type abstractions can each have their own validations, override base functionality, and specific abstraction functionality.

If your model has ever been littered with case statements checking if a User is a guest, admin, etc., you should take a look at STI.

Models

The project had a based model that had many types and each abstraction had a scope of .active that defined what it meant to be active for that type.

class Person < ActiveRecord::Base; end

class FireFighter < Person
  def self.active
    where(has_helmet: true)
  end
end

class PoliceOfficer < Person
  def self.active
    where(has_squad_car: true)
  end
end

Problem

We needed to create an API endpoint that returned all active Person instances. This would require us to iterate through each child of Person and get all its current active members. Since we have Person model let's give it a concept of .active that incorporates every active member of society in our domain.

Solution

We can extend Person to return an array of each active FireFighter and PoliceOfficer.

class Person < ActiveRecord::Base
  def self.active
    FireFighter.active.all + PoliceOfficer.active.all
  end
end

One problem we have with this implementation is every time we add a new abstraction of Person we have to add to .active. Luckily, ActiveRecord STI comes with support for looking up a parent's .descendants.

class Person < ActiveRecord::Base
  def self.active
    active_people = descendants.map do |descendant|
      d.active.all
    end.flatten
  end
end

This is pretty powerful. We can add Astronaut and any active astronauts will automatically be in Person.active array. This implementation will help satisfy our API endpoint requirements, but it does break useful ActiveRecord patterns.

Advance Solution

WARNING: Continue at your own risk. If you are content with the solution above stop, but if you want to see what can be done with Arel continue.

What if we want to chain scopes or extend the .active with pagination for our API? We cannot do this because easily because we are currently returning a Ruby array instead of an ActiveRecord::Relation. How can we modify .active to be an actual scope?

You might be thinking, ActiveRecord comes with the ability to merge scopes between models. Unfortunately, it does not work very well when merging scopes with STI models.

We ended using Arel (known for not being well documented) within our model. Each ActiveRecord::Relation is actually just an object with holding on to Arel values for different parts of an SQL statement -- joins, froms, selects, etc. We are able to get the conditions for WHERE clause by looking at the ActiveRecord::Relation where_values.

class Person < ActiveRecord::Base
  def self.active
    conditions = descendants.map do |d|
      d.active.where_values.reduce(:and)
    end.reduce(:or)

    where(conditions)
  end
end

Our implementation takes the where_values from the .active scope from each descendant and does an SQL OR on them. ActiveRecord::Relation can take

# somewhere in a Rails console
> Person.active.to_sql
=> SELECT "people".* FROM "people"  WHERE (
      ("people"."has_helmet" = 't' AND "people"."type" = "FireFighter")
        OR
      ("people"."has_squad_car" = 't' AND "people"."type" = "PoliceOfficer")
    )

What does give us? We can now use Person.active as a normal scope, which allows us to append any conditions on to it.

> Person.active.where(created_at: 2.days.ago..1.day.ago).order(:created_at)
=> []
> Person.active.limit(10)
=> []

LABS
What I've learned about RubyMotion

I've been trying to learn RubyMotion recently, using Ruby to develop iOS appeals to me.

I have no prior Objective-C or Cocoa API knowledge besides the basic HelloWorld. I've been using this tutorial and have learned more about Cocoa API faster using Ruby than with Objective-C. There is less boilerplate code that needs to be written for defining interfaces and implementations.

The main takeaway of RubyMotion is that it is not your standard Ruby implementation. It is a Ruby runtime wrapped around the Objective-C runtime. All Ruby objects map directly to there corresponding Objective-C object -- Array to NSMutableArray, Hash to NSMutableDictionary, etc. RubyMotion does not come with the standard library as other flavors, you are relying on Cocoa API as the standard library.

There is even a difference in Ruby syntax to map directly to Objective-C. The Objective-C language does message passing for "method invocation". This means that a method call on an object is determined by parameters rather than just method name. RubyMotion had to include this language feature, so you will actually see Ruby that is invalid all other Ruby flavors.

class MyObject
    def doSomething(doSomething, argument: argument)
    end

    #This does not override the method defined above
    def doSomething(doSomething, anotherArgument: argument)
    end
end

Luckily there are extensions for your favorite editors. Rubymine even supports MacRuby syntax, but does not support autocomplete, yet.

Two weeks ago, I saw a talk about RubyMotion from its creator in Berlin. He gave the basic HelloWorld demonstration, but also gave an introduction in the community. It is small, but great things are coming out of it.

The community has started taking the power of Ruby and making the libraries and DSL-y things we love in Ruby.

  • BubbleWrap is a resource API. It gives you easy access to JSON parsing, HTTP requests, alerts, etc. It is kind of catch all of lower-level Cocoa API tasks that you don't want to have to write your own helpers for.
  • Formotion is a DSL to create Forms. Usually you use Interface Builder to build forms and load the appropriate NIB. This gem will allows you to define a form in code.
  • MotionData is ActiveRecord like access to CoreData. It supports migrations, scopes, basic validations, etc.
  • SimpleView provides a DSL for formatting views.

With all this, there is one question that always gets asked. Is RubyMotion worth it? Yes! Laurent, the creator, is in it to win it! This is why he charging for the RubyMotion; funding ensures that he can continue to work on it.

From a Pivot role, I've had to discover RubyMotion's position in testing. Pivotal Labs is a pure TDD shop, everything from Java, Objective-C, Javascript, and Ruby is tested.

RubyMotion comes with a prebuilt RSpec (actually a port of bacon) like testing framework. The testing framework supports the testing of views and controller using the UIAutomation framework. I think that we can agree that it could be better, but I believe there is enough to get started and allow us to expand on it.

The RubyMotion community is still growing. I look forward to see what comes out of it, so that I can use Ruby in other devices.

PIVOTAL LABS
[Standup][NY] 03/08/2012

Interesting

  • Ruby MRI seems to have taken a step back in time, a dangerous, but useful feature (to some) is the goto statement.
  • It appears that DateTime object has some issues with doing math.

    DateTime.now - 1.hour #raises TypeError
    DateTime.now - 3600   #works as expected
    1.hour.class          #Fixnum
    
  • Reading the CSS property background-position in Chrome returns an invalid value. Don't rely on it.

  • Github was hacked! They had a security issue that was a result of attr_accessible being uses incorrectly. Remember to authorize your SSH keys.
  • Need help with cron? Use http://cronwtf.github.com to convert cron into friendly English.
  • &&, ||, and ! vs. and, or, and not. It is highly recommended to always use the strict logical operators (&&, ||, and !) because the keywords (and, or, and not) don't have the same operator precedence.
  • When evaluating variables in strings with bash, its better to use ${var} than $var. The curly-brace allows you to evaluate a variable with copy behind it. For example, ${var}asdf and $varasdf evaluate differently because of the expected variable name.

Help

  • Rails <3.1 has some gotchyas when using :inverse_of option.

    class Note < ActiveRecord::Base
      has_many :contacts, inverse_of: :note
    end
    
    
    class Contact < ActiveRecord::Base
      belongs_to :note, touch: true #for triggering the note observer when the contact is updated
    end
    
    
    class NotObserver
      def after_touch(note)
        note.contacts # does not have the new attributes updated unless you specify the :inverse_of
      end
    end
    
    
    # Somewhere in the code...
    contact.update_attributes....
    
  • When table names are not namespaced on a class. What is the best way to work with this if we want table names to be namespaced?

    class Foo::Bar < ActiveRecord::Base
    end
    
    
    > Foo::Bar.table_name == "bars"
    true
    

PIVOTAL LABS
[Standup][NYC] 2/29/2012 – Lead Day, do we have to program for that case?

Interesting

  • When using validates on an association, remember for uniqueness validations to use the associated attribute.

    validates :foo, :uniqueness => true
    

    Should be

    validates :foo_id, :uniqueness => true
    
  • You can get a quick an easy git blame with a string, rather than a line number.

    git log --pretty=oneline -S'some string'

Help

  • What is the advantage of using scope over a class method?

    scope :new, order(:id)
    

    or

    def self.new
      order(:id)
    end
    

    Some Pivots seem to think that scope doesn't add the default scope in some cases (a bug?). It appears that class methods are the preferred way moving forward in Rails.

Events

  • Tuesday brown bag was a series of Youtube videos of Alan Key speaking about programming.
  • Thursday UX Book Club is meeting to discuss Steve Jobs book.

PIVOTAL LABS
[Standup][NYC] 1/17/2011

Interesting

  • Trying to load Ruby 1.9.3 with RVM on OSX Lion and having problems? Adam has found a solution here.

Events

  • Simple made easy was the tech talk (video) today. The implications being what is easy might not be the best for your code maintenance.

PIVOTAL LABS
[Standup][NY] 12/14/2011 — Nyan can reaches 5 million seconds tomorrow at 4:53pm

Interesting

  • Git 1.7.8 is out!
  • We have a new gong in the office!
  • When using Timecop.timetravel in your tests, make sure that you use before setting up your test data. Otherwise the data could potentially be created before that time existed!
  • git whatchanged gives you a normal git log with a list of changed files.

Help

  • Rails console history is crazy! On opening a new session, and pressing up for history, random data appears from history, many eons ago. Two files are written to with each rails command -> irb_history and irb-history. Any idea what's going? Some people think that it might the interaction with wirble.

PIVOTAL LABS
[Standup][NYC] 2011-11-16 – Lion is not Enterprise ready

Interesting

  • If you are trying to get REE on Lion make sure that you have GCC 4.2 or higher. Learn more.
  • If you are still using a mouse with scroll wheel in Lion, disable the middle click annoyance with Mission Control.

Help

  • Donate for Movember we are team 'Pivots NY'. We grow facial hair for Man Cancer Awareness Month.

PIVOTAL LABS
[Standup][NYC] 2011-11-14 – 3, 2, 1 Launch!

Interesting

  • Heroku has released Scheduler. Their replacement functionally for cron, which allows you to schedule processes to be run (limited to a 10 minute interval).

Events

  • Monday - Raise Cache @ 7pm
  • Wednesday - node.js meetup @ 6:30pm
  • Wednesday - Machine Learning study group @ 7pm