RoR, Learning Ruby the Wrong Way

Posted by ryan
at 10:20 AM on Monday, October 31, 2005

Like most people that have recently jumped on the Ruby on Rails bandwagon (or at least given it a try), one of the first things I did was read the Ruby on Rails book and jump into developing my own web app. Well, here I am a few months later looking at my initial version of the app – and I am completely disappointed. The code is crap – it’s inelegant, somewhat procedural and completely un Ruby-like. And I blame it all on Ruby on Rails.

You see, in my rush to stay with the hype I’ve jumped into Ruby on Rails without spending due time learning Ruby. I suspect many people have done the same thing and what you will begin to see is a dilution of the talent in the Ruby community as more people come into the language the wrong way – through RoR.

It’s not a bad thing that Ruby on Rails has brought exposure to Ruby, but it’s obscuring the language itself which is unfortunate. In an attempt to rectify my mis-education I have taken a step back and am starting to explore the language before proceeding on with more RoR. Until developing with Ruby becomes intuitive to me I shouldn’t be working w/ RoR. I mean how many people successfully learn Java by learning Struts first?

My hope is that I am amongst the minority, but I suspect there are others who have made the same mistake as I have.

Book Review: "The Ruby Way" by Hal Fulton

Posted by ryan
at 9:34 PM on Sunday, October 09, 2005

If you’ve ever bought a learning ruby book, there’s a good chance it was the “pickaxe book” – Dave Thomas’ “Programming Ruby: The Pragmatic Programmers’ Guide”. I’ve read it myself and it is as billed, an excellent book to learn Ruby from.

However, I’m actually finding that Hal Fulton’s book, The Ruby Way is a better read for me. I’m coming from Java and while the Pragmatic book will set you on your way to learning the ruby syntax and some idioms, it doesn’t do much more than that. I need to see how to use Ruby, concrete examples of common problems and how to solve them. I have no doubt that this need stems from my own ignorance and not on the lack of merit of the pragmatic book, but it has been my experience none-the-less. So, if you’re pining for more Ruby lovin’ after reading the pragmatic guide, give the Ruby Way a try, it may be the book that fills that void in your life.

Continuous Integration for Ruby

Posted by ryan
at 9:10 AM on Tuesday, March 13, 2007

If this had you running for the hills it appears that there’s now a better ruby-based option for continuous integration with your Rails project: CruiseControl.rb. (And it’s not just for Ruby/Rails projects either…)

Give it a go, eh?

tags: rubyonrails, rails, continuous integration

REST & ActiveResource

Posted by ryan
at 10:09 AM on Wednesday, March 14, 2007

See here from some syntactical changes that occurred after this post was published

I gave a little chat last night at the Central Virginia Ruby Enthusiast’s Group – otherwise known as the Richmond Ruby Brigade – about REST, ActiveResource and how to build client services from the marriage of the two.

It was a really good group and I’d encourage anybody in the central virginia area to go check them out if they get the chance. It sounds like they’ve got some good speakers lined up in the next few meetings to make it worth your while (and they had free pizza last night – what a grade-A operation!)

For those that are interested, here’s the PDF version of my presentation. As you can imagine much of the value is lost without having the dialogue to accompany the presentation, but I think it somewhat stands on its own. Most of the examples are drawn from my ongoing work on ContactsAPI – a site meant to further the adoption and education of ActiveResource and REST in general. Check it out if you have the time, but again, it’s a work in progress.

tags: ruby, rubyonrails, cvreg

Ruby Hoedown - The South's Ruby Conf

Posted by ryan
at 11:09 AM on Thursday, March 22, 2007

Everybody knows that here in the South all we do is sit on the porch in our rocking chairs, chew, and have hoedowns, right? In that spirit Ruby aficionados across the south now have their own such festivity – The 2007 Ruby Hoedown in Raleigh, NC from August 10th – 11th. SIgn up to be notified of further details…

tags: ruby, rubyhoedown

Get Involved in the 2007 Ruby Hoedown

Posted by ryan
at 2:58 PM on Tuesday, April 03, 2007

It’s official, the 2007 Ruby Hoedown is in full swing now. The venue and dates are set and we’ve already made our call for proposals. Now starts the heavy lifting – heavy lifting best shared amongst the community. If you’re the philanthropic type, or even if you’re not, we’d love for you to volunteer to review the proposals we’ll be getting for the conference. Besides contributing to a worthy cause, members of the program committee will get free registration to the event as well.

So, if you’re interested in helping us review the many worthy proposals that will begin filtering in shortly, drop me a line at proposals [at] rubyhoedown.com. Thanks in advance!

Now That RailsConf is Over, It's Time for the Hoedown

Posted by ryan
at 11:17 AM on Wednesday, May 23, 2007

For all of you that were swamped with stuff prepping for RailsConf, it’s time to shift your focus to the 2007 Ruby Hoedown. Did you present at RailsConf and think it might be appropriate for a Ruby (not Rails) conference? If so, submit your proposal to us by June 2nd and we’ll take a look. Did RailsConf get your intellectual juices flowing? What better way to flex that new intellectual muscle than with a presentation at the Hoedown? You’ve got about a week left to make it happen!

Really want to set the mood? Then have a listen to our 2007 Ruby Hoedown Ad. (not my voice, by the way)

rubyonrails, rubyhoedown, railsconf2007

And Then There Was One

Posted by ryan
at 2:30 PM on Wednesday, September 05, 2007

About four months ago I took a leap of faith and decided to join the rest of you who enjoy the flexibility of self-employment and the ability to work with the technology you actually enjoy and went out on my own. Y|Factorial, LLC was born after a lot of thought about where I was, where I wanted to go and what I want to do – and the answer was to create my own Ruby software development shop.

I definitely have very strong feelings about what Y|Factorial stands for, how it goes about its business and how it will manage its employees. Much of it is still a work in progress, but it’s my intent to be as painfully transparent about this maturation process as possible over on The Naked Company blog. I’m sure I’ll make a few mistakes, fall on my face a few times, and even anger some – but the hope is that, overall, it will be of some benefit.

So, take a peek, laugh at my naivety and maybe even drop me a line if you’re looking for development help.

Cheers.

tags: Y Factorial, ruby, rubyonrails

Roxy: A Ruby Proxy-Object Library

Posted by ryan
at 4:27 PM on Monday, November 10, 2008

Proxies are a powerful tool in software development, allowing you to transparently provide extra functionality or a slight abstraction to an underlying object. One of the more visible uses of proxies is in ActiveRecord which uses a proxy to represent its many associations. For instance, in the following article definition:

1
2
3
class Article < ActiveRecord::Base
  has_many :comments
end

when you call article.comments what you get back is actually a proxy object that wraps the comments collection with some extra functionality like the << and build methods. Although it looks like a normal Array when you directly access comments, it’s really a proxy that’s marshaling method calls to an underlying collection or intercepting the method calls if it’s functionality it wants to handle itself. Named scopes also work in a similar manner.

That’s great and all, but these proxies are tied very specifically to their implementations within ActiveRecord .. and that’s what Roxy is intended to address. Roxy brings some serious moxie to your development with the ability to easily define and use proxies in your non ActiveRecord classes.

Let’s take a look at an example: Suppose I have a person object that has a list of parents and children (again, this is outside the scope of ActiveRecord or any other persistence framework where you might be able to do this with some other mechanism).

1
2
3
class Person
  attr_accessor :first, :last, :parents, :children
end

If you want add functionality to a person that determines if their parents are divorced, or if they have any stepchildren you could easily enough add that functionality directly to the Person object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person
  attr_accessor :first, :last, :parents, :children
  
  def initialize(first, last)
    @first, @last = first, last
  end

  # If my parents have different last names, then assume they're divorced
  def parents_divorced?
      parents.size > 1 and parents.collect { |parent| parent.last }.uniq.size > 1
  end

  # Any child with a different last name than mine is considered
  # a step-child.
  def step_children
    children.select { |child| self.last != child.last }
  end
end

but this approach has always seemed very obtuse, however. If I am strictly modeling my domain to the real world, which is the approach I favor until it becomes unwieldy to do so, what I really want to do is ask a person’s parents if they’re divorced. After all, their divorce status is a property of the parents, not the person itself. With Roxy this structure is easy to model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
require 'roxy'
class Person

  # Add in proxy ability
  include Roxy::Moxie

  attr_accessor :first, :last, :parents, :children
  
  # Add ability to ask the parents collection if they are divorced
  proxy :parents do    
    def divorced?
      proxy_target.size > 1 and
        proxy_target.collect { |parent| parent.last }.uniq.size > 1
    end
  end
  
  # Add ability to ask the children collection for only the step-children
  proxy :children do
    def step
      proxy_target.select { |child| proxy_owner.last != child.last }
    end    
  end    
  
  def initialize(first, last)
    @first, @last = first, last
  end
end

# Now the following is possible:
person.parents.divorced? #=> true|false
person.children.step #=> [<Person...>, <Person...>]

Roxy allows you transparently adorn existing attributes and methods with added functionality, making a more realistic domain model. This is very similar to rails’ association proxies except that you are now free to add functionality to all methods and objects.

Proxy methods are defined in the block that is passed to the proxy call. Within each proxy method you can reference the object that owns the proxy (the person instance here) as proxy_owner and the thing that is being proxied (the parents and children collections here) as proxy_target.

Advanced

You’re not limited to proxying existing methods, you can just as easily proxy to another object using the :to option.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require 'roxy'
class Person

  # Add in proxy ability
  include Roxy::Moxie

  attr_accessor :address

  proxy :shipping, :to => ShippingMethod.all do
    def cheapest
      proxy_target.min { |m| m.cost_from(proxy_owner.address) }
    end
  end
end

# Find the cheapest shipping method from all methods
person.shipping.cheapest #=> <ShippingMethod...>

If the value you want to proxy needs to be evaluated at runtime just pass in a proc. The proc should accept a single argument which will be the proxy_owner instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'roxy'
class Person

  # Add in proxy ability
  include Roxy::Moxie

  attr_accessor :address

  proxy :shipping, :to => proc { |person| ShippingMethod.available_for(person) } do
    def cheapest
      proxy_target.min { |m| m.cost_from(proxy_owner.address) }
    end
  end
end

# Find the cheapest shipping method from the methods
# only available to 'person'
person.shipping.cheapest #=> <ShippingMethod...>

You’ll notice that the best use of proxies is as a lightweight relationship between two things. I.e. instead of creating a whole other object to represent the relationship between a person and the various shipping methods you can quickly add functionality directly to that object-relationship as a proxy method.

A sign of abuse of this particular proxy pattern is when you reference only one of the proxy_owner or proxy_target and neither depends on the other in any way. That is usually an indication that the functionality should live solely in the referenced proxy owner/target and not in the proxy itself.

Proxy methods can also be defined as modules (as in Rails’ association extensions) for greater re-use between similar proxies with the :extend option (which can take one or more modules):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
require 'roxy'
class Person

  # Add in proxy ability
  include Roxy::Moxie

  attr_accessor :age, :children, :parents

  # Re-usable functionality to find the oldest person in a collection
  module PersonCollection
    def oldest
      proxy_target.max { |p| p.age }
    end
  end

  proxy :children, :extend => PersonCollection
  proxy :parents, :extend => PersonCollection

end

# Now the following is possible:
person.parents.oldest #=> <Person...>
person.children.oldest #=> <Person...>

Once you grasp the beauty, simplicity and power of proxies you’ll likely find many uses for them. They’re a great tool to have in your toolbox and Roxy would love it if she found a place in yours.

Update: Nov. 14th, 2008: Based on your feedback I just updated the gem (v0.2) to properly handle proxying methods that have arguments:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Person
  
  include Roxy::Moxie
  
  # Contrived example to show that reload value is passed through
  # to the proxy target
  def ancestors(reload = false)
    1.upto(4).to_a.collect { |i| "#{reload ? 'r' : ''}ancestor#{i}" }      
  end
  
  # Men = odd numbered ancestors
  proxy :ancestors do
    def men
      proxy_target.select { |a| a.include?('1') || a.include?('3') }
    end
    def women
      proxy_target - men
    end
  end

end

# Note how arg is passed through (reloaded ancestors start
# with 'r')
person.ancestors(true).men #=> ['rancestor1', 'rancestor3']

# Even default arg is retained (default is false, so no
# ancestors have 'r' prefix)
person.ancestors.men #=> ['ancestor1', 'ancestor3']

Installation

Installing is pretty simple…

sudo gem install yfactorial-roxy --source http://gems.github.com

Teaser

I hope to have an extension library up soon that utilizes Roxy to provide ActiveRecord-like association definitions in ActiveResource. Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 'roxy'
class User < ActiveResource::Base

  include Roxy::Moxie

  proxy :articles,
            :to => proc { |u| Article.find(:all, :params => { :user_id => u.id } } do
    def destroy_all
      proxy_target.each { |a| a.destroy }
    end
  end
end

# Now a remote user looks a lot like a first class active record object:
user.articles #=> [<Article...>, <Article...>, ...]
user.articles.destroy_all

Stay tuned for that, and let me know where you’ve found proxies to be a great tool to have around. I’m always looking for better example scenarios.

tags: ruby

Rubyists, Learn Some iPhone Skillz

Posted by ryan
at 8:24 PM on Monday, June 01, 2009

If any of you Rubyists are going to be attending the FutureRuby in Toronto this July and have an interest in learning how to work some magic on the iPhone, I encourage you to check out Mobile Orchard’s Dan Grigsby and his Beginning iPhone Programming For Rubyists course taking place before FutureRuby. In addition to the iPhone basics, he’ll be covering our ObjectiveResource framework.

You can get a discount on the course if you register before June 9th so head on over and give it a peek.