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

def enclose_in_single_quotes(string)
  string.split(/'/, -1).map{|e| "'#{e}'"}.join("\\'")
end

enclose_in_single_quotes("ilya'") # => 'ilya'\'''
enclose_in_single_quotes("super'bla'test") # => 'super'\''bla'\''test'

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

Если вы пользовались rescue_from, то наверное замечали, что по какой-то причине исключения иногда проскакивают необработанными. Причина оказалась весьма простая. Все исключения, которые возникли во вьюшках, всегда оборачиваются абстрактным ActionController::TemplateError и таким образом становятся невидимыми для всех ваших rescue_from хендлеров. Это не очень удобно, потому-что никогда нельзя сказать с точностью где некоторые исключения могут возникнуть, а где нет.

В общем сегодня как раз решал такую проблему в Бинстолке и решил сделать из своего решения маленький плугин. Плугин получился очень простой, всего пару строчек кода, зато работает как надо. Теперь все исключения, не важно где они выпрыгнули — во вьюшках или контроллерах — будут прекрасно обрабатываться вашими rescue_from хендлерами.

Читайте ридми на гитхабе и пользуйтесь на здоровье:

http://github.com/iSabanin/rescue_from_templates_exceptions/tree/master

P.S. — если вы считаете что этот плугин должен быть частью Rails Core, пишите в комментариях своё мнение.

Всем известно как изменить текст сообщения об ошибке валидации модели. Но не всем известен трюк, как изменить само название атрибута, которое будет отображаться в сообщении об ошибке. Рельсы, к сожалению, нам не предоставляют простого пути решения.

Итак, проблема:

Сообщение об ошибке на русском языке, в то время как название атрибута на английском (причём часто на ломаном английском, потому-что название определяется автоматом по названию поля в базе).

Для того чтобы решить эту проблему, нам понадобиться один маленький файлик — humanized_attributes.rb. Бросаем его в lib/ и подключаем в environment.rb.

Далее в нашей модели создаём константу HUMANIZED_ATTRIBUTES:

class User < ActiveRecord::Base

  HUMANIZED_ATTRIBUTES = {
    :login => "Имя пользователя" 
  }

  validates_presence_of :login, :message => 'отсутствует'

end

И вуаля:

На самом деле это удобно не только для русифицирования атрибутов, но и когда заказчик хочет чтобы «login» отображался как «user name».

Для пущего удобства, можно обернуть всё это дело плугином с каким-нибудь прикольным DSL, вместо константы.

redirect_to :back

Илья • 22 мая 2008 г.

Оказывается метод redirect_to может принимать аргумент :back.

def destroy
  …
  redirect_to :back
end

Теперь пользователь будет переброшен обратно на ту страницу, с которой пришёл запрос на destroy.

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

Дружим Ruby со Spotlight и Quicklook

Илья • 21 декабря 2007 г.

Дейв Томас не так давно наткнулся на очень интересный плагин для поисковой системы Spotlight, встроенной в Мак ОС. После установки, плагин позволяет искать по модулям, классам, методам и комментариям в любых файлах Ruby, находящихся на вашем Маке. Великолепная штуковина!

Если есть желание попробовать, то качаем Ruby Importer 0.2.1, затем копируем файл RubyImporter.mdimporter в папку /Library/Spotlight (папку возможно придётся создать).

Далее, в терминале нужно запустить следующую команду, чтобы заставить спотлайт заметить новый плагин и проиндексировать с помощью него все Ruby-файлы в домашней директории:

$ mdimport -L && mdimport -r /Library/Spotlight/RubyImporter.mdimporter ~/

Теперь можно приступать к поиску:

А для того чтобы исходники Ruby (и других языков) можно было просматривать с подсветкой кода при помощи Quicklook, нужно установить отдельный плагин для квиклука QLColorCode.

Очень маленький, но весьма полезный трюк, который лично я открыл для себя только сегодня:

$ rake -T clear
(in /Users/ilya/work/application)
rake db:sessions:clear   # Clear the sessions table
rake log:clear           # Truncates all *.log files in log/ to zero bytes
rake tmp:cache:clear     # Clears all files and directories in tmp/cache
rake tmp:clear           # Clear session, cache, and socket files from tmp/
rake tmp:pids:clear      # Clears all files in tmp/pids
rake tmp:sessions:clear  # Clears all files in tmp/sessions
rake tmp:sockets:clear   # Clears all files in tmp/sockets

То есть, после rake -T можно написать любое интересуемое вас слово, в данном случае clear. И тогда на экран выведутся только задачи в названии которых это слово встречается.

За открытие спасибо Антонюку Стасу ;)

Upd: Переписал описание и пример. Как оказалось позднее, выводятся не только задачи, у которых именная область совпадает с введённым словом, но и вообще все задачи, в название которых это слово включено.

Приятное обновление error_messages_for

Илья • 14 октября 2007 г.

В Edge Rails и Rails 2.0 теперь можно указывать допонительные параметры методу error messages for, который выводит ошибки валидации во вьюшках:

  1. :header_message По умолчанию: “<count> errors prohibited this <object_name> from being saved”
  2. :message По умолчанию: “There were problems with the following fields:"

<%= error_messages_for :user, 
  :header_message => "#{@user.errors.size} ошибок сохранения этого пользователя", 
  :message => "Следующие поля заполнены не верно:" %>

Так что теперь можно спокойно использовать эту удобную функцию в русских проектах.

Changeset #7870

Не так давно в распоряжении Rails-программистов появился метод form for, который позволяет сэкономить пару строчек кода, во время написания шаблонов форм. Используя этот метод, мы можем превратить такой стандартный шаблон:


<% form_tag users_path do %>
  <%= text_field :user, :name %>
  <%= text_field :user, :email %>
<% end %>

в такой:


<% form_for :user, :url => users_path do |f| %>
  <%= f.text_field, :name %>
  <%= f.text_field, :email %>
<% end %>

Используя form_for, больше нету необходимости указывать более чем один раз кому принадлежит то или иное поле. Это уменьшает количество повторений в вашем коде, то есть делает его более DRY.

Но что делать, если вы хотите использовать сразу несколько моделей в рамках одной формы? В такой ситуации нам на помощь придёт метод fields for, который переопределяет объект, к которому будут принадлежать поля, находящиеся в его блоке.

Всё просто, давайте разберём следующий пример. В одной и той же форме мы хотим редактировать данные и пользователя, и его кредитной карты:


<% form_for :user, :url => users_path do |f| %>
  <%= f.text_field, :name %>
  <%= f.text_field, :email %>

  <% fields_for :credit_card do |cf| %>
   <%= cf.text_field :number %>
   <%= cf.text_field :holder_name %>
  <% end %>

<% end %>

Используя fields_for в примере выше, мы получили возможность описать сразу две модели в одной форме. Теперь в контроллере у нас доступны и params[:user] и params[:credit_card].

Эта тема так же подробно раскрывается в эпизоде 73 от Railscasts.

Несколько компактных примеров о том, как можно разбивать длинные выражения в руби на несколько строк.


User.create! \
  :name => 'Вася',
  :password => '12345',
  :login => 'vasya'

name = first_name +
       last_name +
       middle_name

name = "Sabanin" \
       " Ilya" \
       " Vladimirovich"  
# name => "Sabanin Ilya Vladimirovich" 

array.
  find_all {|e| e.position > 5}.
    map {|e| e.symbol}.
      join('/').
        downcase

Безопасность Rails: фильтрация логов

Илья • 25 сентября 2007 г.

Если в вашем приложении используются такие важные данные как номера кредитных карт или пользовательские пароли, то вам стоит фильтровать свои логи, в которые эта секретная информация просачивается.

Сделать это очень просто. Достаточно вставить следующую строку в ApplicationController:


class ApplicationController < ActionController::Base
  filter_parameter_logging :password
end

В метод filter_parameter_logging через запятую передаются названия всех параметров, которые вы не хотите отображать в логах. Вы можете вызвать этот метод в любом контроллере, где должна совершаться фильтрация логов.

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

Вот как выглядят логи с отфильтрованным параметром :password:

Processing AccountsController#login (for 127.0.0.1 at 2007-09-25 03:56:02) [POST]
  Session ID: 66e0c98d03cc80433cecfe3cf76f65aa
  Parameters: {"login"=>"vasya", "password"=> "[FILTERED]", 
               "password_confirmation"=> "[FILTERED]"}

Берегитесь операторов and, or и not в Ruby

Илья • 21 сентября 2007 г.

С виду безобидные операторы and,  or  и not могут привести к очень загадочным ошибкам в вашем приложении.

Вот две строчки одинакового кода. В первой строке используются операторы ||  и &&, а во второй операторы  or  и and. Как видите, результат не совпадает:

Всё потому-что в таблице приоритетов операторов в Ruby, оператор && стоит выше оператора ||, в то время как операторы and  и  or находятся на одном уровне.

Что самое неприятное, операторы and  и  or стоят по приоритету даже ниже чем оператор =, а это может создать в коде ошибки следующего типа:

По-скольку оператор = имеет больший приоритет, чем оператор  or, руби сначала присваивает значение false переменной value, а затем сравнивает её со значением true. Получается, что вместо значения true в переменной value, мы получаем значение false.

Такой же код, но с оператором || вместо  or:

Теперь всё работает как надо.

Итак, старайтесь заменять операторы and,  or  и not  на &&, ||  и !. Конечно, вторая тройка не такая красивая и читабельная, но читабельность того не стоит.

Один маленький нюанс :counter_cache

Илья • 18 июля 2007 г.

Если вы хотите использовать :counter_cache для своих ассоциаций, не забудьте что поле, в котором будет хранится количество связей, должно иметь дефолтовое значение 0, а не NULL, как это иногда бывает по-стандарту.

class AddCounterCaches < ActiveRecord::Migration
  def self.up
    add_column :posts, :comments_counter, :integer, :default => 0
  end

  def self.down
    remove_column :posts, :comments_size
  end
end

Сегодня в порыве продуктивно-оптимизационной истерии нашел удобный способ отображать проект в Textmate Drawer.

Превратил такой, “стандартный” вариант:

В такой:

Суть такая, создаем новый проект, из Finder перекидываем содержимое app/ в Drawer. Это то, что мы используем чаще всего. Следом создаем в Drawer новую группу – rails root, куда засовываем всё остальное.

Кстати, вы знали что по запросам в Гугле продуктивность популярней чем порно? vs.

Часто бывает, что вы создаёте новый рельсовый проект, несколько моделей для начала и даже пару миграций, но, ничего не спасёт вас от того, чтобы создать базу данных самостоятельно. Теперь же, достаточно только написать rake db:create и всё готово! А если вы хотите наоборот удалить базу данных, то rake db:drop ваш помощник. Но самое интересное начинается тогда, когда вы хотите полностью пересоздать базу данных и перезапустить для неё миграции — rake db:reset и вуаля!

Итак, три новых рейка для баз данных:

rake db:create
rake db:drop
rake db:reset

Ну и, разумеется, вы можете указывать над какой именно базой данных будут производится действия, указывая переменную RAILS_ENV перед запуском рейка:

RAILS_ENV=test rake db:create

Так же, когда вы используете rake db:reset, вы можете указать до какой версии базу нужно мигрировать:

rake db:reset VERSION=15

Уже несколько лет работаю на Маке в редакторе TextMate и до сих пор не знал о существовании такой замечательной незаменимой штукенции как TextMate Footnotes. Надеюсь и вы не знали :)

TextMate Footnotes это плугин для рельсов и его нужно устанавливать отдельно для каждого вашего веб-приложения, после чего, когда вы зайдёте в своё веб-приложение через браузер, вы увидите внизу страницы небольшое серое меню с потрясающе удобными ссылками: Controller, View, Layout, Stylesheets, Javascripts. Первые три ссылки откроют для вас прямо в ТекстМейте вьюшку, контроллер или лейаут данного действия, которое вы смотрите в браузере. Это потрясающе удобно! А ссылки stylesheets и javascripts выведут на страницу маленький аккуратный списочек используемых на данной странице стилей и скриптов.

Более того, используя Footnotes, можно просмотреть содержание сессии, куков, params и последние 200 строк логов.

Как всё это выглядит, можно посмотреть на фликре.

В общем, Footnotes позволяют экономить очень много времени и тем самым реально увеличивают продуктивность.

Кстати, идея эта, судя по всему, была взята из фреймворка Seaside, только на сиасайде она ещё круче в несколько раз.

А теперь, заходим в своё супер-крутое веб-приложение, которое не сегодня, завтра изменит весь мир, и устанавливаем плугин TextMate Footnotes:

script/plugin install -x http://macromates.com/svn/Bundles/trunk/Bundles/Rails.tmbundle/Support/plugins/footnotes

Перезапускаем веб-сервер (ну на всякий случай) и смотрим что из этого получилось в браузере :)