rails/ruby "и вернуть false"
Я видел этот код в учебнике по рельсам, который я делаю
def access_denied
redirect_to login_path, :notice => "Please log in to continue" and return false
end
Прежде чем изучать рельсы, я сделал большое количество исследований рубинов, и ни одна из прочитанных мной книг не охватывала этот "синтаксис" и "возвращает ложный". Я не могу найти упоминания об этом в синтаксисе rails, может ли кто-нибудь предоставить ссылку или какое-либо объяснение, которое прояснит это?
Я не понимаю необходимость "и" здесь, поскольку я думал, что ruby всегда будет возвращать последнее оцениваемое выражение.
Ответы
Ответ 1
И есть только для вас, чтобы иметь возможность написать возвращение ложного в той же строке, что и предыдущее выражение.
Это эквивалентно этому:
redirect_to login_path, :notice => "Please log in to continue"
return false
это не совсем то же самое, потому что с "и" оно вернет false только в том случае, если метод redirect_to возвращает то, что не является нильским или ложным, но поскольку оно почти всегда возвращает то, что не является нилным или ложным, то правая часть утверждения всегда выполняется (и возвращается false).
В Ruby и Ruby это просто псевдоним && и ведет себя точно так же, как и с одним отличием, он имеет более низкий приоритет, чем все остальные части выражения, поэтому сначала он оценивает все, что на нем слева, а затем применяется. Ruby также имеет или который совпадает с || но с более низким приоритетом в выражениях.
Ответ 2
redirect_to login_path, :notice => "Please log in to continue"
- это нормальное выражение в Ruby, которое не возвращает false (или nil, см. исходный код), поэтому выполнение программы продолжается (чтобы проверить вторую часть после AND) и return false
может быть выполнено.
Ответ 3
Такая конструкция использовалась с фильтром, когда ожидались значения возврата фильтра. false
остановит обычную обработку запроса.
Поэтому, если контроллер выглядит так:
class FooController < ActionController::Base
before_filter :access_denied
# etc.
end
Ни одно из действий контроллера не будет работать; этот метод, вероятно, предназначен для вызова из фильтра, например:
def check_access
return access_denied unless current_user.has_access
end
В эти дни значения возврата фильтра игнорируются.
Он может использоваться как обычный метод в действии, чтобы прекратить обработку действия и вернуть после перенаправления, поэтому никакой другой логики/рендеринга /etc. запускается внутри контроллера.
Ответ 4
Документация по операторам: в разделе "Определено?" И "Или" и "Нет"
Использование and
полезно для объединения связанных операций вместе, пока один из них не возвращает nil
или false
. Вы можете использовать его, как вы показали в своем вопросе, или вы также можете использовать его для короткого замыкания строки кода.
# Short circuit example
blog = Blog.find_by_id(id) and blog.publish!
Блог только получает .publish!
вызвал его, если find_by_id
был успешным.
В вашем примере:
def access_denied
redirect_to login_path, :notice => "Please log in to continue" and return false
end
Они просто используют его для записи кода более компактно на одной строке.
Тем не менее, он также полезен для действия контроллера, где вы можете выполнять рендеринг на основе условных выражений, и вы не хотите получать предупреждения Rails "multiple Renders":
def show
if something
render :partial => 'some_partial'
end
render :partial => 'some_other_partial'
end
Rails даст вам предупреждение, если something
вернет true, так как в действии есть несколько выражений рендеринга. Однако, если вы изменили его на
if something
render :partial => 'some_partial' and return
end
это позволит вам остановить выполнение действия.