Posts tagged "ruby"

A Post Entitled Constant-ly?

posted 1 year ago in ruby

I’ve gone back and forth about what should constitute a good use of class-level constants and a recent project has brought this question up once again.  In this project there are basically two different uses for class-level constants.  The first, and less frequent, use of class-level constants serves to identify “magic values”.  The second use is to define a closed set of options.

Class Constants as Magic Values

“Magic values”, if you are not familiar with the term, are those values that require you to change the response of a class or class instance to a message. Usually you find them in flow control logic such as if-then or case statements.


class AtBat
  MAX_BALLS = 4
  MAX_STRIKES = 3

  attr_reader :pitches, :result, :strikes, :balls

  def initialize(first_pitch = nil)
    @balls = @strikes = 0
    @pitches = [ ]
    @result = nil
    add_pitch( first_pitch ) unless first_pitch.nil?
  end

  def add_pitch(pitch_result)
    @pitches ||= [ ]
    @pitches.push pitch_result

    case pitch_result
      when :foul
        add_strike if @strikes < MAX_STRIKES-1
      when :ball
        add_ball
      when :strike
        add_strike
      else
        @result = pitch_result
    end
  end

  def active?
    !@result.nil?
  end

  private
    def add_strike
      if active?
        @strikes += 1 
        @result = :strike_out if struck_out?
      end
    end

    def struck_out?
      @strikes == MAX_STRIKES
    end

    def add_ball
      if active?
        @balls += 1 
        @result = :walked if walked?
      end
    end

    def walked?
      @balls == MAX_BALLS
    end
end

In the code above the class-constants MAX_BALLS and MAX_STRIKES are magic values. They represent different “high water marks” for the AtBat class. Each instance should respond differently when a pitch is a ball and there are less than MAX_BALLS of them in the AtBat.

This is the best, and possibly only, justifiable use of class constants. Using constants in this case accomplishes two important objectives. First, it pulls the magic values into one place so that they can easily be maintained. If the rules of baseball changed to permit more balls or strikes in at bat you simple change the class-constant and you’re done. Second, the class constant is more expressive of the intent than the value. Why use “3” when evaluating the number of strikes? Because that’s the maximum allowed.

Class Constants as Closed Options

A special case of magic values is when the constant represents a closed set of options for the class. For example, consider when my favorite baseball team, the Boston Red Sox, conducts a contest during the season to give away a pair of tickets to a game and then does something I detest: they restrict entry to residents of the New England states. (Yes, I’m crazy enough to drive the thousand miles between my house and Fenway to see a game.)


class Entrant
  ELIGIBLE_STATES = %w{CT MA ME NH RI VT}
  attr_accessor :first_name, :last_name, :dob, :email, :street, :city, :state_abbrev

  def valid?
    new_england_resident? and over_18?
  end

  private
    def new_england_resident?
      ELIGIBLE_STATES.include? @state_abbrev
    end

    def over_18?
      @dob < 18.years.ago
    end
end

In the code above the ELIGIBLE_STATES constant is used as a special type of magic value. The instance reacts differently based on whether or not one of the attributes “matches” the constant. To that extent the closed option type of class constant makes some sense. It does often have an irritating side effect (constant redeclaration warnings when restarting a Rails application) but that’s the main downside.

More than Magic?

The problem that I have seen fairly often is that these class constants that begin as a closed set of options tend to evolve over time. The list of states shown above, for example, may take on an additional property for reporting purposes such as a state-specific tax rate for reporting the tickets as “income.”


class Entrant
  ELIGIBLE_STATES = {:CT=>0.07, :MA=>0.09, :ME=>0.07, :NH=>0.0, :RI=>0.07 :VT=>0.09}
  attr_accessor :first_name, :last_name, :dob, :email, :street, :city, :state_abbrev

  def valid?
    new_england_resident? and over_18?
  end

  def extended_ticket_value( ticket_price, qty )
    qty * ticket_price * (1 + ELIGIBLE_STATES[@state_abbrev.to_sym])
  end

  private
    def new_england_resident?
      ELIGIBLE_STATES.include? @state_abbrev
    end

    def over_18?
      @dob < 18.years.ago
    end
end

Before you know it there are new “constants” springing up to deal with other flow control changes related to the first constant. Tax rates, shipping charges, and who knows what else might change based on the state of residence for the Entrant. This is where the problem lies. Because the needs emerged slowly they feel like a simple, organic extension of the class. But they’re not.

They are classes in and of themselves.

These classes are not constants in the traditional, magic value sense. They are classes with constant data. That is, they are classes whose data is set and known at the time the software is developed. Just like other classes, they deserve their own class body.


class State
  NEW_ENGLAND_STATES = %w{CT MA ME NH RI VT}
  attr_reader :state_abbrev, :tax_rate, :shipping_charge

  def initialize(state_abbrev, tax_rate, shipping_charge)
    @state_abbrev, @tax_rate, @shipping_charge = state_abbrev, tax_rate, shipping_charge
  end

  def new_england?
    NEW_ENGLAND_STATES.include? @state_abbrev
  end

  def find_by_abbrev( abbrev )
    @@states.detect{|state| state.state_abbrev == abbrev}
  end

  @@states = {
    new(:CT, 0.07, 1.50),
    new(:MA, 0.09, 0.50),
    new(:ME, 0.07, 1.75),
    new(:NH, 0.00, 1.75),
    new(:RI, 0.07, 0.75),
    new(:VT, 0.09, 2.50),
    new(:SC, 0.07, 4.00)
  }
end

class Entrant
  attr_accessor :first_name, :last_name, :dob, :email, :street, :city, :state_abbrev

  def valid?
    new_england_resident? and over_18?
  end

  def extended_ticket_value( ticket_price, qty )
    qty * ticket_price * (1 + state_of_residence.tax_rate)
  end

  private
    def new_england_resident?
      state_of_residence.new_england?
    end

    def state_of_residence
      State.find_by_abbrev( @state_abbrev )
    end

    def over_18?
      @dob < 18.years.ago
    end
end

By pulling this class of constant data out as a unique class we gain similar advantages to the use of constants as magic values. The class now encapsulates all the knowledge about how to deal with a particular state and properly separates those concerns from how to deal with an Entrant. The Entrant code is even more expressive of its intent (e.g., state_of_residence.tax_rate vis-a-vis ELIGIBLE_STATES[@state_abbrev.to_sym]).

Admittedly, something very similar to this could be accomplished with a database-backed class like an ActiveRecord or MongoMapper derived class. The constant nature of the data, however, always makes that feel a little improper even if the end user has no access to the maintenance function. In the back of my mind I always worry that a necessary record will be inadvertently dropped so I want to ‘freeze’ it in code.

What about you? How do you deal with these kinds of classes of constant data? Do you recognize them up front? Shuttle them off to the database?

A Post Entitled What’s in a name? Inject-ing your code

posted 2 years ago in ruby inject

thoughts.inject(world)?

If you’re new to Ruby you may not realize that the title to the blog is an ode to one of my favorite Ruby idioms: inject. In a nutshell, inject is a customizable accumulator that Ruby mixes into collections through the Enumerable module (e.g., arrays and hashes).

Anatomy of an inject-ion

inject essentially has four parts: a collection to be iterated, a seed value, an accumulator, and a block used to ‘accumulate’ the members of the collection. In practice it looks something like this:


collection.inject( seed_value ) do |accumulated_value, collection_member|
  accumulated_value.modify_by collection_member
end

Given that structure, here’s what happens

  1. accumulated_value is initialized with seed_value.
  2. accumulated_value and the first (second, third, …) value of the collection is passed to the block.
  3. The result of executing the block — the value returned by the last statement — is assigned to accumulated_value.
  4. Repeat the previous two steps for every element of the collection.
  5. Return the last value assigned to accumulated_value.

A simple example

The simplest, and probably canonical example, of using inject is to sum the values of an array.


[1, 2, 3, 4, 5].inject( 0 ) do | total, value|
  total + value
end

Just to be thoroughly pedantic, let’s step through what’s going on here based on the explanation above. First, total is assigned the seed value of 0. Next, 0 and the first value of the array (1) is passed to the block and the block evaluates total + value (0 + 1) and assigns it to total. The next iteration passes that total (1) and the next value (2), performs the addition, and assigns 2+1=3 to total. And so on.

Now, if you’re using Ruby to build a database-backed application this might seem to be a bit of a waste. You can and should delegate simple sums like this to the database and avoid the cost of returning the values, instantiating classes, and then reading the attributes you want to sum. Databases live for that. Let them.

A more practical example

In one app that I support we were discussing how to bill customers. Stunning as it may be, that was a reasonably important issue for us so we wanted to get it right. The application primarily provides member management support and billing is tied to the population of members. The catch was that, at the current moment, both the member and the membership could be made inactive. I’m sure that there’s a sql guy out there who’s already got nested selects in mind but our app need only bill one time per month so we can afford to be a little less than optimal here. Inject to the rescue.


customer.memberships.inject(0) do |total, membership|
  membership.expired? ? total : total + membership.members.active.count
end

So, what’s going on? It’s really not that much more complicated than the sum example above. As before we initialize the count with 0. Next, we check each membership. If the membership has expired then we just return the previously calculated total. If not, we add the number of active members on the membership to the previously calculated total.

But wait, there’s more!

There are two great things about inject that should not be overlooked. First, the accumulator can accumulate in any way you want. That means you can use it to transform data as well. For example, we could test to see how random random really is by checking to see how well it distributes numbers by using inject.


numbers = []
1000.times{ numbers.push rand(4) }
numbers.inject( Hash.new(0) ){|frequencies, num| frequencies.merge num => frequencies[num]+1}
=> {0=>254, 1=>249, 2=>248, 3=>249}

Furthermore, since inject is a method that gets mixed in from the Enumerable module that means you can use it far more widely than just arrays. Hashes, strings, ranges… you name it. Anything that uses Enumerable can take advantage of inject. Taking a variation on the number frequency above, what about finding the average length of a ‘line’ in a string?


str = "The quick\nbrown fox jumped\nover the lazy\ndog."
str.inject( Hash.new(0) ) do |lengths, line| 
  len = line.split(/\s+/).size
  lengths.merge len=>lengths[len]+1
end

=> {1=>1, 2=>1, 3=>2}

A Post Entitled Fixing the Broken Pipes

posted 3 years ago in ruby gems

Why do we need the plumber?

If you’re like me you might slip into a comfort zone and not keep up with all the updates to gems and plugins, especially since github has taken plugin/gem development and forking viral. Usually that’s not much of a problem. Unless, of course, the change is to the gem package manager itself.

I’m not sure exactly what changed. What I know is that any time I tried to do a ‘(sudo) gem install my-cool-gem’ it failed with an error that looked like this


Bulk updating Gem source index for: http://gems.rubyforge.org/
Bulk updating Gem source index for: http://gems.github.org/
ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError)
     Errno::EPIPE: Broken pipe reading http://gems.rubyforge.org/gems/...some-poor-gem.gem

As best as google has been able to help me find the problem lay in the the increasingly large number of gems available. The large, uncompressed source of gems times out the connection. Fortunately that appears to be fixed in the latest version of rubygems. Version 1.3.0 was released yesterday. But now you’ve got a chicken-and-egg problem if you have relied on gems to update itself — the Broken Pipe problem prevents you from getting the version that doesn’t have the Broken Pipe problem.

Installing the gem locally

The simple answer to the question is to install the gem from a local source rather than a remote source. It works the same as the tried and true “gem install my-cool-gem” with just one extra step. Here’s what I did specifically to fix the issue with the gem package manager.

  1. Navigate over to the rubygems download page at rubyforge.
  2. Download the latest rubygems-update gem (currently rubygems-update-1.3.0.gem)
  3. Move the gem somewhere handy in case you want to install it again.
    Personally I created a Gems subfolder and moved the gem from ~/Desktop to ~/Gems.
  4. Install the gem locally using a locally named source:
    sudo gem install rubygems-update -n ~/Gems
  5. Once the gem update is installed you still have one more step! (Emphasis for my own needs — I keep forgetting this). From the command line:
    update_rubygems

Once I updated to rubygems v 1.3.0 the Broken Pipe Problem disappeared on my Ubuntu box. Hope the same is true for you!

A Post Entitled If it quacks like a duck…

posted 4 years ago in ruby respond_to

If it quacks like a duck…

duck-typing is the Way of Ruby and Rails programming. The phrase attributed to James Whitcomb Riley refers to the preference in Ruby and Rails to be concerned with what an object does (methods and attributes) rather than what an object is (it’s class). That makes a lot of sense from a modeling perspective. We create classes as representations of like things, but we really deal with them in terms of the way we get to the distinguishing attributes and the kinds of things that it can do because it is a member of that group.

It makes even more sense from a Rails perspective. One of the great mantras of Rails programming is the DRY principle: Don’t Repeat Yourself. A primary means of not repeating yourself is to capture reusable functionality in modules and mix those modules into the classes that need to be able to do those kinds of things. Modules are, first and foremost, abstractly written collections of methods… ways of describing how a duck quacks…

Duck typing is more than just an interface implementation. In most static languages the emphasis is on grabbing a particular interface on an object and then making use of that interface as a contract for interaction. With duck typing you really could not care less whether or not you have an interface. You really only care about whether or not the duck can quack. So you ask it:

duck.respond_to?(:quack)

How I learned to love ducks

Okay, so all the duck typing talk may be old hat to you by now. No matter. It was old hat to me, too. I just forgot to do it. Call it old habits dying hard but my code was littered with type-checking.

A particularly bad area of my largest application is designed to allow the end user to set up their own business processes. The code is full of subclasses that each perform one business function and the user hooks them up to design their larger processes. Where it begins to suffer is from the “all roads lead to Rome” problem. For our customers there is a central object with which they deal, but different users will typically get a handle on it through a different association. Rather than force the user to navigate up the object graph we decided to let the process step do the navigation for them. Falling back on old habits I’d have code looking like this

def apply(target_object, attributes={})
  case
    when target_object.is_a?(Widget)
      return target_object.foo.bar! attributes
    when target_object.is_a?(Cog)
      return target_object.foo.bar! attributes
    when target_object.is_a?(Foo)
      return target_object.bar! attributes
  end
  raise(ArgumentError, "No, foo on you!") 
end

The basic idea is to call the bar! method on a Foo class object, but allow the user to apply the process in any context that knows how to navigate up to the Foo class object (including a Foo instance itself). Obviously the repetition was screaming for some refactoring. Enter duck typing.

def apply(target_object,  attributes)
  foo = target_object.respond_to?(:foo) ? target_object.foo : target_object
  raise(ArgumentError, "Duck foo on you") unless foo.respond_to?("bar!")
  foo.bar! attributes
end

Duck typing brings a lot of advantages to that code. Obviously it eliminates the repetition. An important corollary is that it reduces the code base so there is less to maintain and less to break. Duck typing in this scenario also decouples the method from the classes that might need to use it. This is important in two regards. First, it means that I can eliminate one of those classes like the Widget class and not have to modify all the places that refer to the Widget class to eliminate ‘undefined constant’ errors. Second, it means that I can now introduce new objects that have a handle on the Foo class and automatically gain the ability to use this process step without modification. A less obvious point is that the code now fails more quickly if it’s passed a target object that doesn’t know Foo; it does not have to wait until all the branches of the case statement fail.

In my opinion, the nicest part of the duck-typing focused refactoring is that it makes the intentions of the method much clearer. Like a really good joke or a really bad pun, the punch is in the final line. What’s the objective? To call ‘bar!’ with the appropriate attributes on a Foo instance.

A Post Entitled Static thinking about a dynamic language

posted 4 years ago in ruby contains 1 note

Static thinking about a dynamic language

If you’ve approached Ruby from a background in programming with static (compiled) languages it’s easy to get a lot of “static” in your thinking about Ruby. One of the most common places to lose sight of t dynamic nature of the Ruby language is in class definitions. A class definition is really a call to a method in Kernel that creates a global constant with a reference to the object that represents the class, but Ruby has so faithfully repeated the class-definition language of static languages that we forget that we’re actually executing code.

Who cares if class definitions are dynamic?

The dynamic nature of class definitions in Ruby can be a big deal if you take advantage of it. Mike Clark points out a nice use of the dynamic nature of Ruby in the forthcoming Advanced Rails Recipes. The basic scenario is that you’ve got an ActiveRecord model that contains data that is primarily intended to be constant for the life of the application — something like a table of states and provinces (so Clark) or menu items. Rather than look for performance improvements through caching, you could instead create a constant array on the ActiveRecord class that is populated as the class is created.

class MenuItem < ActiveRecord::Base
  MENUS = { :start_menu=>1, ... }
  START_MENU_ITEMS = find(:all, :order=>"position, name", :conditions=>{:menu_id=>MENUS[:start_menu]})
end

The MenuItem class above has already inherited the class-level find() method from ActiveRecord::Base we we make use of it during the class creation process. By doing this the constant data stays in memory and need not be cached. Of course, care should be taken to make sure that the amount of data stored in this constant array is not so large as to reduce performance elsewhere.

The dynamic nature of Ruby class definitions can also help to keep your class-definitions DRY. I’ve recently been working on a project in which a Person may have many Addresses. Simple enough. But the Addresses need to be subclassed, using single table inheritance, so that I can distinguish a home address from a work address. Oh, yeah, the Addresses also have a date range associated with them so that we can track when you plan on moving to a new Address, which in turn leads me to a need to know the current home address and work address and … This could get very messy. But it’s not if we take advantage of the dynamic nature of Ruby.

class Address &lt; ActiveRecord::Base
  self.inheritance_column = 'address_type'
  ADDRESS_TYPES = %w(HomeAddress WorkAddress SchoolAddress TemporaryAddress)
  belongs_to  :addressable, :polymorphic=&gt;true
end

Address::ADDRESS_TYPES.each do |address_type| 
  eval "class #{address_type} &lt; Address; end"
end

class Person < ActiveRecord::Base
  has_many  :addresses, :as=&gt;:addressable
  Address.subclass_names.each do |address_type| 
    self.send(:has_one, "current_#{address_type.underscore}", 
                      :as=&gt;:addressable, 
                      :class_name =&gt; address_type,
                      :conditions=&gt;['activated_on &lt;= ? AND deactivated_on IS NULL OR deactivated_on&gt;?', Date.today, Date.today])
  end
end

In the code above I’m actually taking advantage of Ruby’s dynamics twice. In lines 7-9 I’m iterating through each of the ADDRESS_TYPES declared in the Address class above and declaring a new subclass for each entry in the array. This may not work in every situation; certainly in most instances of subclassing you’ll want to add code to the subclass. It works here, though, because the subclass name will be used in rendering (e.g., putting a nice home or work image next to the address with css).

Lines 14-18 is where I’ve used the dynamic nature of Ruby class declarations to keep things DRY. The Address.subclass_names method simply iterates over the subclassess of Address and returns an array of the names. This might seem overkill since ADDRESS_TYPES already has this information but it will allow me to know if classes are created in some way other than through the loop in lines 7-9. That said, lines 14-18 simply iterate over all the names of the subclasses and creates an association between person and one member of the addresses collection. Specifically, it creates an Address#current_home_address for the HomeAddress class and so on.

Loading...

Comments

About this site and its Author


The Tumblrs to Follow

  • staff
  • cdmwebs
  • paulsullivanjr
  • dawnvanasse
  • bitbltr