Extract Mostly-Constant Data from the Database

Posted 4 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

Using database-backed models in our applications can cause coupling and performance problems. Extracting that data to Ruby constants helps to resolve those problems.

Example

Consider the following database tables and their data:

  • subscription_plans (subscriber free, subscriber paid, group free, group paid)
  • countries (United States, India, Belgium, Uruguay, etc.)

This data change so rarely that for the purpose of the application, it is essentially constant. Representing the data in our database has the following drawbacks:

  • Code/database coupling
  • Slower performance

Code/database coupling

If we put constant data in the database, our code and the database will need to exist in a very specific shape at a given time.

Every environment (development, staging, production) will need to know the values and seed them into their respective databases.

When we need to deploy code changes, we may need to include a data migration to chande the data. Particularly in environments that gradually roll out features, this may complicate our development, git branching, and deploy processes by forcing us to consider questions such as:

  • Do we run the migration before or after the code changes are deployed?
  • During the roll out to a percentage of users and app servers, will both old and new code work on the migrated database or will one cohort get bugs?

Slower performance

While 99% of our traffic patterns should be served from our database cache, we will still be paying a small performance penalty for accessing the database across a network.

In comparison, if we move our data to constants in our application, we will already have it in memory when the application loads. There is essentially no performance hit to pull it from memory when we need it.

Solution: Constants and Plain Old Ruby Objects

Here is an example class that can replace the subscription_plans table:

class SubscriptionPlan
  def initialize(slug, name, braintree_id = nil)
    @slug = slug.to_s
    @name = name
    @braintree_id = braintree_id
    raise 'plan slug not recognized' unless SLUGS.include?(@slug)
  end

  SLUGS = %w(subscriber_free subscriber_paid group_free group_paid).map(&:freeze).freeze
  SUBSCRIBER_FREE = new('subscriber_free', 'Free Subscription')
  SUBSCRIBER_PAID = new('subscriber_paid', 'Monthly Subscription', 'user_monthly')
  GROUP_FREE = new('group_free', 'Group Subscription')
  GROUP_PAID = new('group_paid', 'Group Subscription', 'group_monthly')

  attr_reader :name, :slug

  def braintree_plan?
    braintree_id.present?
  end

  def price
    price_in_cents.to_f / 100
  end

  def price_in_cents
    braintree_plan? ? 5000 : 0
  end
end

The application no longer needs to have up-to-date seeds, neither its test suite to have factories in sync to be able to run.

We no longer need database migrations if a new subscription plan is added in the future. Instead, the constantized data changes alongside with the code that consumes it, making deploys simpler.

What's next?

If you found this useful, you might also enjoy don't be normal.

This article was based on the original notes in my blog.

Security update: Heartbleed

Posted 4 months back at entp hoth blog - Home

On Monday April 7th, a vulnerability in OpenSSL was disclosed as CVE-2014-0160, also known as Heartbleed. This is a serious vulnerability as OpenSSL is widely used to secure HTTPS traffic, and so it affects a large part off the internet.

All our services have been patched and secured: Tender was never vulnerable but Lighthouse was partially vulnerable through our use of Amazon Elastic Load Balancer. Our load balancer runs on a dedicated instance, which limits the data that could have been exposed. On Tuesday 8th, Amazon issued an update to their services, and we immediately updated our certificates and moved to a new load balancer.

What do I need to do?

If you are a Tender customer: nothing. Tender was never affected.

If you are a Lighthouse customer we recommend:

  • Sign out and back in
  • Change your password
  • Update all your API tokens

No malicious activity has been detected, but given the nature of the bug, and the amount of time it existed, it is better to err on the side of caution.

As usual, if you have any question, comment or concern, feel free to reach out to us at support@lighthouseapp.com or support@tenderapp.com.

Be safe.

Introducing Hound

Posted 4 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

We're pleased to announce Hound, a hosted service that comments on Ruby style guide violations in your GitHub pull requests.

Hound is currently free and available for public and private GitHub projects. We intend to charge in the near future to ensure Hound is sustainable, but public projects will continue to be free. Hound is also open source.

Hound example

Why code style matters

At thoughtbot, we write code that follows our open source style guide.

A consistent code style emphasizes care and team communication. It encourages other developers working in the code to keep the campground clean. It lowers the cognitive overhead for a developer reading code and lets them focus on higher-level concerns, such as the domain and the logic. It also avoids unnecessary debate during code reviews.

What we did before Hound

Historically, if we saw a style guide violation when we reviewed our teammates' code, we would comment on the line in the GitHub pull request.

That worked relatively well, but had some problems.

It was socially awkward. We tended to feel sheepish offering feedback such as:

80 character limit

Or:

Single quotes unless interpolating

It can be tedious to make many of those comments, especially for new developers on a project.

It can cause reviewers to focus on low-level style concerns instead of the primary code change.

All of those reasons can add up to not wanting to comment on every style guide violation, which can let them slip through, which erodes at the benefits of style consistency.

How Hound helps

Given those problems, a program is better than a human for reviewing code style. Hound handles checking for style violations so we humans don't have to.

Hound reviews your Ruby code when a pull request is opened or updated. If Hound finds any style violations in the modified code it will comment on the appropriate line.

Hound example

Thanks, Hound!

Open source

We're also very pleased to experiment with a model of open sourcing a hosted service from the beginning. There are so many good reasons to do this in general, and for Hound specifically:

  • It provides transparency, as users are able to understand exactly how Hound works.
  • It creates an ecosystem where third parties may extract libraries from Hound.
  • Third parties may submit pull requests to fix their own bugs, increasing the number of people who can help support Hound for all its users.
  • It places the focus value not on our super-secret-source-code but on our handling of the hosting, billing, and maintenance of that source code.
  • It provides security through the "many eyes" approach, which we believe is better than security through obscurity.

We believe Hound can be financially successful while being open source.

Ready and waiting for you

Hound has been used on over 300 GitHub projects. We've been using it internally for some time. It only takes a minute to start using it on your project.

Try Hound today.

Heartbleed exploit tl;dr

Posted 4 months back at mir.aculo.us - Home

OpenSSL had a bug for several years which allowed attackers to untraceably read all your SSL traffic and some server memory.

If you’re like me and have better things to do than reinvent the fix-wheel and you’re all like “WTFBBQ TL;DR” here’s the absolute minimum what anyone who runs a web server with SSL must do.

NO, NONE OF THESE STEPS ARE OPTIONAL.

  • Update OpenSSL to 1.0.1g. This is required before you do anything else.
  • Recompile anything that’s statically linked against OpenSSL. In many instances, web server software like Nginx is statically linked and must be recompiled. For example, if your Ruby is statically linked to OpenSSL, it’s recompile time!
  • Reboot the server. This must be done before issuing new certificates.
  • Create a new private key and CSR and get a new SSL certificate. You will need to revoke the old SSL certificate. (If you’re on Godaddy, use their “rekey” function. The old cert will be revoked automatically after 72 hours). Don’t forget to install your new cert.
  • Change any server passwords. These may have been read by an attacker as they are in server memory. It’s not a bad idea to issue new server SSH hostkeys as well.
  • Change any and all passwords and tokens of APIs you use. As server memory may have been compromised, an attacker could access the APIs as if they where you. Not good.
  • If you’re using cookie-based sessions in Rails (or similar environments) you must switch to a new encryption secret. Your current secret may have been compromised, allowing attackers to log in as anyone to your service. Unfortunately this means all your users will have to log in again.
  • Ask your users to change their passwords. As this security issue means that server memory may have been compromised as well as past traffic could be decrypted, passwords should be considered to be compromised.

Whew.

There’s an optional step, which I highly recommend while you’re at it—get your SSL configuration into shape and enable PFS and HSTS. It just takes a minute if you’re on Nginx.

If you have anything to add, please email me directly and I’ll update this post.

Episode #454 - April 8th, 2014

Posted 4 months back at Ruby5

On today's episode: Rails 4 PostgreSQL integration, tips for hiring great software engineers, Ruby Love, what your conference proposal is missing, crafting a conference talk, an introduction to JSON schemas, Build a Ruby Gem, and Surviving APIs with Rails

Listen to this episode on Ruby5

Sponsored by Top Ruby Jobs

If you're looking for a top Ruby job or for top Ruby talent, then you should check out Top Ruby Jobs. Top Ruby Jobs is a website dedicated to the best jobs available in the Ruby community.
This episode is sponsored by Top Ruby Jobs

Rails 4 PostgreSQL Integration

One of the improvements in rails 4 was increased access to PostgreSQL features such as HSTORE, Arrays, and UUIDS as primary keys. If you haven’t had a chance to dive into these features, Yousef Ourabi wrote up a great post walking you through how to use each of these.
 Rails 4 PostgreSQL Integration

Tips For Hiring Great Software Engineers

The folks at Plataformatec just published a blog post this week about tips for hiring great software developers. Check out this fantastic blog post for more specifics and even a candidate profile template to help you structure your interview.
Tips For Hiring Great Software Engineers

Ruby Love

If you haven’t been reading the RubyLove.io blog, you may want to take a visit. There’s four great articles on writing better Ruby. From Applying Design Patterns to Ruby, to Refactoring code, to using an Ask, Don’t tell policy with Ruby.
Ruby Love

What Your Conference Proposal Is Missing

Sarah Mei just published a blog post called What Your Conference Proposal Is Missing, which covers how to write a proposal, moving past the basics into some techniques you can use to boost your proposal to the top of the pile.
What Your Conference Proposal Is Missing

Crafting a Conference Talk

Once you’ve written your conference proposal (and been accepted!), you might be looking for advice on how to actually write your conference talk. Justin Searls just published a post called Crafting a Conference Talk, which details the process he uses when developing a new talk.
Crafting a Conference Talk

An Introduction to JSON Schema

This week on the CodeMancers blog, Kashyap wrote up a great post on using the json-schema gem, which , as you might imagine allows you to easily validate incoming JSON to ensure it’s formatted correctly, and if not, provide good error feedback.
An Introduction to JSON Schema

Build a Ruby Gem eBook

Brandon Hilkert let us know about an eBook he released last week called Build a Ruby Gem. It is 19 chapters, totaling 136 pages, and its content ranges from how to get started with open source projects to the nitty gritty of configuration patterns in a Ruby gem.
Build a Ruby Gem eBook

Surviving APIs with Rails

Last week here at Code School we released our Surviving APIs with Rails course, taught by Carlos Souza. In the course he’ll teach you how to build and test REST APIs with Rails.
Surviving APIs with Rails

Back to Basics: Writing Unit Tests First

Posted 4 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

The value of unit tests and TDD are well documented. Unfortunately, it's still daunting to start practicing it. Here's a primer.

Our desired code

We need to write a method that:

  • takes a string as an argument
  • reverses the string
  • saves the string to a file on the hard drive
  • returns the reversed string

Our tool and techniques

We'll use RSpec to test our method's output. We'll use red/green/refactor methodology. We'll write unit tests that are fast, isolated, repeatable, self-verifying, and timely.

Starting with desired end state

What's a good first test we can write? We know that given a particular input (a string "example string") should product a given output (the string "gnirts elpmaxe"):

describe StringChanger do
  it 'reverses strings' do
    string_changer = StringChanger.new

    reversed_string = string_changer.reverse_and_save('example string')

    expect(reversed_string).to eq 'gnirts elpmaxe'
  end
end

Now let's run our test. We'll use the documentation format, which is more verbose, but for the sake of this example will give us more information about the tests:

% rspec string\_mixer\_upper\_spec.rb --format documentation

We get the following output:

string\_mixer\_upper\_spec.rb:3:in `<top (required)>':
uninitialized constant StringChanger (NameError)

The test is telling us to create a StringChanger class. Let's write it:

class StringChanger
end

When we run our test, we get this output:

StringChanger
  reverses strings (FAILED - 1)

Failures:

  1) StringChanger reverses strings
     Failure/Error: reversed_string = string_changer.reverse_and_save('example string')
     NoMethodError:
       undefined method `reverse\_and\_capitalize'
       for #<StringChanger:0x007fafe5c66ff0>
     # ./string_mixer_upper_spec.rb:8:in `block (2 levels) in <top (required)>'

Finished in 0.00032 seconds
1 example, 1 failure

Failed examples:

rspec ./string\_mixer\_upper\_spec.rb:5 # StringReverAndSave reverses strings

Our test is telling us we need to write a method called reverse_and_save. Let's write it:

class StringChanger
  def reverse_and_save(string_to_reverse)
  end
end

We run our test again:

StringChanger
  reverses strings (FAILED - 1)

Failures:

  1) StringChanger reverses strings
     Failure/Error: expect(reversed_string).to eq 'gnirts elpmaxe'

       expected: "gnirts elpmaxe"
            got: nil

       (compared using ==)
     # ./string_mixer_upper_spec.rb:10:in `block (2 levels) in <top (required)>'

Finished in 0.00301 seconds
1 example, 1 failure

Failed examples:

rspec ./string\_mixer\_upper\_spec.rb:5 # StringChanger reverses strings

The simplest thing that could work

Our test is telling us our method's logic does match expectations. Let's make it pass:

class StringChanger
  def reverse_and_save(string_to_reverse)
    'gnirts elpmaxe'
  end
end

We run our test:

StringChanger
  reverses strings

Finished in 0.00079 seconds
1 example, 0 failures

Refactoring

We have a passing test, but there is a smell we can refactor out. Currently we are returning a hardcoded value. This obviously will not work. Let's do a little refactor and then depend on our tests to tell us if things are still good:

class StringChanger
  def reverse_and_save(string_to_reverse)
    string_to_reverse.reverse
  end
end

We run our test:

StringChanger
  reverses strings

Finished in 0.00079 seconds
1 example, 0 failures

Our test still passes but our method is not fully functional until we write our reversed string to a file.

Stubbing dependencies such as the file system

We're writing a unit test, which should be isolated. We don't want to create a new file every time we run our test, so we stub it out.

The RSpec Mocks library gives us the ability to send the stub message to an object and replace the method we're stubbing with a dummy method that doesn't do anything:

it 'saves string to the file system' do
  string_changer = StringChanger.new
  File.stub(:write)

  string_changer.reverse_and_save('example string')

  expect(File).
    to have_received(:write).
    with('example_file', 'gnirts elpmaxe').
    once
end

We expect the File object to receive the message write one time with the arguments 'example_file' and our reversed string by using the stub's ability to report on the messages it's received. This is called white-box testing.

We run our test:

StringChanger
  reverses strings
  saves string to the file system (FAILED - 1)

Failures:

  1) StringChanger saves string to the file system
     Failure/Error: expect(File).to have_received(:write).with('example_file', 'gnirts elpmaxe').once
       (<File (class)>).write("example_file", "gnirts elpmaxe")
           expected: 1 time with arguments: ("example_file", "gnirts elpmaxe")
           received: 0 times with arguments: ("example_file", "gnirts elpmaxe")
     # ./string_mixer_upper_spec.rb:19:in `block (2 levels) in <top (required)>'

Finished in 0.00106 seconds
2 examples, 1 failure

Failed examples:

rspec ./string\_mixer\_upper\_spec.rb:13 # StringChanger saves string to the file system

Our test is telling us to invoke the File object's write method. Let's write it:

class StringChanger
  def reverse_and_save(string_to_reverse)
    File.write('example_file', string_to_reverse.reverse)
  end
end

We run our test:

StringChanger
  reverses strings (FAILED - 1)
  saves string to the file system

Failures:

  1) StringChanger reverses strings
     Failure/Error: expect(reversed_string).to eq 'gnirts elpmaxe'

       expected: "gnirts elpmaxe"
            got: 14

       (compared using ==)
     # ./string_mixer_upper_spec.rb:10:in `block (2 levels) in <top (required)>'

Finished in 0.00136 seconds
2 examples, 1 failure

Failed examples:

rspec ./string\_mixer\_upper\_spec.rb:5 # StringChanger reverses strings

We made our new test pass but broke our old test because we are no longer returning the reversed string. This shows the benefit of old tests helping guard against regressions in our code.

Let's fix our original test:

class StringChanger
  def reverse_and_save(string_to_reverse)
    string_to_reverse.reverse.tap do |reversed_string|
      File.write('example_file', reversed_string)
    end
  end
end

We run our test:

StringChanger
  reverses strings
  saves string to the file system

Finished in 0.0011 seconds
2 examples, 0 failures

We now have two passing tests and a fully functional method. We did it writing the tests first. This is a simple example, but by following this process, we can conquer any sized programming task. Writing the tests first will also help us write testable code and help us keep our methods small.

What's next?

If you found this useful, you might also enjoy:

How to get an A+ on the Qualsys SSL Labs test

Posted 4 months back at mir.aculo.us - Home

Recently we upgraded our server infrastructure for Freckle Time Tracking and in the process wanted to improve how we serve SSL.

If you don’t know much about this, it’s fine—there’s a few simple steps you can take to make your website more secure and faster loading in the process. _Important: of course, there’s no absolute security, and I make no claim that what I describe here is secure and will work for you. Use it at your own risk._

Long story short, you’ll want to get an A+ rating on the Qualsys SSL Labs test.

For that you’ll need to do the following:

  • Don’t support older protocols. A lot of servers support really old and obsolete protocols. If you run a web app, your users will very likely not need support for these.
  • Don’t support flawed SSL ciphers. There’s a bunch of these and you can avoid using them. Browsers support multiple different ciphers, so this is not a problem.
  • Cache SSL sessions. This will improve performance.
  • Turn on HTTP Strict Transport Security (HSTS). This is a special header that will tell browsers to never connect to the server via normal HTTP.

And that’s it. In order so you don’t need to research the proper settings, here’s how this looks like in form of an nginx configuration:

server {
  # deferred allows for faster connections if there's
  # no other servers on port 443 defined
  listen 443 ssl spdy deferred;

  ssl on;
  ssl_certificate /etc/nginx/your-certificate.crt;
  ssl_certificate_key /etc/nginx/your-private-key.key;

  ssl_prefer_server_ciphers on;
  ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS:!AES256;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;
  ssl_stapling on;

  # tell any upstream things like unicorns that we're on https
  proxy_set_header X-Forwarded-Proto 'https';
  underscores_in_headers on;

  location / {
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    # ...
  }

  # ...
}

And that’s it. Have fun with your new A+ rating on the SSL labs test.

Episode #453 – April 4th, 2014

Posted 4 months back at Ruby5

On today's episode, PDF generation options, some Ruby 2.1 garbage collection "discussion", CDN performance, an edge Rails treat, and a new book from Thoughtbot. Also, your intrepid hosts take their final bow.

Listen to this episode on Ruby5

Sponsored by New Relic

New Relic is _the_ all-in-one web performance analytics product. It lets you manage and monitor web application performance, from the browser down to the line of code. With Real User Monitoring, New Relic users can see browser response times by geographical location of the user, or by browser type.
This episode is sponsored by New Relic

PDF Generation in Rails

Joyce Echessa has a written a blog post that goes over how to use three PDF generation gems in Ruby: Prawn, PDFKit, and Wicked PDF.
PDF Generation in Rails

Ruby 2.1 Garbage Collection

Tim Robertson started a spirited conversation on the topic of garbage collection in Ruby 2.1 with this blog post on the Omniref blog.
Ruby 2.1 Garbage Collection

Mobile CDN Performance

Ilya Grigorik answers the question: Why is my CDN 'slow' for mobile clients? Spoiler: it is not.
Mobile CDN Performance

ActiveRecord::Enum

Edge Rails recently introduced Active Record enums for those columns that have a pre-defined set of values.
ActiveRecord::Enum

iOS on Rails

Thoughtbot are soon to pop with a new reference book titled, "iOS on Rails". You can get a discounted beta version now.
iOS on Rails

Removing Sass Duplication Using Sass Maps

Posted 4 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

Recently Dan asked me to get new icons for Raleigh, New York City, and Austin added to some of our landing pages.

Original Icons

Once I created the icons, I checked out the site to put them in below the offices that have already been on the marketing pages. It looked like this:

&#boston:after {
  background: url('/img/icon_boston.png') no-repeat center top;
}

&#denver:after {
  background: url('/img/icon_denver.png') no-repeat center 42px;
}

&#sanfran:after {
  background: url('/img/icon_sf.png') no-repeat center 54px;
}

&#philly:after {
  background: url('/img/icon_philly.png') no-repeat center 42px;
}

&#stockholm:after {
  background: url('/img/icon_stockholm.png') no-repeat center 45px;
}

@media
(-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {

  &#boston:after {
    background: url('/img/icon_boston@2x.png') no-repeat center top;
    background-size: 97px 112px;
  }

  &#denver:after {
    background: url('/img/icon_denver@2x.png') no-repeat center 42px;
    background-size: 160px 71px;
  }

  &#sanfran:after {
    background: url('/img/icon_sf@2x.png') no-repeat center 54px;
    background-size: 210px 59px;
  }

  &#philly:after {
    background: url('/img/icon_philly@2x.png') no-repeat center 42px;
    background-size: 66px 85px;
  }

  &#stockholm:after {
    background: url('/img/icon_stockholm@2x.png') no-repeat center 45px;
    background-size: 93px 67px;
  }
}

Look at all that repetition! That's almost 50 lines of Sass. Adding new offices to that list would add even more to the repetition. I wanted to get rid of all the repetition and make it really easy to add new offices if we need to in the future. I started off by putting all our offices in a variable then looped through them and used some interpolation to assign the right icon to the right city.

$offices: boston, denver, sanfran, philly, stockholm, new-york, raleigh, austin;

@each $city in $offices  {
  &##{$city}:after {
    background-image: url('/img/icon_#{$city}.png');
    background-position: center 42px;
    background-repeat: no-repeat;

    @if $city == 'boston' {
      background-position: center top;
    }

    @if $city == 'new-york' {
      background-position: center top;
    }

    @if $city == 'sanfran' {
      background-position: center 54px;
    }

    @if $city == 'austin' {
      background-position: center 24px;
    }

    @if $city == 'raleigh' {
      background-position: center 28px;
    }
  }

  @include hirez-screen {
    &##{$city}:after {
      background-image: url('/img/icon_#{$city}@2x.png');
      background-size: 97px 112px;
    }
  }
}

There's still some repetition in that loop with different positioning for each of the icons. Each of the cities that I am overriding the position is getting two lines of positioning when one will do. I figured that there had to be a better way to handle to the differing positions in Sass too.

Luckily for me, Sass 3.3 was released with Sass maps while I was designing the new icons. Connie suggested I try putting the offices into a map with their respective y-position. I went back to my list of offices and converted it to a map.

$offices: (boston: top, denver: 42px, sanfran: 54px, philly: 42px, stockholm: 42px, new-york: top, raleigh: 28px, austin: 24px);

Then went back to my @each loop and changed it around to account for the map.

@each $city, $y-position in $offices  {
  &##{$city}:after {
    background-image: url('/img/icon_#{$city}.png');
    background-position: center $y-position;
    background-repeat: no-repeat;
  }

  @include hirez-screen {
    &##{$city}:after {
      background-image: url('/img/icon_#{$city}@2x.png');
      background-size: 97px 112px;
    }
  }
}

Now we're talking. It's really compact and there's no repetition.

New Icons

What's new in edge Rails: Active Record enums

Posted 4 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

In an Active Record model, usually you will have a column that can only have a set of pre-defined values (such as a status column). Normally, you would define a constant for those values as well as several helper methods like the following example:

class Post < ActiveRecord::Base
  STATUS = %w(draft published)

  def draft?
    status == 'draft'
  end

  def published?
    status == 'published'
  end
end

In the upcoming Rails 4.1.0, the core team has added ActiveRecord::Enum support, which help clean up this type of attribute. With enum, you can rewrite the above code as:

class Post < ActiveRecord::Base
  enum status: %w(draft published)
end

With this single line of code, Rails will generate several helper methods for you:

# Query method
post.draft?
post.published?

# Action method
post.draft!
post.published!

# List of statuses and their corresponding values in the database.
Post.statuses

There is one gotcha which you might notice since this is called enum: you will need to update your database column to be an integer value. Rails will do implicit mapping between the integer value and the index of the value in the array automatically.

# Given that the `status` column has default value of '0'
post = Post.new
post.status # => "draft"

post.status = 'published'
post.published? # => true
post.save! # => UPDATE posts SET status = '1' WHERE id = '1'

If you are interested in trying out this feature, you can try it today on Rails 4.1.0.rc2. Be sure to read the documentation and release notes for more information. If you find any bugs, please do not forget to report them on Ruby on Rails GitHub issues.

Our Internet

Posted 4 months back at mir.aculo.us - Home

Our Internet isn’t big corporations doing whatever they want. Our Internet is not DRM, is not SOPA and not PIPA and not the spying on us (and everyone else). Our Internet isn’t bigots taking away human rights from people. Our Internet isn’t hiding being PR releases.

Our Internet isn’t greed, narcissism, fear and blind hate.

Our Internet is people helping each other be excellent. It’s sharing, caring and being proud of what we humans can do if we only put our will to it. It’s about helping the unprivileged when governments fail. Our Internet is about standing up to your mistakes.

Our Internet is about love and empathy.

The only thing we have is each other.

That is all.

Kestrel

Posted 4 months back at Mike Clark

Kestrel

This American Kestrel gave me a pose from atop one of his favorite hunting perches. The natural world has some amazing color palettes!

Giving Chase

Posted 4 months back at Mike Clark

Giving Chase

It's fairly late in the season to see bald eagles around here, but we'll enjoy it while it lasts. These juveniles were playing chase around the bay.

Episode #452 - March 28th, 2014

Posted 4 months back at Ruby5

Supersonic API stubbing with Mock5, visit tracking in your app with Ahoy, lexical analysis with lexeme, Rails 4.1.0 RC2, code ping pong with DHH, and 12 small ruby web frameworks all in this episode of the Ruby5!

Listen to this episode on Ruby5

Sponsored by New Relic

New Relic is _the_ all-in-one web performance analytics product. It lets you manage and monitor web application performance, from the browser down to the line of code. With Real User Monitoring, New Relic users can see browser response times by geographical location of the user, or by browser type.
This episode is sponsored by New Relic

Mock5

Tired of working around recorded API responses in your test suite? Need to stub out APIs in development with supersonic speed? Take a look at the mock5 gem from Rocketeer Pavel Pravosud!
Mock5

Ahoy

Simple, powerful visit tracking for Rails.
Ahoy

lexeme

Lexeme is a lexical analyzer written in Ruby. It lets you tokenize everything from mathmatical expressions to natural language with a simple API.
lexeme

Rails 4.1.0 Release Candidate 2

This is intended as the last stop before the final version of Rails 4.1.0 hits the virtual presses.
Rails 4.1.0 Release Candidate 2

Code Ping Pong with DHH

Submit your code. Get a response from DHH. Profit.
Code Ping Pong with DHH

12 Small Ruby Web Frameworks

You know about Rails and Sinatra, but had you heard of the menagerie of other Ruby web frameworks? This blog post takes you on a whirlwind tour of 12 of them!
12 Small Ruby Web Frameworks

Thread Safety With Ruby

Posted 4 months back at Luca Guidi - Home

Moore’s law is over. Modern computation is exploited by running processes on multiple cores. Ruby has always ignored this trend, and the community didn’t put enough attention on this topic.

Ruby’s model for concurrency is based on threads. It was typical approach for object oriented languages, designed in the 90s. A thread is sequence of instructions that can be scheduled and executed in the context of a process. Several threads can be running at the same time.

Ruby’s VM process allocates a memory heap, which is shared and writable by threads. If incorrectly coordinated, those threads can lead to unexpected behaviors.

Thread Safety

We define as thread safe a code that behaves correctly when accessed by many threads at the time. Most of the time, the correctness of execution is determined by the state of the memory that is visible by a routine in a given moment. For instance, a variable appears with a certain value, but in the meantime another thread may have changed it.

x = 0

10.times.map do |i|
  Thread.new do
    puts "before (#{ i }): #{ x }"
    x += 1
    puts "after (#{ i }): #{ x }"
  end
end.each(&:join)

puts "\ntotal: #{ x }"

What happens here? When the threads are starting they see the initial value of x. But when each of them, try to add +1, the value became different as result of the parallel computation. Without a proper synchronization, the partial state of x is unpredictable.

% ruby count.rb
before (2): 0
before (0): 0
before (1): 0
after (1): 3
before (5): 1
before (7): 1
after (2): 1
after (0): 2
before (4): 1
after (5): 4
after (7): 5
before (9): 1before (3): 1
before (8): 1
before (6): 1
after (4): 6

after (9): 10after (3): 7
after (6): 9

after (8): 8

total: 10

When the thread (3) started, x was equal to 1, but after adding +1 its value was 7.

Visibility

We met an important issue here: visibility. If the changes caused by a thread are observable by other threads, they can read the correct value, and then partial state is consistent.

Until now, we omitted an important aspect: which kind of variables are we referring to? We are talking about of all that represent a state of the system in a given moment. Global, class and instance variables require attention, when used in a concurrent context.

Local variables are exempt from these problems, because they don’t hold a state.

From this picture, we can infer that stateless programs are always thread safe.

Atomicity

Yet, stateful systems can be thread-safe. What’s important isn’t only what changes (_visibility_) but how it changes (_atomicity_). If we design write operations in a way that while they’re running, other threads can’t read nor alter the state we’re modifying, that change is thread safe.

We call these operations atomic, because their execution appear as indivisible to the rest of the system.

x, mutex = 0, Mutex.new

10.times.map do |i|
  Thread.new do
    mutex.synchronize do
      puts "before (#{ i }): #{ x }"
      x += 1
      puts "after (#{ i }): #{ x }"
    end
  end
end.each(&:join)

puts "\ntotal: #{ x }"
% ruby count.rb
before (2): 0
after (2): 1
before (1): 1
after (1): 2
before (0): 2
after (0): 3
before (5): 3
after (5): 4
before (6): 4
after (6): 5
before (8): 5
after (8): 6
before (9): 6
after (9): 7
before (3): 7
after (3): 8
before (4): 8
after (4): 9
before (7): 9
after (7): 10

total: 10

By using Mutex, we ensure the atomicity of the add operation.

The following example shows the weakness of a common pattern in Ruby applications: lazy loading via ||=.

##
# Counter is thread safe, we use a Mutex to guarantee the atomicity of #increment!
#
class Counter
  attr_reader :total

  def initialize
    puts 'initialized'
    @total = 0
    @mutex = Mutex.new
  end

  def increment!
    @mutex.synchronize { @total += 1 }
  end
end

##
# Application isn't thread safe, because the initialization of Counter
# happens with a non-atomic operation (`||=`).
#
class Application
  def increment!
    counter.increment!
  end

  def counter
    @counter ||= Counter.new
  end

  def total
    counter.total
  end
end

app = Application.new

10.times.map do |i|
  Thread.new do
    app.increment!
  end
end.each(&:join)

puts app.total
% ruby application.rb
initialized
initialized
1 # wrong

Please note that Counter is thread safe, but the final application isn’t. We have used ||=, which isn’t atomic. This caused a race condition: two threads have seen @counter as nil, and then they have initialized a new instance of it. The result of the computation is wrong.

The right way to write that class is:

class Application
  attr_reader :counter

  def initialize
    @counter = Counter.new
  end

  def increment!
    counter.increment!
  end

  def total
    counter.total
  end
end

As rule of thumb, avoid mutations after an object is being initialized.

Conclusion

In a nutshell, the limitations of Ruby concurrency model are: data mutability and difficult synchronization.

In an upcoming article, I’ll cover how Lotus achieves thread safety.