вторник, 28 сентября 2010 г.

Кодировка субтитров в mplayer

Явно указываем mplayer -subcp cp1251

суббота, 25 сентября 2010 г.

authlogic create user without session

Понадобилось создавать пользователя без создания сессии.

В authlogic за это отвечает библиотека acts_as_authentic

И метод save_without_session_maintenance



# Save the record and skip session maintenance all together.

def save_without_session_maintenance(*args)

self.skip_session_maintenance = true

result = save(*args)

self.skip_session_maintenance = false

result

end


node.js + couchdb

Использование CouchDB с узлом.js





Apache CouchDB это документ-ориентировочная база данных, которая может делать запросы

и индексироваться в стиле MapReduce, используя JavaScript. CouchDB также предлагает пошаговую репликацию

с двусторонним обнаружением конфликта и его разрешением.



Для начала установите CouchDB.Вы можете скачать CouchDB здесь.

Следующи шаг - установите npm, потому что все клевые пакеты node - в npm:)

Node имеет поддержку в HTTP лучше, чем любой язык, с которым я когда-либо работал и по совпадению интерфейс CouchDB

доступен исключительно через HTTP. Для начала, давайте просто познакомимся с CouchDB, используя HTTP библиотеку и позже

мы посмотрим на некоторые высшие абстракции.





Знакомство с CouchDB, используя запрос



npm install request



Это упрощенный клиент HTTP, который находится в довольно широком использовании среди разработчиков node.Давайте получим

список всех баз данных в вашем CouchDB.





var sys = require('sys')

, request = require('request')

, h = {accept:'application/json', 'content-type':'application/json'}

;

request({uri:'http://myname.couchone.com:5984/_all_dbs', headers:h}, function (err, response, body) {

console.log(sys.inspect(JSON.parse(body)));

})



Если ваш CouchDB - только что установленный, вы увидете что-нибудь подобное этому.

[ '_users' ]



Сейчас давайте создадим базу данных. Вы можете легко зделать это в Futon, веб интерфейсе для CouchDB, но веселей будет зделать

это в node.

request({uri:'http://myname.couchone.com:5984/dbname', method:'PUT', headers:h}, function (err, response, body) {

if (err) throw err;

if (response.statusCode !== 201) throw new Error("Could not create database. "+body);

})



Код ошибки фактически является ошибоками из HTTP клиента. Ни один правильный HTTP ответ не будет иметь

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



Если вы вышли из режима Админ и создали админскую учетную запись (что вы должны сделать)

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

Авторизация типа basic поддерживаеться в CouchDB и в запросе, так что мы только добавим их к url.

request({uri:'http://myaccount:password@myname.couchone.com:5984/dbname', method:'PUT', headers:h}, function (err, response, body) {

if (err) throw err;

if (response.statusCode !== 201) throw "Could not create database. "+body;

})



все просто.

Сейчас давайте создадим и получим несколько документов

var dburi = 'http://myaccount:password@myname.couchone.com:5984/dbname'

request({uri:dburi, method:'POST', body:JSON.stringify({data:'somedata'})}, function (err, resp, b) {

if (err) throw err;

if (resp.statusCode !== 201) throw new Error("Could not create document. "+b);

console.log(b);

})



Вы увидете в console print что-нибудь подобное этому.

{"id":"8s7dhf8s7dah8f7sdf8dh", "rev":"1-7sdfy87s", seq:1}



Поскольку мы не имели id для этого документа, мы сделали POST к dburi и это создало новое id для нас. Если мы имеем

что-нибудь, что уже имеет определенный id, подобно тому мы имеем JSON тело твита от твитера API, мы

должны использовать id и использовать вызов PUT.

tweet._id = 'twitter-'+tweet.id

request({uri:dburi+'/'+tweet._id, method:'PUT', body:JSON.stringify(tweet)}, function (err, resp, b) {

if (err) throw err;

if (resp.statusCode !== 201) throw new Error("Could not create document. "+b);

console.log(b);

})



И мы должны увидеть чтото вроде етого

{"id":"twitter-192837218", "rev":"1-3dfy87s", seq:2}



Мы можем получить етот документ запросом GET

request({uri:dburi+'/twitter-192837218'}, function (err, resp, b) {

if (err) throw err;

if (resp.statusCode !== 200) throw new Error("Could not get document. "+b);

console.log(sys.inspect(JSON.parse(b)));

})



Или мы можем получить множество документов используя all_docs api.

request({uri:dburi+'/_all_docs?startkey="twitter-"&endkey="twitter-ZZZ"&include_docs=true'}, function (err, resp, b) {

if (err) throw err;

if (resp.statusCode !== 200) throw new Error("Could not get document. "+b);

console.log(sys.inspect(JSON.parse(b)));

})



all_docs API также позволяет фильтрацию startkey и endkey параметров на id, так что запрос подобно этому только даст нам

обратно документы твитера.



Для создания индексов и запрашивания их, я рекомендую вам почитать O'Reilly's CouchDB The Definitive Guide где всё доступно

изложено.





Знакомство с CouchDB, используя node-couchdb



Для некоторых людей прямое использование HTTP API может быть немного долговатым.существует 4 или 5 node библиотек которые

предоставляют высшие абстракции, но только у меня есть время говорить про node-couchdb.



создавать db просто

var couchdb = require('node-couchdb/lib/couchdb')

client = couchdb.createClient(5984, 'myname.couchone.com'),

db = client.db('my-db');

db.exists(function (err, exists) {

if (!exists) db.create();

})



создавать документ так же просто

db.saveDoc('my-doc', {awesome: 'couch fun'}, function(er, ok) {

if (er) throw new Error(JSON.stringify(er));

console.log('Saved my first doc to the couch!');

});

получить документ еще проще

db.getDoc('my-doc', function(er, doc) {

if (er) throw new Error(JSON.stringify(er));

console.log('Fetched my new doc from couch:');

console.log(doc);

});



Получить все документы - еще про... паждите паждите ... ще!

db.allDocs(function (err, resp) {

...

})

db.allDocs({startkey:'twitter-', endkey:'twitter-ZZZ'}, function (err, resp) {

...

})





Знакомство с couch используя creationix's couch-client



Tim Caswell только что запустил свой собственный клиент CouchDB и начал выполнять инструкции приведенные ниже.

модуль couch-client ето гибрид между http помощником запросов и полностью абстрактным драйвером базы данных.



подключение к базе данных простое

var CouchClient = require('couch-client');

var Users = CouchClient("http://username:password@yourhost:5984/users");



Если база данных не существует вы получите ошибки, но это легко сделать с помощью выставленой функцией request

Users.request("PUT", "/users", function (err, result) {

});



как видите, вы можете зделать любой произвольный http запрос используя функцию request(). Она располагаеться между 2 и 4 аргументом

CouchClient#request(method, path[, body][, callback])



Если вы оставите повторный вызов, это вернет движение вместо этого. Повторный вызов, если указано получают два аргумента

callback(err, result). err исключительный обьект если чтото пошло не так.

result ответ от couch уже JSON.parseed



так же для лучшего представления,couch-client имеет несколько utility функций которые исполнят общие задачи со всеми красиво

представлеными встроеными штуками.Это имеет соединение объединяющее, http keep-alive, и соединение запроса используя couch's bulk APIs



* CouchClient#save(doc, callback) -сохранить документ

* CouchClient#get(key, callback) -получить документ

* CouchClient#remove(key/doc, callback) -удалить документ

* CouchClient@changes(since, callback) -наблюдения за изменениями во всей базе данных с since and вызовы callback один раз за именение (експерементально)


rails3 country_select_tag

В некоторых плагинах,хелперах оставшихся от второй рельсы надо отключать экранирование кода.

content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)

вот значение escape по умолчанию стоит true - тогда как для вывода кода надо false

например в country_select_tag я сделал так

content_tag(:select, countries, options.merge(:id => "#{@object_name}_#{@method_name}", :name => "#{@object_name}[#{@method_name}]"),false)

spree+bluehost

То что в россии нормального хостинга нет все надеюсь знают.

Потому ставим рельсовое приложение на хостинг bluehost

Для начала надо активировать ssh на своем аккаунте - для этого создается тикет и прикладывается
скан паспорта(у меня прокатил скан старого паспорта - они может и не смотрели на него)

Затем ставим все необходимые гемы:

качаем архив сприи http://github.com/railsdog/spree/tarball/v0.11.0

распаковываем tar -xzvf ./имя_архива.tgz

заходим в него и ставим гемы rake gems:install

Запускаем gem env

Находим GEM PATHS оно будет такое /home2/username/ruby/gems

вписываем в "echo 'export GEM_PATH=/home2/username/ruby/gems' >> ~/.bashrc "

перелогиниваемся или вызываем export GEM_PATH=/home2/username/ruby/gems


ставим недоставющие гемы gem install rack -v '=1.1.0' --no-ri --no-rdoc

добавляем в config/environment.rb гемы less treetop mutter и прописываем окружение production

распаковываем все гемы rake gems:unpack


дальше создаем базу и забиваем необходимыми данными и по желанию тестовыми rake db:bootstrap RAILS_ENV=production



делаем симлинк ln -s ~/spree/public ~/public_html

создаем файл .htaccess

AddHandler fcgid-script .fcgi

RewriteEngine On

RewriteRule ^$ index.html [QSA]

RewriteRule ^([^.]+)/!$ $1.html [QSA]

RewriteCond %{REQUEST_FILENAME} !-f

RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

ErrorDocument 500 "Application error Application failed to start properly"


Дальше надо отключить редирект на https при входе в админку и при регистрации

Spree::Config[:allow_ssl_in_production]

>> true

Spree::Config.set(:allow_ssl_in_production => false)


проверяем Spree::Config[:allow_ssl_in_production] должно показать false

все - теперь должно работать

recaptcha + rails3

Рекаптча перестала работать в третей рельсе.

Выводится html и js как текст.

А дело в том что секурность рельсы значительно возросла и что б из переменно вставить js в страницу надо это явно указать.

<%= raw recaptcha_tags %>

spree-ebsin

Есть у индусов такая платежная система ebs.in
И им хочется использовать ее вместе со сприи
= EBS Gateway

EBS Payment Gateway Extension (www.ebs.in)

Install and configure extension preferences:

* preference account_id = Get from your account
* preference url = https://secure.ebs.in/pg/ma/sale/pay/
* preference secret_key = Get from your account
* preference mode = 'LIVE' or 'TEST'
* preference currency_code = 'INR'

You can see messages plugin in the application log:

EBS payment authorized on order R374461356

PaymentID = 1190148
Mode = TEST
DateCreated = 2010-08-19 08:55:48
ResponseCode = 0
MerchantRefNo = R374461356
Amount = 62.00
TransactionID = 2288126
ResponseMessage = Transaction Successful

spree-ebsin

spree-quick-auction

Для товаров задаем цены от х до у
Тот кто первый покупает подешевле.
Финт в том что самые дешевые можно ставить уже якобы проданными.
http://github.com/pronix/spree-quick-auction

spree-firstdata

Установка:

Скопировать firstdata_payment_gateway в папку
vendor/extensions и перезапустить spree.
spree-firstdata

Использование "and" и "or" в руби

Если вы достаточно долго используете ruby, вы откроете для себя and и or операторы.

На первый взгляд это просто синонимы && и ||.

Есть любители использовать буквы, есть любители символов(надо ж показать что вы их знаете),HO надо понимать разницу между ними.

В итоге "and" "or" не ведут себя, как и их символическое родственников. В частности, они имеют гораздо более низкий приоритет.

На данный момент, вы можете матюгнуться если это покажется слишком запутанным.

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

Вообще поведение and и or (как и многое в руби) уходит корнями в перл.

В перле они использовались как операторы if и unless.
Например так:

do_something() or die "It didn't work!";

Эти же операторы в руби преследуют ту же цель.
Для начала "and" и "or" не булёвые операторы, они переключают путь выполнения программы.

and

And используется для цепочек связанных операций когда одна из них может вернуть nil или false.

Пример:

` post = Post.find_by_name(name) and post.publish! `

Тут пост будет опубликован если он найден.

Чем отличается &&? Давайте экспериментировать.
` foo = 42 && foo/2 `

`NoMethodError: undefined method /' for nil:NilClass`
` from (irb):18`
` from :0`

И что же тут случилось ?
Скобочки помогут раскрыть тайну:

`foo = (42 && foo)/2`

Ожидали мы немного другое поведение(теперь-то уже понятно что ожидать такого больше не будем)

`foo = 42 and foo / 2 => 21 `

…другое дело, все как надо выполнилось.

Другой пример

1. next if widget = widgets.pop

Станет:

` widget = widgets.pop and next `


OR

or используется в тех же цепочках операций.
Лучший способ понять эту конструкцию - серия неудачных операций: попробуй способ 1 -> ошибка -> тогда попробуй способ 2 и т.д.
Пример:


` foo = get_foo() or raise "Could not find foo!" `

Пример рефакторинга.
было:

` raise "Not ready!" unless ready_to_rock? `

стало:

` ready_to_rock? or raise "Not ready!" `


Вывод: and и && так же как or и || абсолютно разные инструменты. Использовать надо каждый в своем случае.

asset_host

Если ваше приложение и статические файлы находятся на одном домене,

то броузер с сервером будут обмениваться печеньками(cookies),

что вызовет лишнюю нагрузку на канал.


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

В итоге все будет работать быстро и потреблять ресурсов меньше.

В рельсе для этого есть параметр asset_host (лучше его использовать только в production окружении).


_config.action_controller.asset_host = "http://assets.ipronix.ru"
_

И конечно надо настроить nginx


_server {
_
_ listen 80;
_
_ server_name assets.ipronix.com;
_
root /var/www/ipronix.com/production/current/public;

_}
_


После рестарта приложения вы увидите что все стало грузиться с разных субдоменов,

и если попробуете измерить скорость и объем то получите выигрыш в каждом запросе.