neon
neon

Reputation: 2821

Ruby If Statement Refactoring

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

Answers (7)

Victor Moroz
Victor Moroz

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

Brian Underwood
Brian Underwood

Reputation: 10856

Perhaps:

length if (length = some_array.length) > 1

A bit esoteric, but shorter...

Upvotes: 0

DigitalRoss
DigitalRoss

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

Mark Thomas
Mark Thomas

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

fl00r
fl00r

Reputation: 83680

A. You can do something like this

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

B. You can use Presenter pattern

Upvotes: 0

Jakub Oboza
Jakub Oboza

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

user229044
user229044

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

Related Questions