Лайоут для текста

February 28, 2012

По умолчанию при рендеринге простого текста в контроллере он отрисовывается как есть:

def action
  render text: "some" # => some
end

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

Это сделать очень просто:

def action
  render text: "some", layout: true # => "<!DOCTYPE html><html> ..."
end

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

Action Controller Helper Method

February 23, 2012

Долгое время мне казалось очевидным что, для того чтобы метод контроллера объявить хелпер методом необходимо сначала определить метод, а потом передать его имя в helper_method:

class ApplicationController < ActionControllerBase
  def current_user
    @current_user ||= User.find_by_id(session[:user_id])
  end
  helper_method :current_user
end

Однако можно объявлять метод хелпером до его конкретной имплементации.

class ApplicationController < ActionControllerBase
  before_filter :authenticate!
  helper_method :current_user
  # ...

  def current_user
    @current_user ||= User.find_by_id(session[:user_id])
  end
end

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

Если же вернуться от рейлс к руби, то, например, метод можно сделать приватным только после его объявления:

class A
  private :some # <--- EXCEPTION: undefined method `some' for class `A'

  def some
    puts "some"
  end
end

class B
  def another
    puts "another"
  end

  private :another # Ok!
end

Простой Haml генератор статических сайтов

February 17, 2012

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

Итак, скачиваем исходники бутстрап с официальной страницы проекта в папку проекта. Создаем директорию views, добавляем хамл-файлы:

-# views/index.haml
!!! 5
%html
  %head
    -# ...
%body
  .container
    = partial :header
    -# ...
-# views/_header.haml
.header
  %h1 Logo

Создаем файл который будет собирать наш сайт в папку _site:

# make.rb
require 'haml'

`rm -fr _site && mkdir _site`
`cp -r bootstrap _site`

puts "generate index.html"
engine = ::Haml::Engine.new(File.read('views/index.haml'))
File.open("_site/index.html", "w"){|f| f.write engine.render}

Запускаем файл make.rb и получаем ошибку Unknown method 'partial'. В наш генератор необходимо добавить поддержку паршиалов.

У Haml::Engine#render метода есть параметр scope, который позволяет выполнить код хамла в контексте произвольного объекта. Реализуем простой паршиал и запустим make.rb снова:

# ...

class Helpers
  def partial(template)
    ::Haml::Engine.new(File.read("views/_#{template}.haml")).render(Helpers.new)
  end
end

engine = ::Haml::Engine.new(File.read('views/index.haml'))
File.open("_site/index.html", "w"){|f| f.write engine.render(Helpers.new)}

Теперь скрипт выполнится правильно и создаст готовый сайт в папке _site.

Для удобства разработки добавим гард:

# Guardfile
ignore_paths '_site'
guard :shell do
  watch(/.*/) { `./make.rb` }
end

а также скрипт деплоя готового сайта:

# deploy.sh
./make.rb
rsync -aP --del _site/ server:/www/site

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

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

Update: Есть шутка, что нет смысла чему-то долго учиться, потому-что всегда на ютубе будет много роликов, где кто-нибудь это делает в 10 раз лучше. Так и в руби, на любую идею уже есть красиво оформленный гем. Вот ссылки на генераторы статических сайтов, которые посоветовали коллеги в комментариях: