Загрузка...

Ruby & Rails: веб-разработка с удовольствием

Ruby on Rails — фреймворк для создания веб-приложений. Является открытым программным обеспечением (лицензия MIT). Здесь мы обсуждаем новости RoR, делимся учебными материалами и интересными находками С RoR даже сложные веб-приложения могут быть написаны за считанные дни. Это действительно разработка с удовольствием!
     

Liquid

01.02.10, 20:04
Автор ggg

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

Получение доступа к контроллеру и view из liquid хелпера

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

 

{% if opera %}
Приветствую вас, уважаемый пользователь Opera!
{% endif %}

 

Таким образом, нам нужно либо передать в liquid-шаблон переменную opera, либо написать liquid-хелпер, который будет извлекать из запроса типа тип браузера. Для того, чтобы получить доступ к запросу нам необходимо иметь доступ к контроллеру. Это можно сделать следующим образом:

 

def opera
  ctrl = @context.registers[:controller]
  ctrl.request.user_agent && ctrl.request.user_agent['Opera']
end 

 

Как вы можете заметить, нами используется переменная @context, доступная в liquid-хелперах и ее хеш registers, содержащий такие параметры как контроллер и view.

Получение доступа к исходной переменной, которая прошла ликвидизацию

Предположим, имеется такая модель

 

class User < ActiveRecord::Base
  liquid_methods :name
  def super_important_method(x, y, z)
    x.foo(self, y + z)
  end
end

 

Предположим, что мы хотим из liquid-хелпера получить доступ к методу модели super_imporant_method. Это можно сделать следующим образом:

 

def test_liquid_helper(user)
  orig_user = user.instance_variabled_get(:@object)
  # теперь мы можем работать с объектом модели User
  x = SuperClass.new
  orig_user.super_important_method(x, y, z)
end

 

Как сделать универсальный хелпер, сопособный работать и с liquid и не с liquid объектами

Предположим, что у нас есть объект user, описанный выше, рассмотрим, как сделать хелпер, который сможет работать и из erb шаблона и из liquid

 

def universal_helper(user)
  if user.is_a?(User::LiquidDropClass)
    controller = @context.registers[:controller]
    view = @context.registers[:view]
    user = user.instance_variable_get(:@object)
  else
    view = self
  end
  # делаем какие-то действия используя контроллер, вьюху и юзверя
end

 

При желании можно сделать функцию, которая будет делать все указанные действия автоматически, как-то так: make_universal_helper :helper_name.

Пока что это все проблемы, с которыми я столкнулся при работе с liquid-ом. Если вы тоже используете liquid и при этом столкнулись с какими-то проблемами, то отписывайтесь в комментариях, обсудим.

Комментарии

Хорошая статья, только мне больше нравится делать так, как сделано в Mephisto, а именно делать дропы. То есть, когда мы пишем liquid_methods это на самом деле генериться соответствующий to_liquid, в котором передаются параметры для генерации объекта класса Liquid::Drop.

Так как зачастую нужно в “дропах” чуть больше логики, чем просто доступ к аттрибутам объекта, да, и вообще, мне кажется, что это просто удобнее (полагаю это даже вполне можно назвать презентерами), то можно писать свои дропы, а в моделе писать:

class MyModel < ActiveRecord::Base
def to_liquid
ModelDrop.new self
end
end

Более того, тогда можно создавать дропы и указывать между ними ассоциации, как в моделе или скоупы, при этом по ассоциациям или скоупам будут отдаваться не сами объекты, а коллекции дропов для этих объектов.

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

Не сочтите за пиар, если кому интересно, то пост можно прочитать тут: http://2kan.tumblr.com/post/362812633/relations-for-liquid-drops

спасибо за информацию, ваша статья многое проясняет

Войдите, чтобы оставить комментарий