2012-04-18 3 views
2

У меня очень простой вопрос с Ruby. Есть ли способ, чтобы реорганизовать это:Ruby If Statement Refactoring

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

в нечто вроде

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

, где «я» (например) является ссылкой изначально рассчитанное значение - т.е. some_array.length?

+0

Это относится к [Обзор кодов] (http://codereview.stackexchange.com/). –

+1

@Matheus, я бы сказал, что это нормально, это очень конкретный прецедент, а не обзор кода. – tokland

ответ

1

Я хотел бы сохранить основные шаблоны простой и тянуть логики в помощниках. Эрб может содержать:

<%= display_length(some_array) %> 

где помощник содержит:

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

Конечно, настроить имена лучше всего представить свой бизнес-логику.

5

Нет, вы не можете этого сделать. Заявление не оценивает слева направо так, как вы предполагаете. Сначала вычисляется оператор if, поэтому нет «я» для тестирования. «Первоначально рассчитанное значение», как вы выразились, рассчитывается в начале по заявлению if.

+0

У меня было ощущение, что это так. @Mark Thomas: Я закончил тем, что использовал вашу оценку. Благодаря обоим! – neon

1

, если вы не хотите, чтобы вычислить его 2 раз, когда вы можете сделать это, как этот

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

еще вы можете создать вспомогательный метод. Первоначальный вопрос является немного вводит в заблуждение, потому что левая сторона, если не будет вычисляться, прежде чем с правой стороны, так что даже если вы могли бы пройти «вашей собственной личности», как вычисленное значение представьте (код псевдо):

people.destroy_all if self > 100 

Это вычислит разрушение всегда чтобы произвести "вашу собственную личность": D

0

A. Вы можете сделать что-то вроде этого

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

B. Вы можете использовать Presenter pattern

0

Возможно:

length if (length = some_array.length) > 1 

Немного эзотерический, но короче ...

+0

Боюсь, что 'length' получит результат' some_array.length> 1' (true или false). Вам нужно заключить в скобки. –

+0

Хорошая точка, спасибо! Shifted paran –

-2
class Object 
    def block_scope 
    yield self 
    [] # Required for HAML and probably ERB as well 
    end 
end 

Еврорадио:

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

HAML:

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

Немного лучше визуально, чем простое назначение

UPDATE

Согласитесь, что добавление block_scope к Object имен, безусловно, избыточна для представлений, гораздо лучшим решением было бы создание помощника:

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

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

Это совершенно гротескное решение. Это более подробный, чем простой оператор 'if' и имеет чрезвычайно грубый побочный эффект от загрязнения каждого отдельного объекта с помощью универсального метода, который бесполезен в 99,999% случаев. Он не достигает ни одной цели - меньше набирать или меньше оценок 'array.length'. Что касается «визуально лучшего», это довольно субъективно, но я думаю, что вы тоже ошибаетесь в этом вопросе; это уродливо, как грех. Для этого нужны помощники. Извините, если это звучит жестко, но важно убедиться, что новые рубисты не считают это хорошим решением. – meagar

+0

@meagar. Я выполняю меньшее количество оценок (не имеет большого значения для длины Array #), но, как правило, мы не говорим об однострочном блоке, он может быть полезен для больших блоков, особенно при деструкции аргументов. Однако не ясно из этого примера. –

0

Лучшее, что вы можете сделать что-то более-менее, как это:

t = some_array.length; t if t > 1 

Также обратите внимание, что интерполированные выражения ERB, которые являются условными (без else), возвращают значение в одном случае и nil в другом случае. Реализация ERB будет оцениваться в result.to_s и #to_s на nil производит «». Таким образом, это эффективный шаблон дизайна, но, возможно, его не так легко понять всем читателям кода, которые появятся позже.