Getting Comfortable Working With Rails Core

This year’s RailsConf was truly one of the most impressive and inspiring development conferences I have ever been to. Bright-eyed and bewildered, I got to listen to lectures from people big and small in the community. Two individuals, in particular, stood out to me: Yehuda Katz and Rick Martinez. I listened to Yehuda’s keynote; the now Rails hero’s mentioned in his talk “I was just some guy who dove in, and here I am.” Rick Martinez of Flavorpill.com, who you may not know, is really just a guy who did dive in and was able to give a fascinating talk called “Hardcore Extending Rails 3.” The overall message? Again, “I just started digging around, and here’s what I came up with.”

As an aside, one of the questioneers at Rick’s talk was Yehuda commenting something to the affect of “this is what we wish more people would do, just dive in.”

I knew I had what it takes to dive in, it was just a matter of discipline and taking the time to learn the tools and get acclimated with the libraries. I walked into the conference feeling like a novice about to hear four days of lectures that were way over my head, and I left chomping at the bit waiting to start tearing to guts of Rails 3 wide open (which I began to do the entire trainride home).

For the past two months since then, I’ve been consuming more Ruby information then ever, determined to master the language and become a productive member of the Rails community. There have been frustrating times when I didn’t understand anything (and there will be more of that to come), but there has also been a wealth of knowledge that I have gained and have been able to apply immediately. For those of you who want to dive in, I’ve assembled this list of things I’ve done to get going and I think it could help you out, too. Pick and choose as you wish; these items may not all be for you, but if it’s on this list, it’s because I directly associate it with my growth.

  • Read The Ruby 1.9 Book

    If you want to work with Rails, you have got to learn Ruby. Ruby is filled with new concepts and techniques that you probably haven’t experienced in other languages. The more of this language you know, the more you will understand the design patterns that the Rails library uses, and the more power you can leverage in your own code. The internal architecture of the code is a lot to take in, you don’t want to be hung up on Ruby syntax at the same time. Learning Ruby will help you separate whether what you are looking at is confusing because of your lack of understanding of the Ruby code or the Rails library (looking at the Rails lib after learning Ruby better, the code is so much easier to follow). Read “The Ruby 1.9 Book,” also known as “The Pickaxe Book.”

  • Learn Ruby Metaprogramming

    Metaprogramming is the practice of writing code that writes code. Two weeks ago, I would have told you that Metaprogramming is something that the pros did because they’ve grown so bored with the boundaries of the language that they want to add to it. On the contrary, metaprogramming is a staple of working with Ruby and is a compliment of the language’s aesthetics. Learning about concepts such as Open Classes, Dynamic Dispatch and Methods, and beyond will help you understand how programmers wrangle Ruby to get it to work the way they want it to.

    Here are three great resources resource for learning Ruby metaprogramming:

    1. “The Ruby 1.9 Book” book has entire chapter on metaprogramming. I recommend reading this before jumping into…
    2. “Ruby Metaprogramming” by Paolo Perrotta. This book explains metaprogramming concepts in a fun, observational way, with an entire section on metaprogramming Rails.
    3. As a follow up, Yehuda wrote an article that helps clear up some common misconceptions about how to properly write libraries – “Metaprogramming In Ruby”

    By now you realize you’ve got a lot of reading to do, which is why I totally recommend that you…

  • Buy an iPad

    This may seem like one of those “you-got-to-be-kidding-me” kind of todos. But the truth is, I single-handedly attribute so much of my educational growth over the past month to me buying the iPad. Last year, I bought the Ruby 1.9 book and the PDF. The book sat on my shelf and I only casually browsed through it. The PDF was on my laptop, and I only fired it up a couple of times, and then get distracted by a client’s email, or a blog post, and ultimately didn’t read any of it. With the iPad, I take it everywhere: I read for 15 minutes at the laundry mat, 30 minutes at then pool, before I go to sleep, etc. In three weeks, I read over 450 pages of the Ruby 1.9 book and over 250 pages of the Metaprogramming book. Here is the key though: make it an educational device only. For me, that meant not loading on a Facebook app or any other distractions, I didn’t even configure my mail account or add music to it. It’s simply there for ebook reading, reading RSS feeds and Tweets from other developers, and writing blog posts. It’s a productivity machine!

  • Read the Rails source code

    While it may seem daunting at first, the current version of the Rails 3 library is one of the most elegant codebases to try and follow. Before taking the plunge into the codebase myself, I used to hear people say “look at the source” and I used to think “I am not at that level yet.” Trust me, you are, and the more comfortable you get with Ruby, the more you will learn how the Rails code plays into it’s strengths. Additionally, the library is filled with extremely helpful comments. For example, check out base.rb in ActiveRecord; don’t quote me on this, but I’m pretty sure for every line of code, there are two or three lines of comments.

  • Get Involved

    When it comes to getting involved with Rails, you couldn’t ask for a better community to help you out then the Rails community. There are people with all different levels of expertise, willing to lend a hand to help you achieve whatever you’re trying to accomplish.

    • Go to conferences and meet ups. Not only do you learn about emerging technologies, but you also get to network and make friends with other developers, as well as learn about other popular developers in the community. One key piece of advice: don’t be shy. Everyone is there for the same reason, and everyone I’ve gotten to meet in the Ruby community have been nothing but nice and helpful.
    • The Ruby on Rails IRC on freenode, #rubyonrails. Don’t feel shy; just ask your question and be patient. Feel free to hit me up in there, I’d be more than happy to help you out.
    • RailsBridge – RailsBridge is a group of people committed to helping you learn more about Rails. They can answer your questions in the #railsbridge IRC, they organize weekend bug mashes to help the Rails core team get through ticket issues in Lighthouse, and are really just a great group of people. I got to spend a good half hour chatting with Santiago Pastorino of WyeWorks at RailsConf, about RailsBridge and all the things they do, awesome stuff!
    • Read up on the work other developers are up to. Guys like Aaron Paterson, Ilya Gregorik, and Yehuda Katz will commonly blog or tweet about things they are working on. You can learn a lot by being a fly on the wall.

    The biggest piece of advice I can give you in terms of getting involved with the Rails codebase is: start. Any new library takes time to learn, and Rails is no exception. If you follow any or all of the tips I’ve listed, I think you’ll find the learning curve to be a little less steep. If you have any other advice that helped you out along to way, please leave a comment below, myself and others would appreciate it.

    • Digg
    • del.icio.us
    • Facebook
    • Google Bookmarks
    • Twitter

4 Comments »


Lecture

‘Mail’ is a resevered model name in Rails 3

This may bite you in the ass if you are upgrading a Rails app from 2 to 3: ‘Mail’ is now a reserved model name. That means, if you currently have a model app/models/mail.rb, and/or a class defined as class Mail < AR::Base (for instance), it will collide with the new Mail class in Rails 3, and possibly throw this error

1
undefined method `transfer_encoding' for class `Mail::Message'

That is because Rails defines Mail.transfer_encoding in it’s Mail class, and your’s is over-riding it. The quick fix: rename your class and your file name.

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

No Comments »


Code

Drupal Linkshare Pixel Module Released

I released a nice little module onto the Ubercart site today called “Linkshare Pixel.” This handly little module is will create an image tag that Linkshare requires you to put on your checkout page for tracking purposes. It takes care of building the URL out of the cart contents and store configurations, all you have to do is provide your Linkshare merchant ID.

http://www.ubercart.org/project_project/linkshare_pixel

Enjoy!

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

1 Comment »

,
Information

Whyday

The Ruby community announced yesterday that August 19 will be “Why Day” (http://www.whyday.org), in honor of whytheluckstiff. For most of use in the Ruby world, _why needs no explanation, for those who don’t, I demand you to go learn about him, and all the amazing work he did for this community. I can go into detail, and site resources, but he’s had such an impact, that learning about him will not be hard at all.

I will however, post a link to his song, “This book was made”, that came with his “Poignant Guide” book. This Book Is Made

Thanks _why.

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

No Comments »

Information

Working With Rack in Rails 3

While attending this year’s RailsConf in Baltimore, there was much excitement in the air about Rails 3. This was perpetuated by the fact that the Rails core team pushed Rails 3, Beta 3 & 4 during the conference. While there are so many awesome new things that Rails 3 is providing, and I strongly encourage everyone to move over to it as soon as they can, I want to talk today about Rack, and how it is allowing your to optimize your Rails app like never before.

Nice Rack.

If you are new to a lot of the things going on in Rails 3, you probably aren’t to familiar with the concept of Rack. The story goes like this: before Rails 3, all of the things that the Rails framework provides you, like session handling, parsing the parameters, and other conveniences that Rails provides you pertaining to requests, were tightly coupled to the Rails code base. In the early days of Rails, this was no big deal; we had these tools and we loved them. However, as Rails grew, and the apps built on Rails had more demanding requirements, we found situations where these conveniences add a lot of not needed overhead. For example, let’s say we wanted to have a Rails application whose sole responsibility was to accept uploaded files that we save to a server. You wouldn’t necessarily need session handling, cookies, flash, etc. Also, you may have written a great library that is better optimized or offers more hooks to certain ingrained Rails functionality for your application that you would like to use instead. Enter Rails 3.

In Rails 3, the framework gutted many of these great features out of the framework and into this concept of a Rack. We’ll talk about what Rack is in just a second, but it is important to note that the key advantage hear is that these awesome conveniences can be taken out of your application stack (or enhanced) to optimize them to suite your application’s need.

Anatomy of a Rack

Ok, ok … so what is a Rack? Rack is simply an interface that sits in between your web server and your application.


When a request comes into a Rails app, before it encounters your application code, it will run through your Rack. The rack is a daisy-chained library of classes, each of which have different responsibilities, all of which are the dominant set-ups that need to be done for every request (sessions, params, etc).

Components

A Rack application is simply a class which defines a method, #call. This method receives a parameter, the current set up environment hash, commonly named “env”. The required return value of that method is an array composed of exactly three elements:

  • The status code (200, 404, etc.)
  • The headers for the request
  • The response body

Note: The response body must respond to #each, therefore you will commonly find it in an array ( [my_response]) or a class mixed in with Enumerable.

The next Rack application inline to fire in your middleware will make a call to #call when it initializes and will receive its return value (the response / header / body array) as a parameter to #initialize, commonly labeled “app”.

Enough talking, let’s looks at code.

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
32
33
34
35
36
37
38
module Rack

  # The Rack::Static middleware intercepts requests for static files
  # (javascript files, images, stylesheets, etc) based on the url prefixes
  # passed in the options, and serves them using a Rack::File object. This
  # allows a Rack stack to serve both static and dynamic content.
  #
  # Examples:
  #     use Rack::Static, :urls => ["/media"]
  #     will serve all requests beginning with /media from the "media" folder
  #     located in the current directory (ie media/*).
  #
  #     use Rack::Static, :urls => ["/css", "/images"], :root => "public"
  #     will serve all requests beginning with /css or /images from the folder
  #     "public" in the current directory (ie public/css/* and public/images/*)

  class Static

    def initialize(app, options={})
      @app = app
      @urls = options[:urls] || ["/favicon.ico"]
      root = options[:root] || Dir.pwd
      @file_server = Rack::File.new(root)
    end

    def call(env)
      path = env["PATH_INFO"]
      can_serve = @urls.any? { |url| path.index(url) == 0 }

      if can_serve
        @file_server.call(env)
      else
        @app.call(env)
      end
    end

  end
end

So here is the first Rack application in a default Rails 3 stack, which is responsible for serving back static files. As you can see, it’s #initialize receives “app” as a first parameter, which would be the response of #call from the previous Rack app. For this Rack, the #call function doesn’t create it’s own array to return, it simply loads a static file if it finds it with Rack::File, or just passes the current environment silently if there is no static file.

Closing

The best way to learn what rack can do for you is to look into the code for the current Rails 3 stack and see what it does. You can get a list of your rack stack by running:

1
rake middleware

See also the Official Rack Project site for super easy documentation and explanations.

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

No Comments »

,
Code

Adding Methods on Associations in Rails

Many times, you may find yourself interested in moving some of your logic outside of the view and into a model, so that you can re-use it throughout your app. But sometimes, the method you may want to define needs to be on an association of two models, and not on the models themselves.

As a real world scenario, imagine you are making an online game in which two models exist, Game and Score. The Game model keeps track of when the game was started, who started it, the level of difficulty, etc. The Score model keeps track of the value of the score, the round the score was done in, and the time the score was placed. The Game model has many Score models. Obviously, when the game is over, we are going to want to be able to see the total score. But what model do we define the method on? The Game model, itself, doesn’t have any scores and a Score object only knows about itself and not all the others that belong to the parent Game object.

This is a situation where the method needs to be defined on the association of Game and Score. Anytime the value you are trying to obtain can only be calculated with a parent and a child of an association, then you need to define the method on the association.

How to define it

Turns out that defining the method is a little trivial. The has_many method, used for creating one-to-many relationships, accepts a block in which you can define methods. Inside that block, self is set to the collection of children in the relationship. So now to define your total_score method:

1
2
3
4
5
6
7
8
9
  class Game < ActiveRecord::Base
    has_many :scores do
      def total_score
          total = 0
          self.each { |score| total += score.value }
          total
      end
    end
  end

Then, in the app …

1
2
3
4
5
6
7
g = Game.create(:user_id => 1)
g.scores.build(:value=>20)
g.scores.build(:value=>40)
g.scores.build(:value=>60)
g.save
g.scores.total_score
# 120
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

2 Comments »

, ,
Code

What’s in a deadline, really?

As I sit here in court, waiting patiently to fight a cell phone ticket that I am clearly guilty of, I got the opportunity to read over David Hansson’s recent post on deadlines. To recap, he stated that we should stop holding ourselves accountable to unrealistic deadlines, or better put, to deadlines that force us to sacrifice quality, testing or hours. This isn’t a new thought for any seasoned developer. While we dread the idea of slaving over late hours and patch-and-go design methodologies, we seem to constantly practice the former, and unfortunately the ladder.

While, I agree that we shouldn’t be pigeon-holing ourselves into tight deadlines, the truth is, most of the time, doing so will land you the contract, and refusing it will result in the client giving it to one of countless other developers who will gladly slave to meet that impossible deadline. So, how does one find a homeostasis where both the client and the developer are mutually happy with the quality of work and the amount of time it takes to build it?

For most development companies, three basic questions fuel the work we do, to a certain extent:

  • What do you need done?
  • How much can you can pay to get it done?
  • When do you need it done by?

Armed with these 3 answers, you can derive a general synopsis of the life-cycle of a project. For a certain type of client, the first two questions are givens: the client needs these features and they only have a certain amount budgeted to get it done. Clients generally come to you with specific demands that they typically have good reasons for (and obviously, we will intervene if our experience tells us the demands need tailoring) As for budget, that’s always a touchy subject: we are resolute in what our labor costs will be, but sometimes, clients won’t budge and you still want to help. As a result, time may be your ultimate leverage when you gain the knowledge of the different ways time can factor in to a project.

Why is your deadline?

Steve Walker and myself spend a great deal of time debating certain points of our industry in hopes of carving out a strategy we refer to as “Client-Driven Development.” The idea is to shift the paradigm of many of the assumed truths of developing software for clients. One of the facets that interests me is the concept of a deadline. To explain, here are a couple of examples.

The arbitrary deadline

Scenario: The last web company I worked for believed in the arbitrary deadline as a means to engage their employees. A new idea would be conceived by the CEO and its deadline was always “the last Friday of the month,” regardless of rational, time estimate to develop the feature, or what day of the month it currently is.

Result: The net result was a company divided by people that knew the deadline was bullshit so they lost passion for the project (and eventually the company) and people that worked feverishly to meet this deadlines because “he’s the boss.”

The open-ended deadline

Scenario: Many times, you will work with a client who “doesn’t have a deadline”. The reasons why they do not vary, but many times I feel the client thinks they are being convenient by being very open-ended.

Result: The result of offering an open-ended deadline can have two general consequences. The first is that the developer may afford the client the ability to either negotiate the features or the budget. The second is that the developer will hold you to their estimate, but the project will never get done. You all know about that project that you have right now that started over six months ago but either you haven’t finished it yet because there is no client pressure, or the client has finished providing the content or approvals, also because there is no client pressure.

Note: having an open deadline is like getting in shape without weighing yourself first: sure, you may tell yourself “the amount of weight doesn’t matter, just as long as I look good,” and you still might even loose the weight. However, knowing your starting point and agreeing on the end point is the catalyst for realistic motivation.

Event Inspired Deadline

Scenario: A very common situation is for a client to come to you and say they need a project launched by a certain date because of a certain upcoming event, where ‘event’ is paralleled by a significant date to the client’s demographic. Some examples are trade shows, monthly newsletters, cultural events (ex. launching a red version of a site by Valentine’s day), or in tandem with a new product release, to name a few.

Result: As a whole, I find I am more accepting of these deadlines because they have a black and white reason for their necessity. The issue developers have with these deadlines is that, often times, they are given without much time to develop. “We have a trade show in 2 days and we want the this new section to go live by then,” or even more painful “We have a trade show in 2 months and we want this new section to go live by then,” and then you don’t get the content for it until two days before the deadline.

Conclusion

My suggestion to you is not to try to treat the deadline game in a one-size-fits-all manner, because all clients and projects are different. It’s just not realistic to think that every client will agree to the one way you are going to address deadlines. I have found it much more effective to analyze what type of deadline the client has and see how I can use that as an advantage against the other main aspects of the project. Remember that while the three points of a project – features, budget, and time – may always form a triangle, there are different types of triangles based on how you handle each vertex.

Sidenote: For those curious, I got the ticket thrown out.

Joey Naylor: Dad, why is the American government the best government?
Nick Naylor: Because of our endless appeals system.

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

1 Comment »


Lecture

Turn Current Working Trunk Into a Branch in SVN

So you start working inside of a trunk checkout of a Subversion repo, thinking that you will just be making a quick update. Once you start working, you realize it might have been better to make a branch to work on the feature separately from the trunk? Fear not! As Floyd Price from CodeSpaces points out, the process is pretty simple when you think about what you want to get done.

Technically, if you have not committed the changes into the trunk yet, you are dealing with the most up to date version of the trunk. If you were create a new branch from the trunk, they’d both be on the same page, sans your new edits.

Your current trunk checkout: A + B
               A new branch: A

To make the new branch, run:

#svn cp trunk_repo_path branch_repo_path/new-name
  svn cp http://example.com/repo/trunk http://example.com/repo/branches/new-branch

Now, in your current trunk repo check out you’ve been working in, switch the URL to be the new branch

svn switch http://example.com/repo/branches/new-branch .

If you run `svn st`, you will see the same modified files, but if you run `svn info` you will see the checkout’s URL now points to the branch, and you are free to commint

svn commit -m "first of commit new feature"

Hope this helps.

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

No Comments »


Code

Why does my autospec keep looping?

After following all of the most up-to-date tutorials I could find, making sure I installed all of the latest gem releases, and just trying to be diligent overall, I couldn’t figure out why my autospec kept looping. In particular, it loops when there are Cucumber features being run ( by setting AUTOFEATURE=true before running autospec ). If you search around on Google, you will find a whole mess of articles with other people having the same issue, and all solutions seemed to come from this one article: http://www.ruby-forum.com/topic/183578 . After reading that, life was glourious for all, David Chelimsky to the rescue! From his life-saving post…

If you use Autotest with Ruby on Rails, be sure to gem install autotest-rails when you upgrade to ZenTest-4.1.0.

Without that gem, when you run the autospec command that ships with RSpec, Autotest won’t won’t have any way of knowing it’s in a Rails app and it will load up rspec’s autotest/rspec.rb instead of rspec-rails‘ autotest/rails_rspec.rb.

Absolutely brilliant! I run to my console, upgrade my gems … and it still loops! Determined not to give up, I did what any smart person would do, ask someone else.

After about a half-hour of frustration of wheel-spinning, Steve Walker and I were finally able to bang out a solution that just may work for you.

About half way down the github wiki for Cucumber, you will see a section titled “Other ways of running features” in which they advise you to put this in your cucumber.yml file

autotest-all: --require features --require lib --format progress features
autotest: --require features --require lib features
default: --format pretty
html: --format html --out features.html

This is a little out of date, most likely written before RSpec moved to autospec, and all hell breaks loose presumably because we are still configuring it to point to autotest.

In conclusion, drop in this …

autospec-all: --require features --require lib --format progress features
autospec: --require features --require lib features
default: --format pretty
html: --format html --out features.html

…and let me know if it fixes it.

Happy red/green/re-factor-ing!

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

1 Comment »

Uncategorized

Ruby 1.9.1 & Textmate Don’t Play Nicely Together

Ruby 1.9.1 has been out for a long time now, so you may feel pretty comfortable about installing it on your box and doing to the big “let’s see what this broke” game with Rails. We’ll I just wanted to give you a little heads up with another program you may have not expected issues with, Textmate.

What? The Horror! Not being able to code Ruby with Textmate. Well, fortunately, that is not entirely true. You can still use the infamous editor to edit you Ruby code, no problem. The issue comes when trying to use any of the generators or functions that require you to execute Ruby code. You may find yourself running into this puzzling error:

invalid multibyte char (US-ASCII)

For those of you not in the know, the handling of different character types have changed in Ruby 1.9 and Textmate’s latest release does not accommodate this change.

I will update this with any updates, in terms of fixed Textmate versions or any other reliable solutions.

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Twitter

No Comments »

,
Information