Mark Needham

Thoughts on Software Development

Ruby: Control flow using ‘and’

with 5 comments

Something I’ve noticed while reading Ruby code is that quite frequently the flow of a program is controlled by the ‘chaining’ of different operations through use of the ‘and’ keyword.

I’ve noticed that this pattern is used in Javascript code as well and it’s particularly prevalent when we want to get a status for those operations after they’ve all been executed.

For example we might have the following code…

status = user.is_allowed_to_edit_foo? and user.update_foo(params[:foo]) and user.save

..where the user’s foo would only get updated and the record saved if they were actually allowed to edit their foo.

At the moment it seems quite strange to me because when I see operations chained together like that I assume that they’re all ‘query’ type operations but in Ruby it seems like ‘command’ type operations are used too.

To an extent the command query separation principle is being broken but it seems quite common to return a boolean value to indicate whether or not a state changing operation was successful.

I’d be more familiar with that type of code being written like this but I don’t think it reads as well:

status = false
if user.is_allowed_to_edit_foo?
	if user.update_foo(params[:foo])
		status = user.save
	end
end

While trying to think of a way of writing that code which I think would be more intention revealing I ended up with the following:

class User
  def is_allowed_to_edit_foo?(foo, &block)
    yield and return true if can_edit_foo?
    false
  end
 
  def update_foo(&block)
    #do some awesome stuff
    successful_update = true
    yield and return true if successful_update
    false
  end 
 
  def can_edit_foo?
    true
  end  
end
user = User.new
status = user.is_allowed_to_edit_foo?(params[:foo]) do
  user.update_foo do
     user.save
  end
end

I’m guessing the original code I posted is more idiomatic Ruby but I still think it’s interesting to see the different styles that you can write code in.

Written by Mark Needham

September 23rd, 2010 at 2:33 pm

Posted in Ruby

Tagged with

  • Mateus Brum

    This is the same for me.
    Query separation principle is being broken with an additional complexity with &block.

  • http://www.markhneedham.com Mark Needham

    Yeh the command/query separation principle is certainly still being broken but it seems like that’s a trade off that’s made by choosing to use the ActiveRecord pattern?

  • Saager Mhatre

    http://api.rubyonrails.org/classes/Object.html#method-i-returning should make your code a tad bit more readable

  • Saager Mhatre

    Would this be a good alternative?

    status = user.save if user.is_allowed_to_edit_foo? and user.update_foo(params[:foo])

  • http://www.markhneedham.com Mark Needham

    Yeh that looks much better actually – the power of the new line!