C4 always sleepy

3Mar/100

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.* решило проблему.

1Mar/100

Установка 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

ну вот вроде и все :) В принципе - не так сложно :)

5Feb/100

Rdoc in osx Dictionary

Буду краток

$ sudo gem install rdoc_osx_dictionary

Дарит счастье всем руби-программерам работающим под OSX

Tagged as: , , , No Comments
25Jan/100

Cucumber + environment variables

В продолжение моего поста по поводу установки переменных окружения в тестовых сценариях - недавно столкнулся с необходимостью установки своих переменных окружения при использовании Cucumber + Webrat. Решается это элементарно - прописываем в *steps.rb файле

header('HTTP_ACCEPT_LANGUAGE', 'en')

Аналогично можно тестировать и использование https - есть очень хороший пример тут.

25Jan/100

Rails I18n – презентация

Неплохая и самое главное познавательная презентация.

25Jan/103

Примеры 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)

Если у вас есть чем поделиться - присылайте, буду обновлять список :)

25Dec/090

Custom HAML filters

На днях сделал набор кастомных HAML-фильтров, которые заменяют ссылки на youtube, vimeo, rutube, daylymotion на соответствующие видео. Использовать просто - ставим плагин, а дальше используем фильтры cbtextile, cbmarkdown или cbmaruku как обычные HAML-фильтры.

28Sep/094

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, :o 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: Возможно решение не идеальное, но с удовольствием рассмотрю все ваши рекомендации по его оптимизации :)

26Aug/094

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.

24Aug/094

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.

На сегодня пожалуй все :) Удачи :)

28Jul/090

Link Shot #8

Ruby on Rails
Секреты rails console
Немного про интеграцию ftp и приложений на ror

Flex
Тестирование Flex-приложения с помощью Cucumber, часть 2

27Jul/090

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"
17Jul/092

Пара плагинов для 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 сайта.

6Jul/090

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.

3Jul/091

Чем вы тестируете ваши рельсовые приложения?

Собственно говоря - опрос :) Если вы напишите почему был выбран тот или иной вариант - был бы очень признателен :)

Сам лично использую Test::Unit :)