开发者

"#{ }" notation vs. erb notation

What are the differences between the notation:

"
  some text
  #{some_ruby_code}
  some text
  #{some_more_ruby_code}
  some_other_text
"

and

ERB.new("
  some text
  <%=some_ruby_code%>
  some text
  <%=some_more_ruby_code%>
  some_other_text
").result

I just have a broad impression that the erb notation may be more powerful, but am not so clear. Can you compare them from various aspects, and tell which should be used in what kind of occasions? What kinds of 开发者_StackOverflowthings can be done in one notation and not in the other?

Addition 1

Most of the answers so far seem to be claiming how erb is inefficient, and shouldn't be used when "#{ }" can be used. Now, let's ask the other way. Why can't the "#{ }" notation replace erb? Wouldn't it be much faster and better?

Addition 2

Most answers below seem to be assuming that a single occurance of "#{ }" does not span over multiple lines, so that a chunk of code like a loop taking multiple lines cannot be embedded within. But why not? If you do so, I don't see any difference from doing it with <% >, except that in the latter you put <% > in every line.


You're right that your ERB version should produce the same result as the normal version (I think), but its purpose is entirely different.

ERB is really just for templating: if you need to generate text (like an HTML page, or a document), some templating engine like ERB will be the right tool. It's not meant for simple string interpolation, though: while it certainly is capable of doing that, it's a rather periphrastic way of going about it. Indeed, you're actually creating an ERB object from a string, and then evaluating it back into a string.

You can get an idea of how very inefficient this is with a quick benchmark:

$ irb -rbenchmark -rerb
ruby-1.9.2-p136 :023 > Benchmark.bm do |bm|
ruby-1.9.2-p136 :024 >     bm.report 'interpolation' do
ruby-1.9.2-p136 :025 >       a = 'hello there'
ruby-1.9.2-p136 :026?>     5000.times { "well #{a}" }
ruby-1.9.2-p136 :027?>     end
ruby-1.9.2-p136 :028?>   bm.report 'erb' do
ruby-1.9.2-p136 :029 >       a = 'hello there'
ruby-1.9.2-p136 :030?>     5000.times { ERB.new("well <%= a %>").result(binding) }
ruby-1.9.2-p136 :031?>     end
ruby-1.9.2-p136 :032?>   end
      user     system      total        real
interpolation  0.000000   0.000000   0.000000 (  0.001495)
erb  0.340000   0.000000   0.340000 (  0.352098)
 => true 

The standard way to interpolate Ruby code into strings is using #{} within a string literal. This is built in at the language level (as opposed to at the library level).


Advantages to ERB:

  1. Everyone already knows and "loves" that PHP-like style
  2. You don't need to worry about balancing or escaping ' or "
  3. Typically you don't need to program the underlying Ruby mechanism, i.e., you don't need to define a method, possibly located in a class, perhaps qualified with a module, etc...

In the big picture, I believe the overall idea is to separate out the parts of a program that need to be done by a software developer from the part that a front-end web developer can do. For example, the software developer can simply specify that @account_number is available and it can be referenced by HTMLers without Ruby qualifications.

In real life, there seem to be a lot of one-person projects, but at least at one time the norm was to throw a team at a typical problem. Even today, look at all the Rails questions here on SO from developers that obviously know hardly any Ruby. And ERB predates Rails, so if you go back to the origins of the mechanism there was a time you really always needed a real software department because every project involved putting together a framework, so you probably didn't want to require Ruby software qualifications from every last member on the team.

Now, I do see what you mean. If you already know Ruby it's a lot harder to justify the erb ugliness.


One downside of trying to use ERB for general string interpolation is that ERB is really aimed at generating HTML. The result will be lots of encoding issues when you forget to raw-ify everything and get confused about why your ampersands, greater-than, less-than, etc. symbols are getting mangled.

I think there'll be more computational overhead for ERB as well but this might not matter.

Furthermore, if you put inlined ERB inside Ruby will end up with Ruby inside ERB inside Ruby (and quite possibly more levels as you call methods from within ERB) and that will be a bit of a confusing mess. Think of the poor souls that will have to maintain your code, said poor soul might even be you.

UPDATE: You could use #{} for simple HTML templates (see Mustache for something like that) but it would be difficult and rather ugly to produce a repeated section; repeated sections are quite common in HTML templates so that should be easy and natural for an HTML template system. With ERB, you can just:

<% a.each do |e| %>
    <!-- ... -->
<% end %>

but that would be a mess in #{} interpolation. You'd also end up doing #{html(blahblah)} all the time and most people would forget.

Also, "#" has a special meaning in URLs and a different special meaning in CSS (where braces also have a special meaning); fragment URLs and chunks of CSS are fairly common in HTML templates so you'd be constantly worrying about mixing up things up. This particular bit of nastiness would probably only be an issue when using #{} to produce a CSS selector or a fragment in a URL but that's enough to make it cumbersome.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜