среда, 21 декабря 2011 г.

Хотел сделать тупую авторизацию в google hosted домене, однако ...

Однако omniauth при всей свой крутости с google_oauth2 не умеет банального - federated login.

Иными словами, хочу проверить, что юзер из моего google домена, если да - пустить в приложение, нет - гуляем.

Увы и ах, нет такой стратегии, а если хотите - можете написать request в wiki.

Полезняшка, для ускорения установки джемов отключаем генерацию rdoc и ri

не секрет, что в продакшн окружении нам не нужна документация по джемам, поэтому для ускорения установки джемов следует сделать следующее:

cat >~/.gemrc

gem: --no-rdoc --no-ri
ctrl+d

что выключит генерацию rdoc и ri

вторник, 20 декабря 2011 г.

Няшный рейтинг для rails

Куда ведет нас rails 3.1? Пост, полный скорби по былым временам (плач Ярославны)

После достаточного перерыва, судя по интенсивности постов с багофиксами рельс, не могу не выразить солидарность с мнением Макса Лапшина по поводу движения в сторону усложнения рельс.

На сегодняшний день ситуация очень усложняется новомодными свистелками типа assets pipeline, которые делают процедуру деплоя приложения чуть менее чем полностью кошмарной. Лично у меня время на дебаг деплоя увеличилось в разы, равно как и посещаемость у stackoverflow.com на предмет вопросов о therubyracer и так далее.

Bundler, RVM, CoffeeScript, HAML, SASS/SCSS, REE, Unicorn и это лишь часть того нового, чем нужно овладеть со времен rails 2.x и подружить с Capistrano.

Вся экономия времени на bundler package во сто крат превышается ловлей багов от компиляции native extensions c банальным sqlite3 при bundle install! Получившийся геморрой хорошо иллюстрирует этот топик в группах ror2ru.

В это все входит время на изучение документации, выпиливания багов на FreeBSD.

Да в конце концов, просто для того, чтобы задеплоить rails приложение на FreeBSD приходится собирать NodeJS из портов (для того же v8, therubyracer,execjs)!


Жить со времен Rails 2.x стало заметно сложнее. Задача "склепать по-быстрому прототип" уже исключает "по-быстрому".

Однако, как минимум active_admin и допиленный omniauth с интеграцией vkontakte, facebook и прочими радует.

Простые перечисления в модели

https://github.com/nofxx/symbolize облегчит жизнь

Интерфейсы

буду собирать сюда ссылочки

дизайн админок
http://pilu.github.com/web-app-theme/#themes/activo

готовая админка
activeadmin.info/

JS дизайн форм/ веб-приложения
http://sproutcore.com/

JS дизайн форм
http://cappuccino.org/

Что такое coffeescript
http://jashkenas.github.com/coffee-script/

понедельник, 19 декабря 2011 г.

sitemap для сайта на Rails

https://github.com/kjvarga/sitemap_generator

с достаточно доступным DSL синтаксисом можно сгенерить сайтмап.

Делается это rake таском, который можно дергать из capistrano при деплое новой версии.

Хотя было бы более правильным это делать по crontab, ведь страницы могут изменяться/добавляться из админки сайта.

суббота, 17 декабря 2011 г.

поломались сайты rals 2.x

Если после обновления rubygems перестали запускаться приложения от rails 2.x и возросло количество deprecation warnings, самое время откатить версию rubygems назад.

это можно сделать командой rvm rubygems 1.4.2

rvmrc

Запишу на будущее синтаксис создания rvmrc

rvm --rvmrc --create ruby@project

пятница, 16 декабря 2011 г.

Баг при обновлении gem update --system

после обновления rubygems стали появляться сообщения об ошибках

множественные "invalid gemspec invalid date format"

помогает следующий небольшой скрипт

find . -type f | xargs perl -pi -e 's/ 00:00:00\.000000000Z//'

среда, 14 декабря 2011 г.

Сильно сократить время на deploy rails приложения

Сильно сократить время на deploy rails приложения поможет достаточно простая команда bundle package, которая создаст в /vendors/cache репозиторий гемов и будет его использовать при bundle install. И совсем перестанет дергать rubygems.org, что ускоряет деплой чуть более чем "драматично".

понедельник, 12 декабря 2011 г.

will_paginate теперь требует перевод для Page Gap

В файл локализации теперь будет необходимо добавлять


en:
  will_paginate:
    previous_label: "← Previous"
    next_label: "Next →"
    page_gap: "…"
иначе вместо ... будет надпись "Page Gap"
https://github.com/mislav/will_paginate/wiki/I18n

Ошибка omniauth с Facebook и Mail.ru

Досадная ошибка на моем продакшн-боксе FreeBSD 8.2


Started GET "/users/auth/mailru/callback?code=01a63d3ffdfc70e7afbfa617742bccd3" for 178.159.227.26 at Mon Dec 12 20:48:47 +0200 2011

OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed):
 
при использовании devise+omniauth+ominauth-mailru на FreeBSD вываливалась, как оказалось, из-за того, что ruby не мог получить список корневых сертификатов.

Полечилось через 2 часа гугления примерно следующим:

cp /usr/local/share/certs/ca-root-nss.crt /etc/ssl/ca-bundle.crt

и изменяем строку в config/initializers/devise.rb на

config.omniauth :mailru, 'XXXXXX', '4fb8e9b16c95691c41a470089099b0acb',:client_options => {:ssl => {:ca_file => '/etc/ssl/ca-bundle.crt'}}

will_paginate внезапно

Внезапно от will_parinate получил exception следующего содержания


NoMethodError (undefined method `paginate' for #):
  app/controllers/pictures_controller.rb:4:in `index'


для @pictures = Picture.all.paginate(:per_page=>1,:page=>params[:page])

оказалось, что это уже встечали бойцы с RoR http://stackoverflow.com/questions/1408852/will-paginate-undefined-method-total-pages

способ лечения
в код контроллера добавить


require 'will_paginate/array' 

Включить сжатие и кеш браузера в Apache2.2

Кто еще не включил сжатие и кеширование, очень рекомендуется это сделать



как описано здесь http://trevorturk.com/2009/06/11/speed-up-your-apachepassenger-rails-app-in-2min/

проверить, что все настроено правильно, и контент сжимается, можно по этой ссылке

воскресенье, 11 декабря 2011 г.

uploadify jquery rails3

Давно использую библиотеку JQuery.uploadify http://www.uploadify.com/ для загрузки больших файлов с отображением progress bar.

Довольно непросто заставить работать компоненту из-за protect_from_forgery, поэтому публикую часть кода, возможно кому-то будет полезно.

<%- session_key_name = Rails.application.config.session_options[:key] -%>


<% content_for :jquery do %>

$('#photo_photo_file').uploadify({
'uploader'  : '/uploadify.swf',
'script'    : '<%= admin_album_path(@album)%>/photos',
'cancelImg' : '/assets/cancel.png',
'buttonText': 'Upload new photos',
'buttonImg' : '/assets/upload.gif',
'width' : '125',
'height' : '35',
'auto'      : true,
'multi' : true,
 onComplete: function(event, queueID, fileObj, response, data){
var data = eval('(' + response + ')');$.getScript(data.photo);
},
'scriptData': {
 '<%= session_key_name %>' : '<%= u cookies[session_key_name] %>',
 '_http_accept': 'application/javascript',
      'authenticity_token' : encodeURIComponent('<%= u form_authenticity_token if protect_against_forgery? %>')
    }
});
<% end %>

суббота, 10 декабря 2011 г.

Няшка, уведомление Growl после deploy

Так как с precompile assets deploy становится все дольше и дольше, имеет смысл не втыкать в командную строку, а получать красивое уведомление от Growl.

Вот как это можно сделать: http://www.stephencelis.com/2008/11/06/capistrano-growl-notifications.html

И все будет работать, если строку
 `growlnotify -ncap -p#{priority} -m #{message.inspect} Capistrano`


заменить на
 `growlnotify -ncap -p#{p} -m #{message.inspect} Capistrano`

пятница, 9 декабря 2011 г.

bundle:install в рецепте Capistrano

Довольно непростым делом оказалось развертывание rails 3.1 окружения через Capistrano в том виде, в котором это работало для rails 2 проектов.

Вот эти две строки, добавленные в deploy.db дают расслабится чуть более:


require "bundler/capistrano"
load "deploy/assets"

первая добавит функционал bundler:install при deploy
вторая включит assets precompile

Про gritter

Всем, кто работает с Mac нравятся уведомления в стиле Growl.

На Юлином сайте в админке использовался мной для этих целей jquery плагин http://boedesign.com/demos/gritter/, который показывал красивое уведомление по завершению длительной загрузки изображений.



который в общем-то прикручивался на то время довольно просто руками.

Сейчас же это стало еще проще с выходом гема gritter. Который и делает данную задачу чуть более чем тривиальной.

Что нужно сделать при переходе с Rails 3 на Rails 3.1

Вот очень хорошо расписано пошагово, что нужно сделать для корректного перехода, в частности, на assets pipeline

http://webtempest.com/upgrade-rails-3-to-3-1/

четверг, 8 декабря 2011 г.

Тонкая настройка Passenger и PassengerMaxPoolSize для apache

Не без удивления обнаружил простую и понятную статью по настройке Passenger для Apache

и попутно командой passenger-status выяснил, что секция



# PassengerMaxPoolSize
# Default: 6
# For 2gb RAM: 30
# For 256 slice with MySQL running: 2
PassengerMaxPoolSize 8

# PassengerPoolIdleTime
# Recommended to be avg time per page * 2
# In Google Analytics... (Avg time on site / Avg page views) * 2
# Default: 300
PassengerPoolIdleTime 150



попросту не работает!

зато стоит вынести PassengerMaxPoolSize 8 за mod_rails как все применяется.
Такие дела.

UPDATED: Загрузка mysql из production mysql в development

слегка модифицирован http://www.snippetstash.com/public/9


# Fetches the production database on the server contents into the development
 # database
 #
 # Assumes you have dbuser, dbhost, dbpassword, and application defined somewhere in your
 # task. Modify as needed - database.yml is used for importing data, just not for exporting.
 #
 # Only supports MySQL.
 desc "Load production data into development database"
 task :fetch_remote_db, :roles => :db, :only => { :primary => true } do
   require 'yaml'

   database = YAML::load_file('config/database.yml')

   filename = "dump.#{Time.now.strftime '%Y-%m-%d_%H:%M:%S'}.sql"

   on_rollback do
     delete "/tmp/#{filename}"
     delete "/tmp/#{filename}.gz"
   end

   cmd = "mysqldump -u #{database['production']['username']} --password=#{database['production']['password']} #{database['production']['database']} > /tmp/#{filename}"
   puts "Dumping remote database"
   run(cmd) do |channel, stream, data|
     puts data
   end

   # compress the file on the server
   puts "Compressing remote data"
   run "gzip -9 /tmp/#{filename}"
   puts "Fetching remote data"
   get "/tmp/#{filename}.gz", "dump.sql.gz"

   # build the import command
   # no --password= needed if password is nil.
   if database['development']['password'].nil?
     cmd = "/usr/local/mysql/bin/mysql -u #{database['development']['username']} #{database['development']['database']} < dump.sql"
   else
     cmd = "/usr/local/mysql/bin/mysql -u #{database['development']['username']} --password=#{database['development']['password']} #{database['development']['database']} < dump.sql"
   end

   # unzip the file. Can't use exec() for some reason so backticks will do
   puts "Uncompressing dump"
   `gzip -d dump.sql.gz`
   puts "Executing : #{cmd}"
   `#{cmd}`
   puts "Cleaning up"
   `rm -f dump.sql`

   puts "Be sure to run rake db:migrate to ensure your database schema is up to date!"
 end


UPDATED: еще один старый recipe для capistrano


desc "Load production data into development database"
task :load_production_data, :roles => :db, :only => { :primary => true } do
  require 'yaml'

  database = YAML::load_file('config/database.yml')

  filename = "dump.#{Time.now.strftime '%Y-%m-%d_%H:%M:%S'}.sql"
  on_rollback { delete "/tmp/#{filename}" }

  run "mysqldump -u #{database['production']['username']} --password=#{database['production']['password']} #{database['production']['database']} > /tmp/#{filename}" do |channel, stream, data|
    puts data
  end
  get "/tmp/#{filename}", filename
#  exec "/tmp/#{filename}"
  exec "mysql -u #{database['development']['username']} --password=#{database['development']['password']} #{database['development']['database']} < #{filename}; rm -f #{filename}"
end

Локализация devise

Локализация devise

https://github.com/plataformatec/devise/wiki/I18n

кладем ее в

config/locales/devise.ru.yml и вуаля

ну и вообще про локализацию моделей очень хорошо написано

http://habrahabr.ru/blogs/ror/128951/#habracut

UPDATED: Лечим проблему инсталляции gem sqlite3 на FreeBSD

Если у вас

Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

        /usr/local/rvm/rubies/ree-1.8.7-head/bin/ruby extconf.rb
checking for sqlite3.h... yes
checking for sqlite3_libversion_number() in -lsqlite3... no
sqlite3 is missing. Try 'port install sqlite3 +universal'
or 'yum install sqlite3-devel' and check your shared library search path (the
location where your sqlite3 shared library is located).
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/usr/local/rvm/rubies/ree-1.8.7-head/bin/ruby
--with-sqlite3-dir
--without-sqlite3-dir
--with-sqlite3-include=${sqlite3-dir}/include
--with-sqlite3-lib
--without-sqlite3-lib=${sqlite3-dir}/lib
--enable-local
--disable-local
--with-sqlite3lib
--without-sqlite3lib


то поможет простая команда

gem install sqlite3 -v '1.3.4' -- --with-sqlite3-dir=/usr/local

где -v '1.3.4' - нужная вам версия sqlite3

UPDATED: все оказалось значительно веселее, если мы хотим автоматизировать оное действие в capistrano.

Для этого необходимо в продакшн хосте в /etc/ssh/sshd_config добавить
PermitUserEnvironment yes

и перезапустить sshd

service sshd restart

что даст возможнось использовать файл ~/.ssh/environment при деплое, поскольку capistrano пользует non-interactive user и обычные переменные окружения не подгружаются, в этом можно убедиться запустив в cap:shell "printenv".

Так вот, после оных манипуляций можно добавлять строку в
~/.ssh/environment
CONFIGURE_ARGS="--with-sqlite3-dir=/usr/local"

и cap bundle:install уже не прервется на искомой ошибке (скорее всего  на какой-то другой ;).

среда, 7 декабря 2011 г.

в связи с переходом на REE в продакшене на FreeBSD 8.2


выпилять работу более старых версий rails можно путем добавления  в environment.rb следующего

сразу после
require File.join(File.dirname(__FILE__), 'boot')

добавить

if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.3.7')
 module Rails
   class GemDependency
     def requirement
       r = super
       (r == Gem::Requirement.default) ? nil : r
     end
   end
 end
end


и в config/boot.rb

require 'thread'

в начало файла

Полечил no such file to load -- iconv у rvm для FreeBSD 8.2

Лечение оказалось довольно простым

rvm package install iconv

rvm install ree-1.8.7-head --with-iconv-dir=/usr/local






четверг, 23 июня 2011 г.

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

Вот так это делается в рельсах
before_filter :restrict_by_ip
def restrict_by_ip  
	if request.remote_ip !~ /^127\.0\.0\./    
		redirect_to 'http://www.chieftec.com'  
	end
end

четверг, 26 мая 2011 г.

Array assoc и rassoc

Я знал, я знал. Что надо искать и куда смотреть, поэтому нашел замечательный оператор assoc у Array.

работает это дело так: Array.assoc(value) вернет индекс, по которому найдется элемент в подчиненном массиве.

 

В моем случае оператор group_by вернул [[1,[a,b,c]],[2,[c,d,e]] и assoc выполнил поиск по ключам массива.

понедельник, 23 мая 2011 г.

Вот так красиво можно делать выборку через AREL в Rails 3

Выбрать клиентов за вчера
Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)

И вот так для in SET

Client.where(:orders_count => [1,3,5])

 

понедельник, 16 мая 2011 г.

патч для исправления ошибок при обновлении компонент (Rails 2)

require File.join(File.dirname(__FILE__), 'boot') if Gem::VERSION >= "1.3.6" module Rails class GemDependency def requirement r = super (r == Gem::Requirement.default) ? nil : r end end end end

Запуск под passenger (а также под утилитку от 37signals) рельсового 2.x приложения

# Rails.root/config.ru
require "./config/environment"
run ActionController::Dispatcher.new