Unicorn и Rails 2.3.5, а также bluepill и delayed_job
Читая одну замечательную статью по поводу использования bluepill для мониторинга delayed_job я решил углубиться и задал вопрос автору bluepill - а можно ли использовать его замечательную тулзу вместе с пассажиром, на что получил отрицательный ответ и предложение использовать unicorn. Все бы конечно хорошо, но при попытке запустить его с моим приложением на rails 2.3.5 я получил интересную ошибку:
I, [2010-03-03T22:33:14.466155 #65927] INFO -- : listening on addr=0.0.0.0:8080 fd=3
I, [2010-03-03T22:33:14.525494 #65927] INFO -- : worker=0 spawning...
I, [2010-03-03T22:33:14.526519 #65927] INFO -- : master process ready
I, [2010-03-03T22:33:14.528122 #65928] INFO -- : worker=0 spawned pid=65928
I, [2010-03-03T22:33:14.656300 #65928] INFO -- : Refreshing Gem list
Missing the Rails 2.3.5 gem. Please `gem install -v=2.3.5 rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.
особое внимание - на последнюю строчку
немного покопавшись в интернете выяснил, что конфликт вызван наличием в системе rack 1.1.* и использование rack 1.0.* решило проблему.
Установка rails3.beta на Windows
Буквально вчера меня и еще пару коллег окрестили сектантами за пропаганду продукции эппл, которая несмотря на свою "кривизну" (линк от еще одного коллеги пришелся очень даже в тему) занимает своё почетное место у меня на столе. Именно поэтому я решил написать небольшое руководство по установке rails 3 на windows-машине и теперь с нетерпением жду обвинений в сектантстве от php-кодеров
Ну что же - давайте приступим к делу. Покопавшись немного в интернете я нашел ряд рекомендаций от различных авторов и приступил к установке.
Первым делом надо поставить свежий ruby 1.9 и git. В первом случае мне пригодился rubyinstaller, а во втором - msysgit. Установили? Поехали дальше
Нам необходимо поставить все необходимые зависимости, поэтому
C:\>gem install tzinfo builder memcache-client rack rack-test erubis mail text-format thor bundler i18n
По идее еще надо бы установить rack-mount, но текущая версия 0.6.0 не понравилась actionpack-у, поэтому пришлось пойти у него на поводу и установить версию 0.4.0
C:\>gem install rack-mount --version 0.4.0
переходим к самому интересному
C:\>gem install rails --pre
Successfully installed actionpack-3.0.0.beta
Successfully installed arel-0.2.pre
Successfully installed activerecord-3.0.0.beta
Successfully installed activeresource-3.0.0.beta
Successfully installed actionmailer-3.0.0.beta
Successfully installed railties-3.0.0.beta
Successfully installed rails-3.0.0.beta
7 gems installed
Installing ri documentation for actionpack-3.0.0.beta...
Installing ri documentation for arel-0.2.pre...
Installing ri documentation for activerecord-3.0.0.beta...
Installing ri documentation for activeresource-3.0.0.beta...
Installing ri documentation for actionmailer-3.0.0.beta...
Installing ri documentation for railties-3.0.0.beta...
Installing ri documentation for rails-3.0.0.beta...
Installing RDoc documentation for actionpack-3.0.0.beta...
Installing RDoc documentation for arel-0.2.pre...
Installing RDoc documentation for activerecord-3.0.0.beta...
Installing RDoc documentation for activeresource-3.0.0.beta...
Installing RDoc documentation for actionmailer-3.0.0.beta...
Installing RDoc documentation for railties-3.0.0.beta...
Installing RDoc documentation for rails-3.0.0.beta...
Кажется все? А вот и нет - про базу данных забыли. Для тестов нам хватит sqlite3, а все остальное доставим позже, ок?
C:\>gem install sqlite3-ruby
Ну вот теперь можем приступить к самому приятному
C:\temp>rails test_app
Получилось? Отлично!!! Теперь попробуем запуститься ...
C:\temp\test_app>rails server
c:/Ruby19/lib/ruby/gems/1.9.1/gems/railties-3.0.0.beta/bin/rails:2: command not found: C:/temp/test_app/script/rails
c:/Ruby19/lib/ruby/gems/1.9.1/gems/railties-3.0.0.beta/bin/rails:2:in `exec': No such file or directory - C:/temp/test_app/script/rails (Err
no::ENOENT)
from c:/Ruby19/lib/ruby/gems/1.9.1/gems/railties-3.0.0.beta/bin/rails:2:in `'
from c:/Ruby19/bin/rails:19:in `load'
from c:/Ruby19/bin/rails:19:in `'
"WTF?" спросят меня читатели и будут совершенно правы. Эх, к хорошему быстро привыкают
Дело в том, что команда rails server вызывает script\rails напрямую и указания типа #!/usr/bin/env ruby просто напросто игнорируются. Удалось найти несколько способов решения этой проблемы
1. We could hack the railties bin\rails file to call this file with ruby.exe.
2. We could hack the railties bin\rails file to call rails.rb and rename script\rails to script\rails.rb. As long as we checked the box to associate .rb files with the Ruby interpreter while installing, this will work the way it was originally intended to.
3. In the short term, we can just substitute 'rails server' with 'ruby script\rails server', or 'rails generate scaffold test' with 'ruby script\rails generate scaffold test'.
Предлагаю использовать 3й вариант за его простоту:
C:\temp\test_app>ruby script\rails server
=> Booting WEBrick
=> Rails 3.0.0.beta application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-03-01 11:13:15] INFO WEBrick 1.3.1
[2010-03-01 11:13:15] INFO ruby 1.9.1 (2010-01-10) [i386-mingw32]
[2010-03-01 11:13:15] INFO WEBrick::HTTPServer#start: pid=5636 port=3000
ну вот вроде и все
В принципе - не так сложно
Rdoc in osx Dictionary
Буду краток
$ sudo gem install rdoc_osx_dictionary
Дарит счастье всем руби-программерам работающим под OSX

Cucumber + environment variables
В продолжение моего поста по поводу установки переменных окружения в тестовых сценариях - недавно столкнулся с необходимостью установки своих переменных окружения при использовании Cucumber + Webrat. Решается это элементарно - прописываем в *steps.rb файле
header('HTTP_ACCEPT_LANGUAGE', 'en')
Аналогично можно тестировать и использование https - есть очень хороший пример тут.
Rails I18n – презентация
Неплохая и самое главное познавательная презентация.
Примеры rails-приложений
Решил составить список open-source приложений на Rails, который как я надеюсь поможет начинающим (и не очень начинающим) программистам в написании красивого и функционального кода.
Redmine - система управления проектами
TeamBox - еще одна система для проджект-менеджмента, twitter-like
FatFreeCRM - CRM
Video App - аналог YouTube на Rails
Panda - еще одно приложение для стриминга видео
GemCutter - репозитарий gem'ов
CommunityEngine - Социальная сеть
LovdByLess - и еще одна социальная сеть
RailsCasts - ну кто не знает Ryan Bates и его RailsCast-ы? Это - исходники его блогового движка
Tracks - система GTD, управление задачами
Retrospectiva - снова проджект-менеджмент
Restful Authentication Tutorial - отличный туториал по реализации системы аутентификации, recaptcha, логгирование неудачных попытов аутентификации и многое другое
Shapado - аналог stackoverflow.net с использованием MongoMapper (thx 2 undr)
Open Source Rails - много различных приложений (thx 2 Alexey Osipenko)
Если у вас есть чем поделиться - присылайте, буду обновлять список
Custom HAML filters
На днях сделал набор кастомных HAML-фильтров, которые заменяют ссылки на youtube, vimeo, rutube, daylymotion на соответствующие видео. Использовать просто - ставим плагин, а дальше используем фильтры cbtextile, cbmarkdown или cbmaruku как обычные HAML-фильтры.
SSO на Rails с использованием Authlogic
Вопрос SSO для многих актуален, различных решений великое множество (OpenId, Oauth, CAS итд.), но иногда хочется сделать все по своему. Давайте попробуем написать свой SSO для наших сайтов?
Давайте для начала определим, что нам необходимо сделать:
1. Разработать центральный сервис аутентификации
2. Разработать сайт, который будет использовать SSO
2. Обеспечить доступность идентификатора сессии в рамках всех наших сайтов
3. Обеспечить доступность сессионных данных
4. Обеспечить доступность пользовательских данных
Давайте приступим к процессу разработки.
1. Первым делом нам необходимо реализовать сам сервис аутентификации. Про это уже много написано, например ознакомиться можно в соответствующем railscast или asciicast.
2. Думаю тут я могу обойтись без лишних комментариев, единственное что вам необходимо селать - это включить authlogic, создать модели User и UserSession:
class User < ActiveRecord::Base
establish_connection "auth_#{RAILS_ENV}"
acts_as_authentic
end
(на строку establish_connection пока не обращаем внимания - мы к ней еще подойдем
)
class UserSession < Authlogic::Session::Base
end
(обратите внимание на сложность данного класса
)
а также дополним ApplicationController базовым набором методов
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.record
end
def require_user
unless current_user
store_location
flash[:notice] = I18n.t(:"notices.require_logged_in")
redirect_to login_url
return false
end
end
def require_no_user
if current_user
store_location
flash[:notice] = I18n.t(:"notices.require_logged_out")
redirect_to dashboard_url
return false
end
end
# Store the URI of the current request in the session.
#
# We can return to this location by calling #redirect_back_or_default.
def store_location
session[:return_to] = request.request_uri
end
# Redirect to the URI stored by the most recent store_location call or
# to the passed default. Set an appropriately modified
# after_filter :store_location,
nly => [:index, :new, :show, :edit]
# for any controller you want to be bounce-backable.
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
2. Идентификатор сессии будем хранить в cookies. Для того, чтобы он был доступен для всех сайтов на домене *.example.com (auth.example.com, site1.exampe.com итд) нам по идее достаточно просто написать
ActionController::Base.session = {
:domain => ".example.org"
}
но знающие люди рекомендуют такой вот замечательный gist. Сохраняем его как файл
session_domain.rb в conf/initializers/, а также вносим небольшие изменения в session_store.rb:
ActionController::Base.session = {
:key => '_example_session',
:secret => 'oursupersecretkey'
}
Самое время перейти к следующему пункту
3. Не закрывая session_store.rb продолжаем вносить в него изменения:
ActionController::Base.session_store = :active_record_store
Для сайтов, которые будут использовать интерфейс SSO (а также если вы захотите вынести хранилище сессий в отдельную БД) порписываем в этом же файле
# Use sessions from preconfigured session store
ActiveRecord::SessionStore::Session.establish_connection("sessions_#{RAILS_ENV}")
а в файле database.yml:
# Sessions stores
sessions_development:
adapter: sqlite3
database: ../auth/db/development.sqlite3
pool: 5
timeout: 5000
sessions_test:
adapter: sqlite3
database: ../auth/db/test.sqlite3
pool: 5
timeout: 5000
sessions_production:
adapter: sqlite3
database: ../auth/db/production.sqlite3
pool: 5
timeout: 5000
4. Помните пару абзацев назад я просил не обращать внимания на строчку кода? Самое время к ней вернуться. Класс User будет использовать соединение с БД нашего сервиса аутентификации для получения информации о текущем пользователе. Обновим данные в database.yml:
auth_development:
adapter: sqlite3
database: ../auth/db/development.sqlite3
pool: 5
timeout: 5000
auth_test:
adapter: sqlite3
database: ../auth/db/test.sqlite3
pool: 5
timeout: 5000
auth_production:
adapter: sqlite3
database: ../auth/db/production.sqlite3
pool: 5
timeout: 5000
Вот в принципе и все
Не сложно, правда? Теперь на site1.example.com мы спокойно сможем работать с current_user и пользовательской сессией.
PS: Возможно решение не идеальное, но с удовольствием рассмотрю все ваши рекомендации по его оптимизации
Plugins. rails-footnotes, correct-format, custom-err-msg, jrails
Продолжаю тему про рельсовые плагины.
rails-footnotes добавляет в ваше приложение, если оно запущено в development mode некий футер, который содержит в себе выдержку из логов, данные о сессии, куках, переданных параметрах, ссылки для редактирования модели, вьюхи и контроллера, css, javascript итд. Также у вас есть возможность увеличивать количество отображаемых данных.
correct-format - автоматически "причесывает" передаваемую в модель информацию - заменяет в адресах email "," на "ю", изменять автоматом регистр вводимых данных итд. Пример использования:
class User < ActiveRecord::Base
# Make usernames consistently lower case
correct_format_downcase :username
# Replace comma's with periods in email address, and make email address all lower case
correct_format_email :email
# Capitalize first letter of first word, and downcase the rest
correct_format_capitalize :username
# Capitalize all first letters of ALL WORDS in the string
correct_format_capitalize_each :address_line_1, :address_line_2
# UK Postcodes are upper case
correct_format_upcase :postcode
# apply a function to EVERY string field in a record
correct_format_capitalize self.attributes.select{|k, v| self.column_for_attribute(k).type == :string }.map(&:first)
end
custom-err-msg - плагин, позволяющий корректировать вывод сообщений об ошибке. Например если
validates_acceptance_of :accepted_terms, :message => 'Please accept the terms of service'
отобразит "Accepted terms Please accept the terms of service", то с установленным плагином и
validates_acceptance_of :accepted_terms, :message => '^Please accept the terms of service'
сообщение будет отображаться чуть лучше - "Please accept the terms of service"
Ну и последний плагин на сегодня, про который наверняка все уже слышали - jrails, позволяющий легко перейти от использования prototype и script.aculo.us на jquery.
Plugins. acl9, acts_as_textiled, app_config
Этим постом я начинаю серию постов, объединенных одной темой - это плагины в Rails.
Начну я пожалуй с app_config, плагина написанного нашим соотечественником - Женей Большаковым (taknado.com). Женя в своем плагине реализовал идею Димы Штефлюка и сделал это надо сказать весьма успешно
Использовать плагин очень просто. Первым делом создаем файл config/config.yml с содержанием подобным
common:
admin_email: admin@domain.com
xml_rpc_url: http://domain.com:8000/
media_path: <%= RAILS_ROOT %>/tmp/media
development:
xml_rpc_url: http://localhost:8000/
test:
xml_rpc_url: http://localhost:8008/
В группе common размещаем общие для всех environments параметры, в production/development/test - соответствующие названию. Доступ к параметрам можно получить через Conf.variable_name, где variable_name - это и есть наш конфигурационный параметр.
Еще один плагин - acl9, также написанный нашим сооттечественником - Олегом Дашевским. Это плагин, позволяющий организовать role based-аутентификацию, но в отличии от популярного role requirement - более гибкий в плане интеграции с плагинами авторизации типа authlogic, twitterauth и другими плагинами. Ничто не мешает вам написать свой функционал, использующий например протокол oauth для авторизации и вместе с acl9 обеспечить удобную систему управления доступом. Как пользоваться плагином можно узнать из его страницы на github.com и из тестового приложения.
И последний плагин на сегодня - acts_as_textiled, автором которого является Chris Wanstrath. С помощью этого плагина можно пометить то или иное поле в модели, что оно использует textile для разметки. Достаточно просто в модели указать
class Story < ActiveRecord::Base
acts_as_textiled :body_text, :description
end
и в дальнейшем данное поле будет рендериться на лету в html.
На сегодня пожалуй все
Удачи
Link Shot #8
Ruby on Rails
Секреты rails console
Немного про интеграцию ftp и приложений на ror
Flex
Тестирование Flex-приложения с помощью Cucumber, часть 2
Tip: тесты и переменные в Rails
Не так давно, при тестировании экшна, на котором висит вот такой before_filter мне пришлось столкнуться с проблемой - дело в том, что установить переменные request.headers['HTTP_ACCEPT_LANGUAGE'] и request.host не предоставлялось возможным - headers и host могут выступать только как getter'ы. Решение оказалось достаточно простым - в тесте пишем метод setup, в котором прописываем
@request.env['HTTP_ACCEPT_LANGUAGE'] = "ru"
@request.env['HOST'] = "somehost.ru"
Пара плагинов для RoR
1. При использовании замечательного плагина friendly_id есть вероятность того, что сгенерированный slug будет совпадать с именем вашего экшна. Как вариант - можно составить список экшнов и прописать их как :reserved, но можно сделать проще - генерировать свои slug'и (например добавлять id модели):
has_friendly_id :title, :use_slug => true do |text|
self.id.to_s + "-" + text
end
2. Очень полезный и удобный плагин meta-tags (by kpumuk) продолжает идеи Ryan Bates, описанные им в одном из railscasts - очень полезен для тех, кто заботится о SEO сайта.
Rails Magazine #3
Вышел новый выпуск электронного журнала Rails Magazine.
В номере:
* Create a code snippet app
* Working on a typical Open Source Rails project
* Theme Support
* Observer and Singleton design patterns
* JRuby monitoring with JMX
* Ruby Web Frameworks: A Dive into Waves
* How to Implement Automated Testing
* Ruby on Rails & Flex
* Workflow solutions with AASM
Chris Wanstrath (founder of Github) shares his learnings in building a successful business with Open Source.
Interviews with Carl Mercier, Ilya Grigorik and Ryan Singer.
Чем вы тестируете ваши рельсовые приложения?
Собственно говоря - опрос
Если вы напишите почему был выбран тот или иной вариант - был бы очень признателен
Сам лично использую Test::Unit


