3 авг. 2009 г.

I18n. Поддержка Украинского языка в Ruby & Ruby on Rails

Ukrainian language support for Ruby & Ruby and Rails | Підтримка української мови | Поддержка Украинского языка в Ruby & Ruby on Rails

Перевод основных gems + плюрализация

18 июн. 2009 г.

Игнорирование файлов в Git

Для того, чтобы поставить в игнор некоторые файлы или каталоги необходимо их внести в файл .gitignore

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

git rm --cached


Такая команда удалит файл только из индекса, но оставит его локальную копию.

15 июн. 2009 г.

Fixtutes vs Factories


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






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


Я не буду вдаваться в подробности реализации, недостатки и приимущества YAML Fixtures, FactoryGirl и ObjectDaddy, потому как это лишь реализации решения конкретной проблемы.


Проблема звучит так: Наполнить базу данными.


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


Эсли это тестирование, то по сути нам не очень важна семантика данных. Тоесть вместо Васи Пупкина и Пети Коржика, могут быть использованы User-1, ..., User-N.

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


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


Теперь еще более смелое предположение: фикстуры и фабрики - одно и тоже.


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


Основные притензии:



  • Замедляют выполнение тестов

  • Позволяют вносить противоречивые данные в базу

  • Проблема с поддержкой больших объемов данных

  • Поломка в одном виде фикстур ломает сразу группу тестов



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


Фабрика не панацея, а колько подходящие средство для решения поставленной задачи.


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



<% 10.times do |i| %>
user_<%= i %>
id: <%= i %>
first_name: <%= "First Name User-#{i}" %>
last_name: <%= "Last Name User-#{i}" %>
<% end %>


1 Factory.define :user do |f|
2 f.first_name 'Вася'

3 f.last_name 'Пупкин'
4 end
5
6 Factory(:user, :last_name=>'Коржик', :first_name => 'Петя')

7 Factory(:user, :last_name=>'Карбуратор', :first_name => 'Гриша')

8 Factory(:user, :last_name=>'Нина', :first_name => 'Мишка')


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

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


Выбор есть:


23 апр. 2009 г.

Сodecamp 2009


Приглашение на данное мероприятие было для меня полной неожиданностью.
Вначале мы с Русланом Волошиным планировали выступать вместе, но обстоятельства
сложились так, что "отдуваться" пришлось мне одному.

Что из этого получилось решать, конечно, слушателям, но мне, лично, понравилось почти все.
Под "почти все" я имею ввиду ограничение по времени :-)

Тему я выбрал довольно широкую: Введение в мир Ruby и Ruby on Rails. И даже немного засомневался в своих возможностях вложить все это в 40 минутный практикум.

Времени на подготовку почти не было.

По принципу "обезъяна видит - обезъяна делает" порыскал ключевым ресурсам по данной теме и в результате получилась вот такая компиляция, которая помогала мне скрывать присутствие в лексиконе слов паразитов типа "Ыыыыыыы" :-)(шучу конечно).

Попытки начитать подкаст сразу показали, что выступить на русском языке (мероприятие было международным) мне не удастся, по той простой причине, что мой речевой аппарат не преспособлен к такой эквилибристике, а "шокать" и "гекать" как-то не особо хотелось. Разрешить дилему помог тот факт, что выступать придется в КПИ(Киевский политехнический институт). Поскольку это украинский ВУЗ, а я по образованию преподаватель информатики, то просто обязан следовать закону который преписывает вести лекции на государственном языке, тобиш украинском.

Так что "звыняйте" дорогие читатели и слушатели но доклад был на родном языке по вполне обоснованным причинам, хоть и вразрез с форматом конференции. Реакция была самая разная от недоумения, до (нескромно) нескрываемого одобрения. Но главное, что она *была*, а это значит, что слушатели не остались равнодушными.

Впечатленией было очень много и начались они с момента, когда меня, стоящего в дверях и слушающего докладчика, начали спрашивать: не начался ли доклад по Ruby и Rails.

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

Пардон, воркшоп. Как мне объяснили, что когда с примерами, то это воркшоп а не доклад и на него выделяют на 10 минут больш времени. Потому я выбрал воркшоп. Хотя в период моего обучения это называлось практикумом.

Я часто посещаю различного рода ИТ конференции, и не только ИТ. И хорошо себе представляю обстановку и формат проведения. Многое зависит от харизмы докладчика и широты или узости специализации освещаемой темы, а главное насколько полно ему удасться войти в резонанс с аудиторией.

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



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

В задачу доклада НЕ ставилось:
- столкнуть лбами Ruby c Python, Java или PHP и Ruby on Rails с CakePHP;
- вдаваться в детали и сравнительные характеристики;

Основной целью было:
- разделить сиамских близнецов: Ruby и Ruby on Rails, у многих новичков складыватся впечатление, что RoR это весь Ruby-мир, зачастую много говорят о красоте и мощи RoR, но не отдают должное фундаменту на котором он выстроен.
- рассказать "кто", "когда" и "зачем" создал еще один язык программирования и еще один програмный каркас.
- показать джентельменский набор разработчика который позволяет практически не выходить за рамки языка программирования: начиная от автоматизации процесса разработки и заканчивая IDE, в котором этот процес происходит;
- показать, что в сущетвует замечательное ruby сообщество http://rubyclub.com.ua, частью которого я себя считаю.

Наверное последний пункт я выполнил хуже всего, причины опущу, они банальны.

Почему так много и эмоционально описал это событие? Ну, потому, что это был первый раз. Первый публичный опыт. А первый раз как известно очень много значит для все последующих и будут ли таковые вообще :-)

P.S. Были вопросы: когда же все таки постоиться полноценная конференция по Ruby и Ruby on Rails ?
Лето на подходе и все возможно :-)

26 мар. 2009 г.

Redcar - TextMate для Linux



Страница проекта
Репозитарий на githaub.com

Как говориться
Наш ответ Чемберлену.


Особенность редактора в том, что написан он на чистом Ruby по образу и подобию TextMate.
Ничего вразумительного больше сказать не могу :-)) Погоняем - увидим. Но начало уже положено :-)



20 мар. 2009 г.

Многомерные массивы в Ruby

Заполнить многомерный массив случайными числами из заданного диапазона.
Данные вводяться с клавиатуры

Ruby не поддерживает многомерные массивы напрямую. Зато можно создать массив массивов.
Вторым параметром конструктор класса Array принимает заполнитель значения массива по умолчанию.
Почему бы не отдать ему уже готовый заполненный случаными числами одномерный массив.

>> (h, w, d = gets.split) && (a=Array.new(h, Array.new(w).map{|e| e=rand(d)}))
3 4 100
=> [[97, 96, 18, 60], [82, 73, 83, 70], [49, 3, 19, 93]]
>> a[1][3]
=> 70

cupsd: Child exited on signal 6! failed!

Именно с такой вот руганью сваливался CUPS.
Даже в логи ничего не писал.
Помогло наведение порядка в /etc/hosts.

19 мар. 2009 г.

HAML. Хайку на Ruby

HAML - DSL язык для создания разметки.
Реальная алтернатива для замены стандартного ERB.

Принципиальное отличие - формирование кода с помощью отступов пробелами(_не табуляцией_), а следовательно отсутствие надобности в закрывающих тегах.

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

Установка:
sudo gem source -a http://gems.github.com


sudo gem install haml


Создание приложения и подключение haml:
rails [myapp]
haml --rails [myapp]


/app/views/layouts/application.haml

!!!
%html
%head
%title Hello world!!!
%body
%header
%body=yield
%footer


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Hello world!!!</title>
</head>
<body>
<header></header>
<body></body>
<footer></footer>
</body>
</html>


Некоторый виды форматирования:


  • % - тег
  • = - вычисление
  • - - выражение не возвращающее результат
  • #, . - соответственно id и класс div
  • : - фильтр(textile, sass, ruby, plain)


пример


#toolbar
%a.icon.icon-add
= link_to 'Create New'


     
<div id='toolbar'>
<a class='icon icon-add'>
<a href="/">Create New</a>
</a>
</div>


Кстати скажу, что html генериться весьма аккуратный.

Утилиты для упрощения миграции:

haml - интерпретатор haml кода в html для командной строки.

html2haml - конвертирование html файлов с erb разметкой в haml код.

17 мар. 2009 г.

RoR vs PHP или Из неверного - все, что угодно.

Это почему я такой злой был? Потому, что у меня фреймворка не было.(C) Я


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

PHP популярней, чем RoR. RoR круче PHP.

PHP — шаблонизатор, притендующий на роль языка программирования. Создан был изначально для «нарезки» текста — таковым и остался. Этим же определяется сфера его применения — исключтельно WEB. Название говорит само за себя: PHP: Hypertext Preprocessor.

Ruby on Rails aka RoR — програмний каркас на основе высокоуровневого языка Ruby.

Правильно было бы сравнивать RoR и CakePHP.

“Нелюбовь” к PHP основывалась в основном на том, что долгое время не было програмных каркасов, достаточно популярных, чтобы объеденить вокруг себя достаточно широкий круг разработчиков и доминировать среди подобных ему.

Путаница и холивары возникают еще и потому, что слабо различается отличие между CMS, Framework и собственно самим языком программирования. Подмена одного понятия другим порождает бурю эмоций и флейма: Joomla vs RoR, PHP vs RoR etc, RoR vs Symphony

Ruby-код очень приближен к английскому языку.

Это не верно. Matz(Якихиро Мацумото) — японец, следовательно он несет особенности языка и родного удобного ему лаконичного иероглифического написания. К английскому языку близок RoR — потому как автор его американец дацкого происхождения David Heinemeier Hansson.

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

Человеку удобней смотреть на широкое чем на узкое. Тоже самой происходит и с программой. Лучше видеть всю программу сразу, чем листать страницы. Именно в этом месте происходит ломка сознания программистов C, Pascal, Javа, пытающихся писать на Ruby в стиле привычном для себя . Естественно, что код написанный в соответствии с Ruby way кажеться им “неуместной отимизацией”(сокращенной формой) их кода в ущерб его читабельности.

Для разработки на RoR необходимо переходить на Linux.

Существуют проблемы при разработке на системах семейства Windows. Но Linux не единственная альтернатива. Более того, фанаты семейства MaxOS считают, его чуть ли ни родным для Ruby, потому как со свойственной им прозорливостью в свое время одними из первых включили его в состав дистрибутива операционной системы.

Лично я сам склоняюсь к мнению, что *nix подобные системы более приспособлены для процесса разработки.

13 мар. 2009 г.

Первый номер RailsMagazine


Вышел первый номер журнала RailsMagazine. Цена 8$ USD за печатное издание.
Свободнораспространяемая копия в формате PDF будет доступна через несколько дней.

13 февр. 2009 г.

Сам себе Stylesheet. CSS.ERB.


Для того чтобы спрятать вещь, достаточно положить ее на видном месте.


CSS раздражал и пугал меня уже давно: куча неуправляемого наваленного в один файл хлама, прикосновение к которому подобно миске со спагетти - тянеш с одного конца и что-то движеться с другого.

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

Подумывалось даже написть свой парсер, чтобы генерировать стили налету. Но буквально недавно в разговоре с Евгением Гуриным на тему HAML vs ERB было упомянуто расширение css.erb. Мозг откликнулся почти сразу :-)

Раз можно получить ресурс в формате JSON или XML, то почему бы ему не быть CSS


В принципе, на этом все. Писать особо больше нечего Джо Сассер и так уже все доходчиво объясняет.

application.css

p {
color: <%= @user.color %>;
}


stylesheet_controller.erb


def show
@user = User.find(params[:id])
respond_to do |format|
format.html
format.css
end
end

application.html.erb

<%= stylesheet_link_tag formatted_user_path(@user, "css") %>


Вот тут эще статья по динамической генерации стилей.

Вобщем все на HAML, товарищи! Там это все уже есть встроенное.

P.S. Правда немного смущает структурирование отступами, чем нередко подкалывают питоноводов. Но ничего, переживем. YAML же мы как-то приняли.

P. P. S. YAML не допускает отступы табуляциями, желательно два пробела.

10 февр. 2009 г.

Scaffold in Ruby on Rails

ActiveScaffold, Streamlined, AutoAdmin - все это инструменты для автоматической генерации графического интерфейса по данным конфигурации или той информации. которую удается извлечь из модели.

Все три встраивают свой код на разных слоях:
ActiveScaffold - контроллер,
AutoAdmin - модель
Streamlined - слой ui с привязкой к модели

В принципе самым правильным с точки зрения гибкости и устойчивости к изменениям является Streamlined, потому, что можно одновременно иметь несколько вариантов настроек и заменять изменяя только одну строку в регистрации элемента UI слоя.

Из этого всего можно сделать вывод, что слой автоматического формирования графического интерфейса сущесвует. Где же его разместить, если каждый инструмент диктует нам свои условия?

Решение следующее. Вынести весь код отвечающий за генерацию UI в отдельный каталог app/ui.

Как нам заставить этот код работать?

Пользуясь тем, что классы Ruby всегда открыты и принципом примата соглашений создадим копии нужных нам классов(котроллеров или моделей, в зависимости от выбранного генератора UI) в каталоге UI и загрузить каждый из этих классов.

После загрузки все обявления одноименных класов сольються воедино.

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

Никто так-же не запрещал нам использовать комбинацию из нескольких генераторов.

environment.rb

Dir["#{RAILS_ROOT}/app/ui/*.rb"].each(&:require)


app/controllers/welcome_controller.rb

class WelcomeController < ApplicationController
def index
#
end
end


app/ui/welcome_controller.rb

class WelcomeController < ApplicationController
active_scaffold do |config|
...
end
end

7 февр. 2009 г.

acts_as_extensible. Все факты в одном месте.

Практическое использование Rails: Часть 3. Оптимизация ActiveRecord

В данной статье описываются способы решения проблемы наследования в реализации патерна ActiveRecord Ruby on Rails.

По моему мнению, ни один из этих способов не является полным, так как не решает проблемы связаной с сосредоточением общих данных и логики в одном месте.

Недостатки однотабличного наследования там уже описаны(STI).
Многотабличные методы заставляют вносить общие поля во все таблице, а это неоправданное расточительство времени при большем количестве подкласов.

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

Для решения задачи можно использовать расширение acts_as_extensible делигирует вызовы свойств объекту связанному по has_one, а так же берет на себя заботу о его создании и уничтожении.

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

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

Унаследовать все подсклассы от одного абстрактного суперкласса и определить общее поведение там.
Это избавит нас от перебора всех моделей и встаки кода например через include 'Module'.

Код становиться чище, вероятность ошибок снижается.

# Общие поля
# title: string
# body: string
# contentible_id
# contentible_type

class Content < ActiveRecord::Base
belongs_to :contentible, :polymorphic => true
validates_presence_of :title, :body # Проверка общих свойств
end

class AbstractContent < ActiveRecord::Base
self.abstract_class = true
acts_as_extensible :content, :as => :contentible

# общие связи
has_many :comments, :as => :commentable

def publish # общие методы
...
end
end

class Post < AbstractContent
end

class News < AbstractContent

end

class Comment < AbstractContent
validates_something :field, :field2 # Проверка индивидуальных свойств
end


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

Вообще ActiveRecord допольно неплохой патерн, пока речь не заходит о наследовании.

DRY!!!

Спасибо, Коля :-)

30 янв. 2009 г.

Firefox как Chrome

На данный момент мое мнение такое:

IE+Chrome+Opera < Firefox

Не по количеству пользователей. а по заявленному функционалу, включая модули расширений.
С выходом браузера Chrome у пользователей складовались с ним самые разные отношения. Насколько мне удалось понять, то в основном из-за аскетизма и простоты и перегруженности и некоторой топорности стандартной темы Firefox.

Сегодня я покажу как переодеть Firefox в одежду Chrome :-)

План такой:

  • Установить тему аля Google Chrome(Chromifox 1.0)

  • Убрать главное менюHide Menubar

  • Кнопка с выпадающим меню,
    куда будут перенесены нужные нам пункты из главногоPersonal Menubar



Да вот, собственно, и все. Ставите расширения и тем, выносите кнопку меню на тулбар и настраиваете по словему вкусу.

Странно, что меню у меня исчезло только когда я поставил галочку в меню Вид/Панель главного меню.
Тоесть все немного шиворот-навиворот.

Аналогично нереодевается под IE.


20 янв. 2009 г.

CMS. Каша из топора.

Сразу к сути. Зачем нужны CMS? Хранить данные и управлять контентом.
Тут как бы все просто. Но...

Возьмем Ruby on Rails и RadiantCMS.

1. Tags vs Helpers(собственная библиотека тэгов которую надо изучать и расширять, против стандартных хелперов)
2. Snippets vs Partials(на деле снипеты это те-же париталы. кстати в коробочных снипетах параметры не предусмотрены, надо ставить экстеншен)
3. Extensions vs Wrapped Rails Plugins(практически каждый екстеншен базируется на плагине рельсовом, доработанном напильником, так как система плагинов рельс остаялетя желать лучшего(Engines например))
4. Храним шаблоны в БД, а потом все таки пишем расширение которое позволяет использовать файлы в качестве шаблонов.
5. Перенос такой системы? Что-бы перенести надо сначала пол системы извечь из базы.

Вывод:
CMS полезна:

  • когда она есть и существующий функционал удовлетворяет поставленным задачам;

  • когда задача сводится к настройке, хотя настройка может дороже обойтись, чем написание нового функционала;

  • если функции CMS дублируют функционал каркаса(RoR);

  • у CMS небыло альтернатив до появления програмных каркасов + система плагинов(RoR, Merb, Symphony, CakePHP)

17 янв. 2009 г.

Связь belongs_to и ключ :through


class Country
has_many :cities
end

class City
belongs_to :coutry
end


class Person
belongs_to :city
has_one :country, through => :city # NOT belongs_to :country, through => :city
end


Для того, чтобы использовать belongs_to надо иметь в модели внешний ключ на владельца.
В данной случае нужно использовать has_one