Reputation: 2821
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?
Upvotes: 2
Views: 363
Reputation: 9225
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
Upvotes: -2
Reputation: 10856
Perhaps:
length if (length = some_array.length) > 1
A bit esoteric, but shorter...
Upvotes: 0
Reputation: 146231
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.
Upvotes: 0
Reputation: 37527
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.
Upvotes: 1
Reputation: 83680
A. You can do something like this
<%= l = some_array.length if l > 1 %>
B. You can use Presenter pattern
Upvotes: 0
Reputation: 5421
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
Upvotes: 1
Reputation: 239521
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.
Upvotes: 5