rnd
rnd

Reputation: 45

Are blocks in Ruby overused?

I'm starting to learn Ruby and probably unsuprisingly the hardest thing to wrap my head around is blocks.

Looking at some examples of their use some of them just seem unecessary complicated, and almost like someone is trying to obfuscate the code.

For example, here's some migration code from Rails:

create_table :posts do |t|
    t.string :name
    t.string :title
    t.text :content
    t.timestamps
end

Assuming that the t refers to the created table isn't this just the same thing as this?: (added parentheses to make it more clear)

t = create_table(:posts)
t.string(:name)
t.string(:title)
t.text(:content)
t.timestamps()

How is the first version 'better' or more clear?

Upvotes: 3

Views: 175

Answers (4)

DVG
DVG

Reputation: 17480

The real benefit to blocks is that they allow you to pass code as a parameter. You give the actions you want executed to the method, and at some point that method executes your block. When that happens, what happens before and after are encapsulated from you, you just need to be concerned with the code you give to the method.

Is there a situation that could be done another way? Maybe, but the class that you bass the block to changes, you don't need to worry about it or take extra actions, because they are encapsulated and you just have to be concerned with the block code.

Upvotes: 0

MrDanA
MrDanA

Reputation: 11647

One reason to use blocks is if there are things you need to do after the block.

For instance, assume that some private migration method called now_commit_sql needs to be called to actually commit the SQL to create your posts table. In the second way you listed, it be up to the user to remember to type in t.now_commit_sql() (in addition to the now_commit_sql method having to be made public).

In the block way, after the yield, it can just be called on its own, and thus be more seamless and less error prone for the user. In addition, if the Rails developers needed to call some other method in a future version, such as log_sql() or what have you, they could stick it in there instead of the user having to now know to call t.log_sql() in addition to .now_commit_sql().

Upvotes: 5

Dave Newton
Dave Newton

Reputation: 160170

Flip your question: how is the first version more complicated?

Short answer: in general, no. Blocks serve specific purposes.

IMO the block is more communicative because:

  • Everything in the block is related
  • Scope is enforced at the language level (no more t after the block)

Blocks can also execute code before or after the method's yield. For example, a block that yields a file can close the file.

Those added parentheses do not make anything more clear: one of the beauties of Ruby (and similar languages) is that optional parentheses make things seem more declarative, which a table definition is.

Upvotes: 6

snøreven
snøreven

Reputation: 1974

Because it's a block it is clear at first sight that the whole stuff is related. In the second example you have to look twice.

Upvotes: 0

Related Questions