Recent Ruby and Rails Regales 0

Posted by sjs
on Thursday, June 28

Some cool Ruby and [the former on] Rails things are springing up and I haven’t written much about the two Rs lately, though I work with them daily.

Rails on Rules

My friend Jim Roepcke is researching and implementing a plugin/framework designed to work with Rails called Rails on Rules. His inspiration is the rule system from WebObjects’ Direct to Web. He posted a good example for me, but this baby isn’t just for template/view logic. If some of the Rails conventions were specified in a default set of rules which the developer could further customize then you basically have a nice way of doing things that you would otherwise code by hand. I think it would be a boon for the ActiveScaffold project. We’re meeting up to talk about this soon and I’ll have more to say after then, but it sounds pretty cool.

Sake Bomb!

I’ve noticed a trend among some recent posts about Rake: the authors keep talking about booze. Are we nothing but a bunch of booze hounds?! Well one can hope. There’s some motivation to learn more about a tool, having more time to drink after work. This week Chris Wanstrath dropped a Sake Bomb on the Ruby community. Like piston, sake is something you can just pick up and use instantly. Interestingly the different pronunciations of rake and sake help me from confusing the two on the command line… so far.

Secure Associations (for Rails)

Jordan McKible released the secure_associations plugin. It lets you protect your models’ *_id attributes from mass-assignment via belongs_to_protected and has_many_protected. It’s a mild enhancement, but an enhancement nonetheless. This is useful to enough people that it should be in Rails proper.

Regular expressions and strings with embedded objects

taw taught me a new technique for simplifying regular expressions by transforming the text in a reversible manner. In one example he replaced literal strings in SQL – which are easily parsed via a regex – with what he calls embedded objects. They’re just tokens to identify the temporarily removed strings, but the important thing is that they don’t interfere with the regexes that operate on the other parts of the SQL, which would have been very difficult to get right with the strings inside it. If I made it sound complicated just read the post, he explains it well.

If you believe anything Steve Yegge says then that last regex trick may come in handy for Q&D parsing in any language, be it Ruby, NBL, or whataver.

Embrace the database 0

Posted by sjs
on Friday, June 22

If you drink the Rails koolaid you may have read the notorious single layer of cleverness post by DHH. [5th post on the archive page] In a nutshell he states that it’s better to have a single point of cleverness when it comes to business logic. The reasons for this include staying agile, staying in Ruby all the time, and being able to switch the back-end DB at any time. Put the logic in ActiveRecord and use the DB as a dumb data store, that is the Rails way. It’s simple. It works. You don’t need to be a DBA to be a Rails developer.

Stephen created a Rails plugin called dependent-raise which imitates a foreign key constraint inside of Rails. I want to try this out because I believe that data integrity is fairly important, but it’s really starting to make me think about this single point of cleverness idea.

Are we not reinventing the wheel by employing methods such as this in our code? Capable DBs already do this sort of thing for us. I don’t necessarily think it’s bad to implement this sort of thing, but I think it’s a symptom of NIH syndrome. Instead of reinventing this kind of thing why don’t we embrace the DB as a semi-intelligent data store? The work has been done all we have to do is exploit it via Rails.

There are a few reasons that the Rails folks choose not to do so but perhaps some of them could be worked around. Adapting your solution as you progress and realise that things aren’t exactly as you thought they were… I believe the word for that sort of thing is agility.

Database agnosticism

From SQLite to Oracle, just configure the connection, migrate, and run your app on any database. One of the biggest Rails myths that is backed by the Rails team themselves. It takes a fair amount of work to ensure that any significant app is fully agnostic. Sure you can develop on SQLite and deploy on MySQL without much trouble but there are significant diffirences between RDBMSs that will manifest themselves if you create an app that’s more than a toy. Oh, you used finder_sql? Sorry but chances are your app is no longer DB agnostic. FAIL.

Solution: Drop the lie. Tell people the truth. Theoretically, theory and practice are the same; in practice they are not. Be honest that it’s possible to be DB-agnostic but can be a challenge. Under no circumstances should we shun something useful in the name of claiming to be DB-agnostic.

Staying agile

If we start making use of FK constraints then we’ll have to make changes to both our DB and our code. This makes change more time-consuming and error-prone which means change is less likely to happen. This goes against the grain of an agile methodology. Or does it?

Solution: Rails should use the features of the DB to keep data intact and fall back on an AR-only solution only if the DB doesn’t support the operation. There doesn’t need to be any duplication in logic rules either. If Rails could recognise a FK constraint that cascades on delete it could set up the has_many :foos, :dependent => :destroy relation for us. In fact I only see our code becoming DRYer (maybe even too DRY[1]).

Staying in Ruby

Using the DB from within Ruby is a solved problem. I don’t see why this couldn’t be extended to handle more of the DB as well. Use Ruby, but use it intelligently by embracing outside tools to get the job done.

Many relationships could be derived from constraints as people have pointed out before. There are benefits to using the features of a decent RDBMS, and in some cases I think that we might be losing by not making use of them. I am not saying we should move everything to the DB, I am saying that we should exploit the implemented and debugged capabilities of our RDBMSs the best we can while practicing the agile methods we know and love, all from within Ruby.

[1] I make liberal use of annotate_models as it is.

test/spec on rails declared awesome, just one catch

Posted by sjs
on Thursday, June 14

This last week I’ve been getting to know test/spec via err’s test/spec on rails plugin. I have to say that I really dig this method of testing my code and I look forward to trying out some actual BDD in the future.

I did hit a little snag with functional testing though. The method of declaring which controller to use takes the form:


use_controller :foo

and can be placed in the setup method, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# in test/functional/sessions_controller_test.rb

context "A guest" do
  fixtures :users

  setup do
    use_controller :sessions
  end

  specify "can login" do
    post :create, :username => 'sjs', :password => 'blah'
    response.should.redirect_to user_url(users(:sjs))
    ...
  end
end

This is great and the test will work. But let’s say that I have another controller that guests can access:

1
2
3
4
5
6
7
8
9
10
11
12
13
# in test/functional/foo_controller_test.rb

context "A guest" do
  setup do
    use_controller :foo
  end

  specify "can do foo stuff" do
    get :fooriffic
    status.should.be :success
    ...
  end
end

This test will pass on its own as well, which is what really tripped me up. When I ran my tests individually as I wrote them, they passed. When I ran rake test:functionals this morning and saw over a dozen failures and errors I was pretty alarmed. Then I looked at the errors and was thoroughly confused. Of course the action fooriffic can’t be found in SessionsController, it lives in FooController and that’s the controller I said to use! What gives?!

The problem is that test/spec only creates one context with a specific name, and re-uses that context on subsequent tests using the same context name. The various setup methods are all added to a list and each one is executed, not just the one in the same context block as the specs. I can see how that’s useful, but for me right now it’s just a hinderance as I’d have to uniquely name each context. “Another guest” just looks strange in a file by itself, and I want my tests to work with my brain not against it.

My solution was to just create a new context each time and re-use nothing. Only 2 lines in test/spec need to be changed to achieve this, but I’m not sure if what I’m doing is a bad idea. My tests pass and right now that’s basically all I care about though.

inspirado 0

Posted by sjs
on Tuesday, May 22

spyderous is a Gentoo dev and I read his posts via the Gentoo planet (and again on the freedesktop.org planet).

He recently mentioned an idea to foster participation in Gentoo (or any other project) by aggregating personal project plans for people to browse. I thought it sounded cool so I started coding and came up with what I call inspirado.

It’s fairly basic so far but it’s only a week old. It is RESTful and you can get XML for most pages by appending .xml to the URL (or by using curl and setting the HTTP Accept header). Eventually Atom and/or RSS should be available as well.

Note that everything you see there is purely for testing purposes and any changes you make are most likely going to be blown away.

There are several features on my TODO list but I’d love to hear about any you might have. Write to sami.samhuri@gmail.com if you have suggestions or anything else to say.

(Inspirado is, of course, a Rails app.)

Dumping objects to the browser in Rails 2

Posted by sjs
on Tuesday, May 15

Here’s an easy way to solve a problem that may have nagged you as it did me. Simply using foo.inspect to dump out some object to the browser dumps one long string which is barely useful except for short strings and the like. The ideal output is already available using the PrettyPrint module so we just need to use it.

Unfortunately typing <pre><%= PP.pp(@something, '') %></pre> to quickly debug some possibly large object (or collection) can get old fast so we need a shortcut.

Taking the definition of Object#pp_s from the extensions project it’s trivial to create a helper method to just dump out an object in a reasonable manner.

1
2
3
4
5
def dump(thing)
  s = StringIO.new
  PP.pp(thing, s)
  "<pre>#{s.string}</pre>"
end

Alternatively you could do as the extensions folks do and actually define Object#pp_s so you can use it in your logs or anywhere else you may want to inspect an object. If you do this you probably want to change the dump helper method accordingly in case you decide to change pp_s in the future.

1
2
3
4
5
6
7
class Object
  def pp_s
    pps = StringIO.new
    PP.pp(self, pps)
    pps.string
  end
end

Good reading 0

Posted by sjs
on Tuesday, May 15

This is the best tutorial I have read on developing RESTful web apps using Rails. If you’re remotely interested or curious about REST on Rails I highly recommend that as one of your first reads.

I have been messing around with REST and managed to piece together a basic app without much trouble. That tutorial really cleared up some things I wasn’t too sure about, especially with respect to routing resources.

Check out the restful_authentication plugin to see how a session becomes a resource.

For many cases I can definitely see the benefits of REST and for the exceptions you just use Rails in the traditional way.

Rails plugins (link dump) 0

Posted by sjs
on Wednesday, May 09

Some Rails plugins I find useful:

Array#to_proc: A complement to Symbol#to_proc

Posted by sjs
on Thursday, May 03

By now many Ruby programmers are familiar with the magic that is Symbol#to_proc.

If you haven’t seen anything such as youngest = people.map(&:age).min yet here’s a quick explanation of the syntax.

  • Ruby calls to_proc on the block parameter if it is not already a Proc. (coercion)
  • Since a symbol is a message, Symbol#to_proc simply constructs a block that sends self (the symbol) to the first block parameter.
  • The code above is equivalent to youngest = people.map { |p| p.age }.min
  • The few characters saved are significant if you are sufficiently lazy, or if you frequently chain short blocks like that together.

This is a great way to clean up your code, and the brevity will have you groaning when you have to type out something such as: birth_years = people.map { |p| p.birthdate.year }

But there is a simple way to make that shorter using a trick similar to Symbol#to_proc. To me it seems logical that if map(&:sym) sends :sym to each element of the enumerable object, then an array of symbols should chain the calls together on each element of the enumerable.

If you’ve looked at the implementation of Symbol#to_proc in Rails then this should look familiar as it’s nearly the same code.

1
2
3
4
5
6
7
8
9
10
11
module ArrayExtensions
  # Turns an array of symbols into a simple proc, which is especially useful for enumerations. Examples:
  #
  #   # The same as people.map { |p| p.birthdate.year }
  #   people.map(&[:birthdate, :year])
  def to_proc
    Proc.new do |*args|
      self.inject(args.shift) { |obj, msg| obj = obj.__send__(msg, *args) }
    end
  end
end

This makes the following code valid, and equivalent to the previous example using birth_years.


birth_years = people.map(&[:birthdate, :year])

You can use strings, like so: birth_years = people.map(&%w[birthdate year]), but I don’t dig the &% part of it. To each their own.

Then all that needs to be done is load the extension. I’m doing all this in the context of Rails so I’m setting this up in my environment.rb.


Array.send(:include, ArrayExtensions)

ActiveRecord::Base.find_or_create and find_or_initialize 0

Posted by sjs
on Wednesday, April 11

If you work with Rails then you may be familiar with the dynamic attribute-based finder methods in ActiveRecord::Base. They are class methods used such as User.find_or_initialize_by_name(‘sjs’) or User.find_or_initialize_by_name_and_password(‘sjs’, ‘insanely secure password’). There is also a find_or_create_by_… version.

If you want to do this for many attributes it gets old very, very quickly. This should just accept a hash of attributes like the other ActiveRecord methods we’re used to. 3 methods later and the problem is solved, read on…

Chronic time parsing in Ruby 0

Posted by sjs
on Friday, March 30

The date & time extensions provided by Rails are convenient but they don’t provide anything when it comes to relative dates using weekday names, for example. I’ve been frustrated writing weekday arithmetic so I went in search of something easier. What I found was Chronic!

Ruby and Rails have spoiled me rotten 0

Posted by sjs
on Sunday, July 16

It’s true. I’m sitting here coding in PHP using the Zend Framework and all I can think about is how much nicer Rails is, or how much easier it is to do [x] in Ruby. It’s not that the Zend Framework is bad or anything, it’s quite nice, but you just can’t match Ruby’s expressiveness in a language like PHP. Add the amazing convenience Rails builds on top of Ruby and that’s a really hard combo to compete with.

syncPeople on Rails Bundle 1.0 is out 0

Posted by sjs
on Tuesday, March 07

That’s right, and you should go and get it right away. It’s now the default Rails bundle for TextMate as well.

The reading of schema.rb to generate self.down is really genious. As are footnotes. There’s no going back to gvim now (for Rails anyways).

Now all I need is $500 so I can sell my over-worked PPC Mac mini and be able to get one with an Intel Core Duo in it. It’s not that it’s painfully slow or anything, but compared to the computer I built to be my main workstation it’s pretty weak. I got used to things to being more or less instantaneous.

Generate self.down in your Rails migrations 0

Posted by sjs
on Friday, March 03

Scott wrote a really cool program that will scan self.up and then consult db/schema.rb to automatically fill in self.down for you. Brilliant!

Intelligent Migration Snippets 0.1 for TextMate

Posted by sjs
on Tuesday, February 21

This should be working now. I’ve tested it under a new user account here.

This does requires the syncPeople bundle to be installed to work. That’s ok, because you should get the syncPeople on Rails bundle anyways.

 

When writing database migrations in Ruby on Rails it is common to create a table in the self.up method and then drop it in self.down. The same goes for adding, removing and renaming columns.

I wrote a Ruby program to insert code into both methods with a single snippet. All the TextMate commands and macros that you need are included.

See it in action

I think this looks cool in action. Plus I like to show off what what TextMate can do to people who may not use it, or don’t have a Mac. It’s just over 30 seconds long and weighs in at around 700kb.

Download Download Demo Video

Features

There are 3 snippets which are activated by the following tab triggers:

  • mcdt: Migration Create and Drop Table
  • marc: Migration Add and Remove Column
  • mnc: Migration Rename Column

Installation

Run Quick Install.app to install these commands to your syncPeople on Rails bundle if it exists, and to the default Rails bundle otherwise. (I highly recommend you get the syncPeople bundle if you haven’t already.)

Download Download Intelligent Migration Snippets

This is specific to Rails migrations, but there are probably other uses for something like this. You are free to use and distribute this code.

Obligatory Post about Ruby on Rails 0

Posted by sjs
on Sunday, February 19

I’m a Rails newbie and eager to learn. I welcome any suggestions or criticism you have. You can direct them to my inbox or leave me a comment below.

I finally set myself up with a blog. I mailed my dad the address and mentioned that it was running Typo, which is written in Ruby on Rails. The fact that it is written in Rails was a big factor in my decision. I am currently reading Agile Web Development With Rails and it will be great to use Typo as a learning tool, since I will be modifying my blog anyways regardless of what language it’s written in.

Clearly Rails made an impression on me somehow or I wouldn’t be investing this time on it. But my dad asked me a very good question:

Rails? What is so special about it? I looked at your page and it looks pretty normal to me. I miss the point of this new Rails technique for web development.

It’s unlikely that he was surprised at my lengthy response, but I was. I have been known to write him long messages on topics that interest me. However, I’ve only been learning Rails for two weeks or so. Could I possibly have so much to say about it already? Apparently I do.