2

I have a very simple Ruby question. Is there a way to refactor this:

<%= some_array.length if some_array.length > 1 %>

into something like

<%= some_array.length if self > 1 %>

where 'self' (for example) is references the initially calculated value - i.e. some_array.length?

2
  • This belongs on Code Review. Commented Apr 18, 2012 at 15:33
  • 1
    @Matheus, I'd say SO is ok, it's a very specific use case, not review of code. Commented Apr 18, 2012 at 15:38

7 Answers 7

5

No, you can't do this. The statement doesn't evaluate left-to-right in the way you're assuming it does. The if statement is evaluated first, so there is no "self" to test. The "initially calculated value" as you put it, is calculated first by the if statement.

Sign up to request clarification or add additional context in comments.

1 Comment

I had a feeling this was the case. @Mark Thomas: I ended up using your appraoch. Thanks to both!
1

I like to keep the main templates simple and pull logic into helpers. The erb can contain:

<%= display_length(some_array) %>

where the helper contains:

def display_length(array)
  array.length if array.length > 1
end

Of course, adjust the names to best represent your business logic.

Comments

1

if you don't want to compute it 2 time you can do it like this

<% len = some_array.length %>
<%= len if len > 1 %>

else you can create helper method. Initial question is bit misleading because left side of if will not be computed before right side so even if you could pass "your self" as computed value imagine (your pseudo code):

people.destroy_all if self > 100

This will compute destruction always to produce "your self" :D

Comments

0

A. You can do something like this

<%= l = some_array.length if l > 1 %>

B. You can use Presenter pattern

Comments

0

The best you can do is something more-or-less like this:

t = some_array.length; t if t > 1 

Also, note that interpolated ERB expressions that are conditional (without an else) will return the value in the one case and nil in the other case. The ERB implementation will evalute result.to_s and #to_s on nil produces "". So, it's a workable design pattern but perhaps not easily understood by all the code readers that will come later.

Comments

0

Perhaps:

length if (length = some_array.length) > 1

A bit esoteric, but shorter...

1 Comment

I'm afraid that length will get the result of the some_array.length > 1 then (true or false). You need to parenthesize it.
-2
class Object
  def block_scope
    yield self
    [] # Required for HAML and probably ERB as well
  end
end

ERB:

<% array.length.block_scope do |l| %>
  <%= l if l > 1 %>
<% end %>

HAML:

- array.length.block_scope do |l|
  = l if l > 1

A little better visually than simple assignment

UPDATE

Agree that adding block_scope to Object namespace is definitely overkill for views, much better solution would be creating a helper:

def block_scope(*args)
  yield *args
  [] #?
end

- block_scope(array.length) do |l|
  = l if l > 1

2 Comments

This is an utterly grotesque solution. It's more verbose than a simple if statement and has the extremely gross side-effect of polluting every single object with a generically named method that is useless 99.999% of the time. It doesn't accomplish either goal of less typing or fewer evaluations of array.length. As far as being "visually better", this is pretty subjective, but I think you're dead wrong on that point too; it's ugly as sin. This kind of things is what helpers are for. Sorry if this sounds harsh, but it's important to make sure new Rubyists don't think this is a good solution.
@meagar I does accomplish fewer evaluations (doesn't make much sense for Array#length though), besides generally we are not talking about one-line block, it can be useful for bigger blocks, especially with argument destructuring. It is not clear from this example though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.