Ловим exception внутри выражений

Илья • 28 января 2007 г.

Век живи, век учись.

Не так:
if @user.name
  @user.name.capitalize
else
  "name not set"
end
И не так:
@user.name? ? @user.name.capitalize : "name not set"
И даже не так:
begin
  @user.name.capitalize
rescue
  "name not set"
end
А вот так:
@user.name.capitalize rescue "name not set"

Красота…

Update: Привёл немного не подходящий пример в прошлый раз: @user.name обычно не возвращает исключение, поэтому этот метод тут не поможет.

Another update: На самом деле этот хак не стоит воспринимать слишком серьёзно. Есть большая вероятность того, что вы не поймаете какое-нибудь действительно важное исключение, которого вы не ожидали.

Что окончательно устарело в Rails

Илья • 27 января 2007 г.

Rails очень быстро меняется. Не успеваешь закончить писать приложение, как оно уже устарело :) Хочу написать несколько очевидных маленьких штуковин, которые уже достаточно давно устарели, но не смотря ни на что, всё равно продолжают использоваться программерами.

Во-первых, следующие переменные давно уже нужно использовать как методы, то есть без знака @:

Было:
@request, @response, @session, @headers, @template, @cookies и @flash
Стало:
request, response, session, headers, template, cookies и flash

ActionController:

expire_matched_fragments()        → expire_fragment()
keep_flash()                      → flash.keep()
redirect_to_path()                → redirect_to(path)
redirect_to_url()                 → redirect_to(url)

ActionView:

@content_for_layout               → yield
@content_for_some_fragment        → yield :some_fragment
link_image_to()                   → link_to(image_tag())
link_to 'Bla bla', :post => true  → link_to "Bla bla", :method => "post"
render_partial                    → render :partial
render_partial_collection         → render :partial => 'bla', :collection => @b
human_size()                      → number_to_human_size()
start_form_tag(); end_form_tag()  → form_tag :action => "bla" do
                                      text_field 'bla', 'bla'
                                     end

ActiveRecord:

:dependent => true                → :dependent => :destroy
:exclusively_dependent => true    → :dependent => :delete_all
find_all()                        → find :all
find_first()                      → find :first

Update: Александр Сенько напомнил, что:

Вызывать следующие методы в вашем контроллере больше не нужно, рельсы теперь делают это автоматом:
model; service; observer; depend_on; dependencies_on

Ничего не забыл?

Наблюдаем за ActiveRecord

Илья • 26 января 2007 г.

Небольшая, но приятная находка, которая позволяет следить за тем что делает ActiveRecord прямо из script/console.

$ script/console
>> ActiveRecord::Base.logger = Logger.new(STDOUT)
=> #<Logger:0x2814134 ...>
>> user = User.find :first
  User Load (0.000346)   SELECT * FROM users LIMIT 1
=> #<User:0x2665478 ...>

По-поему очень удобно.

Именные роуты

Илья • 26 января 2007 г.

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

link_to "Vasya Pupkin", :controller => "users", :action => "show", :id => user

Особенно не приятно, когда такая длиннющая конструкция встречается в проекте много раз. В этой ситуации нас выручат именные роуты. И вот как они работают в двух словах:

В config/routes.rb создаём новое правило:
map.user "users/:id", :controller => "users", :action => "show"

Заметьте, что вместо привычного map.connect, я использовал map.user. А это значит, что теперь в любом уголке своего приложения я могу использовать метод user_url(user), который вернёт мне :controller => ‘users’, :action => ‘show’, :id => user.id.

Теперь переписываем нашу ссылку, для использования с новеньким именным роутом:

link_to "Vasya Pupkin", user_url(@user)

Не правдо ли так гораздо чище и быстрее?

А теперь, перед тем как создать два десятка красивеньких именных роутов и избавиться от трёхэтажных link_to, посмотрите что ещё можно сделать.

Это работает не только с роутами, но и с любыми методами, которые принимают в виде аргументов хеш (сейчас это жутко модно). Если у нас подряд идёт вызов нескольких методов и в них передаются почти одинаковые хеши, то мы можем их объеденить при помощи метода #with_options. Вот, например, три обычных именных роута:

map.users "/users", :controller => "users", :action => "list"
map.user "/users/:id", :controller => "users", :action => "show"
map.deadsouls "/users/deads", :controller => "users", :action => "dead"

Как видите, все они ссылаются на один и тот же контроллер — users. Получается не очень DRY (Dont Repeat Yourself). Тут то и приходит на помощь прекрасный #with_options:

map.with_options :controller => "users" do |users|
  users.users "/users", :action => "list"
  users.user "/users/:id", :action => "show"
  users.deadsouls "/users/deads", :action => "deads"
end

Теперь кусок :controller => “users” передаётся во все роуты, хотя написали мы его только один раз.

Заметка написана по мотивам блога великолепного Jamis Buck.