<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
  <title>Прогерское говно</title>
  <link type="text/html" rel="alternate" href="http://mindscan.msk.ru/programmingshit"/>
  <updated>2012-04-08T19:22:26+04:00</updated>

  
  <entry>
    <title>
      <![CDATA[Турборедактирование кусков текста]]>
    </title>
    <link type="text/html" href="http://mindscan.msk.ru/programmingshit/edit-pieces-of-text.html"/>
    <updated>2012-04-08T18:00:00+04:00</updated>
    <id>http://mindscan.msk.ru/programmingshit/edit-pieces-of-text</id>
    <content type="html">
      <![CDATA[<div class="l-content">
<p class="intro"><span class="caps">TLDR</span>: <a href="http://railscasts.com/episodes/336-copycopter">поп-эпизод</a> про <a href="http://copycopter.com/">Copycopter</a> навёл на идею о вполне рабочей схеме для редактирования статических кусков текста, реализуемой буквально за 10 минут.</p> 
<p><a href="http://copycopter.com">Copycopter</a> имеет несколько существенных минусов:</p>
<ul>
	<li>модератора посылают редактировать тексты почему-то на другой сайт;</li>
	<li>там ему предлагают ещё раз авторизовываться, а глупый клиент ведь может вводить данные и от редактируемого сайта;</li>
	<li>ему нужно знать путь-идентификатор текста;</li>
	<li>в случае мультилокального сайта неудобно построены дефолтные значения.</li>
</ul>
<p>Вместо этого мы будем:</p>
<ul>
	<li>редактировать текст прямо на нашем сайте, где модератор уже авторизован;</li>
	<li>хранить дефолтные значения в локали;</li>
	<li>кнопку редактирования поставим прямо у текстов.</li>
</ul>
<p>Моя любимая часть — как всё это выглядит, покажу на примере тупого <a href="http://tedxparkkultury.ru">сайта</a> с русской и английской версиями.</p>
<p>Модель текста:</p>
<div class="l-columns clearfix">
<div class="l-column">
<div class="highlight"><pre><code class="ruby"><span class="k">class</span> <span class="nc">Text</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
  <span class="n">translatable_columns</span> <span class="ss">:body</span>

  <span class="n">validates_presence_of</span> <span class="ss">:path</span>
  <span class="n">validates_uniqueness_of</span> <span class="ss">:path</span><span class="p">,</span> <span class="ss">:allow_blank</span> <span class="o">=&gt;</span> <span class="kp">false</span>
  <span class="n">validates_presence_of</span> <span class="ss">:body_ru</span><span class="p">,</span> <span class="ss">:body_en</span>

  <span class="n">default_scope</span> <span class="n">order</span><span class="p">(</span><span class="s1">&#39;path&#39;</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
</div>
</div>
<div class="l-mark"><font color="999999">Удивительно, но бородатый <a href="https://github.com/iain/translatable_columns">translatable_columns</a> всё ещё работает. Единственное, надо добавить ?-суффикс.</font></div>
</div>
<p>Например для <code>PagesController#index</code>, во view мы выводим текст с путём <code>pages.index.about</code> (благодаря идее <a href="http://copycopter.com">Copycopter</a> уменьшаем напряжение в пальцах — пишем просто <code>.about</code>):</p>
<div class="highlight"><pre><code class="erb"><span class="cp">&lt;%=</span> <span class="n">text</span> <span class="s2">&quot;.about&quot;</span> <span class="cp">%&gt;</span><span class="x"></span>
</code></pre>
</div>
<p>Вся техника в хелпере:</p>
<ul>
	<li>если текста нет, то берём дефолтное значение из файла локали — это значительно упрощает деплой и разработку, ибо вообще не нужно заморачиваться с сидами;</li>
	<li>кнопка редактирования текста тоже неглупа.</li>
</ul>
<div class="highlight"><pre><code class="ruby"><span class="k">module</span> <span class="nn">TextsHelper</span>
  <span class="k">def</span> <span class="nf">text</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
    <span class="n">path</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">controller_path</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">%r{/}</span><span class="p">,</span> <span class="s1">&#39;.&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">.</span><span class="si">#{</span><span class="n">action_name</span><span class="si">}#{</span><span class="n">path</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">if</span> <span class="n">path</span><span class="o">.</span><span class="n">starts_with?</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)</span>
    <span class="n">obj</span> <span class="o">=</span> <span class="no">Text</span><span class="o">.</span><span class="n">find_or_initialize_by_path</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
    <span class="n">text</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">persisted?</span> <span class="p">?</span> <span class="n">obj</span><span class="o">.</span><span class="n">body</span> <span class="p">:</span> <span class="n">t</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="ss">:scope</span> <span class="o">=&gt;</span> <span class="s1">&#39;texts&#39;</span><span class="p">)</span>
    <span class="n">textile</span><span class="p">(</span><span class="n">text</span><span class="p">)</span> <span class="o">+</span> <span class="n">edit_text</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">edit_text</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
    <span class="k">return</span> <span class="s2">&quot;&quot;</span> <span class="k">unless</span> <span class="n">moderator_signed_in?</span>
    <span class="n">url</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">persisted?</span> <span class="p">?</span> <span class="n">edit_text_path</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="p">:</span> <span class="n">new_text_path</span><span class="p">(</span><span class="ss">:text</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="ss">:path</span> <span class="o">=&gt;</span> <span class="n">obj</span><span class="o">.</span><span class="n">path</span><span class="p">})</span>
    <span class="n">content_tag</span><span class="p">(</span><span class="ss">:div</span><span class="p">,</span> <span class="n">link_to</span><span class="p">(</span><span class="n">t</span><span class="p">(</span><span class="s2">&quot;moderator.edit_text&quot;</span><span class="p">),</span> <span class="n">url</span><span class="p">),</span> <span class="ss">:class</span> <span class="o">=&gt;</span> <span class="s1">&#39;moderator moderator_edit moderator_edit_text&#39;</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre>
</div>
<p>Осталось немного, при создании новых текстов прицепить значения из локали:</p>
<div class="highlight"><pre><code class="ruby"><span class="k">class</span> <span class="nc">TextsController</span> <span class="o">&lt;</span> <span class="no">InheritedResources</span><span class="o">::</span><span class="no">Base</span>
  <span class="kp">include</span> <span class="no">InheritedDefaults</span>
  <span class="n">admin_panel</span>

  <span class="k">def</span> <span class="nf">new</span>
    <span class="vi">@text</span> <span class="o">=</span> <span class="no">Text</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:text</span><span class="o">]</span> <span class="o">||</span> <span class="p">{})</span>
    <span class="k">if</span> <span class="vi">@text</span><span class="o">.</span><span class="n">path?</span>
      <span class="vi">@text</span><span class="o">.</span><span class="n">body_ru</span> <span class="o">=</span> <span class="n">t</span><span class="p">(</span><span class="vi">@text</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="ss">:scope</span> <span class="o">=&gt;</span> <span class="s1">&#39;texts&#39;</span><span class="p">,</span> <span class="ss">:locale</span> <span class="o">=&gt;</span> <span class="ss">:ru</span><span class="p">)</span>
      <span class="vi">@text</span><span class="o">.</span><span class="n">body_en</span> <span class="o">=</span> <span class="n">t</span><span class="p">(</span><span class="vi">@text</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="ss">:scope</span> <span class="o">=&gt;</span> <span class="s1">&#39;texts&#39;</span><span class="p">,</span> <span class="ss">:locale</span> <span class="o">=&gt;</span> <span class="ss">:en</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre>
</div>
<p>Done! Всё гениальное просто, вроде бы.</p>
<p>Кстати, забавный интерфейсный мини-коллапс произошёл с человеком из агентства, который вставлял английские тексты.</p>
<p>В форме редактирования текста поля назывались <em>Содержание</em> и <em>Body</em> и показывались одновременно, чтобы видеть соответствие:</p>
<p><img src="/programmingshit/images/edit-texts/form.png" width="" height="" alt="" class="image-bordered"/></p>
<p>Видимо предложение заменить русские тексты в английской версии он воспринял буквально и засадил английский текст в оба поля, везде, где ступала нога. Surprise!</p>
</div>]]>
    </content>
  </entry>
  
  <entry>
    <title>
      <![CDATA[Выведите контент в RSS]]>
    </title>
    <link type="text/html" href="http://mindscan.msk.ru/programmingshit/show-content-in-rss.html"/>
    <updated>2012-02-14T00:00:00+04:00</updated>
    <id>http://mindscan.msk.ru/programmingshit/show-content-in-rss</id>
    <content type="html">
      <![CDATA[<div class="l-content post_rss">

<p class="intro"><b>Посты в <span class="caps">RSS</span> для контентных сайтов — это не твиты об обновлениях и не тизеры материалов, а&nbsp;альтернативный канал вещания.</b></p>
<p>Призывы пойти почитать статью на сайте, хоть и объяснимы ленью адаптировать содержание, желанием покрутить рекламу или просто тёмностью, всё-таки non comme il faut: контент должен быть по-максимуму доступен в фиде, чтобы его можно было читать здесь и сейчас. Если нужно крутить рекламу, вставьте её!</p>
<p>Проще всего понять ленту <span class="caps">RSS</span>, применив метафору <em>мобильной версии сайта</em>:</p>
<ul>
	<li>чтобы контент было удобно потреблять на мобильных устройствах, она должна быть;</li>
	<li>полноценной её не назовёшь, но&nbsp;квинтэссенцию: картинки и текст — должна выдавать.</li>
</ul>
<div class="l-mark l-mark_peepcode"><font color="999999">Несмотря на&nbsp;нестандартный вид статей, <a href="http://peepcode.com/blog">Peepcode</a> отдаёт их в&nbsp;фид, одновременно напоминая: <i>This article is heavily styled and is best viewed at&nbsp;<a href="http://peepcode.com/blog/2009/ruby-emacs-flog">PeepCode</a>!</i></font></div>
<div><img src="/programmingshit/images/rss/peepcode.png" width="850" height="808" alt="" id="peepcode" /></div>
<div class="l-columns clearfix">
<div class="l-column"><p>Для начала в&nbsp;ленту надо вывести <em>максимально полное</em> содержание, парой регекспов сделать абсолютные ссылки в тексте и пути к&nbsp;изображениям — это уже результат!</p></div>
<div class="l-mark"><font color="999999">Например для&nbsp;<a href="http://bangbangstudio.ru/shooters/japanese">шутеров Bang! Bang!</a> выводится основная колонка, без&nbsp;сайдбара слева и&nbsp;фанатизма.</font></div>
</div>
<p>В более сложных случаях, когда содержание имеет кастомную верстку, его нужно адаптировать, буквально заставить выглядеть нормально без помощи <span class="caps">CSS</span>&nbsp;— это можно сравнить с&nbsp;вёрсткой под&nbsp;дегенеративные браузеры.</p>
<div class="l-columns clearfix">
<div class="l-column"><p>Сложные куски инфографики, как например <a href="http://www.the-village.ru/village/food/restaurants/110951-mezhdu-bulok-vnutrennosti-20-moskovskih-burgerov">аутопсию гамбургеров на&nbsp;Village</a>, можно отливать полностью в&nbsp;картинках (ценность «кунжута на булочке» для <span class="caps">SEO</span> минимальна)&nbsp;— материал так готовится быстрее и&nbsp;проще, а выглядит он, в сравнении с&nbsp;вёрсткой редактора, лучше, и, что важно в&nbsp;текущем контексте — готов к&nbsp;употреблению в&nbsp;фидах. Ну и теоретически, если редакция уделяет внимание доступности контента, она может готовить упрощённую версию поста для&nbsp;фидов.</p></div>
<div class="l-mark"><font color="999999">Смотрите ещё микро про&nbsp;<a href="http://robotector.tumblr.com/post/15773151644/burger-graphics">бургерографику</a>.</font></div>  
</div>
<p>Пожалуйста, выведите контент в <span class="caps">RSS</span>!</p>
</div>]]>
    </content>
  </entry>
  
  <entry>
    <title>
      <![CDATA[Забудьте про регистрацию с паролями!]]>
    </title>
    <link type="text/html" href="http://mindscan.msk.ru/programmingshit/registration-forms-suck-big-time.html"/>
    <updated>2012-01-13T00:00:00+04:00</updated>
    <id>http://mindscan.msk.ru/programmingshit/registration-forms-suck-big-time</id>
    <content type="html">
      <![CDATA[<div class="l-content">
<p class="intro"><b><a href="http://me.veekun.com/blog/2011/12/04/fuck-passwords/">Пароли утомляют</a><span class="pseudo-a">.</span></b></p>
<p>Но всё-таки абсолютное большинство новых сайтов продолжают неистово делать свои собственные, одинаково унылые формы, со&nbsp;всем сопутствующим набором: отправками ссылок для подтверждения, &laquo;забыли пароль?&raquo; и&nbsp;прочим &laquo;посмотрите в&nbsp;папке Spam&raquo;.</p>
<p>Формы регистрации больше не&nbsp;нужны! Они неудобны пользователю.</p>
<div class="l-colums clearfix">
<div class="l-column"><p><img src="/programmingshit/images/registrations/zvooq.png" alt="" width="553" height="262" id="zvooq" /></p></div>
<div class="l-mark l-mark_zvooq"><font color="999999"><p><a href="http://zvooq.ru">Zvooq</a> правильно показывает, чем нужно пользоваться.</p><p>Уверен, что если&nbsp;бы им&nbsp;не&nbsp;нужно было мигрировать пользователей с&nbsp;советского сайта&nbsp;&mdash; они&nbsp;бы сделали авторизацию только через Facebook.</p><p>Для простоты буду называть проблему занудных аутентификации, авторизации и&nbsp;идентификации просто авторизацией.</p><p></font></div></p>
</div>
<p>Если браузеры ещё не&nbsp;поддерживают собственных механизмов (хотя многие об&nbsp;этом говорят, начиная с&nbsp;<a href="http://www.azarask.in/blog/">сына Раскина</a>, кажется), то&nbsp;остаётся использовать меньшее из&nbsp;зол&nbsp;&mdash; авторизацию через внешних провайдеров: <span class="symbol symbol_text">f&nbsp;t&nbsp;g&nbsp;v</span>&nbsp;и&nbsp;многих других. Благодаря&nbsp;<a href="http://www.omniauth.org/">Omniauth</a> это можно сделать очень быстро. У&nbsp;кого-то нет Facebook, Twitter, Google или Вконтакте-аккаунта? Можно для них добавить OpenID через Яндекс, OAuth через mail.ru, а остальным меньшинством пренебречь.</p>
<p>Если обязательно нужна почта для общения с&nbsp;пользователем, то&nbsp;можно использовать только провайдеров, отдающих email, или, в&nbsp;конце-концов, дать возможность вводить почту в&nbsp;настройках.</p>
<p>Не&nbsp;нужно делать и&nbsp;администраторов сайта с&nbsp;паролями, пусть они также авторизуются через внешних провайдеров.</p>
<p>Если пароли остались в&nbsp;качестве наследия старого режима, то&nbsp;нужно хотя&nbsp;бы безболезненно для&nbsp;пользователя сделать слияние аккаунтов&nbsp;&mdash; по&nbsp;возможности без лишних вопросов, вроде:</p>
<p><img src="/programmingshit/images/registrations/lookatme.png" alt="" width="339" height="185" /></p>
<p>Довольно часто соответствие можно установить по&nbsp;email.</p>
<p>В общем забудьте про регистрацию!</p>
</div>]]>
    </content>
  </entry>
  
  <entry>
    <title>
      <![CDATA[Как я клеил брендирование для Follow me]]>
    </title>
    <link type="text/html" href="http://mindscan.msk.ru/programmingshit/kak-ya-kleil-brendirovanie-dlya-followme.html"/>
    <updated>2011-08-29T20:40:00+04:00</updated>
    <id>http://mindscan.msk.ru/programmingshit/kak-ya-kleil-brendirovanie-dlya-followme</id>
    <content type="html">
      <![CDATA[<div class="l-content text">

<p class="intro"><b>На <a href="http://radiofollow.me/">Follow me</a> нужно было сделать возможность кастомного оформления страниц: фон, стили, баннеры, чтоб, например, забрендировать какую-нибудь передачу. Задача чуть менее, чем&nbsp;полностью банальная, но получилось вроде забавно.</b></p>
</div>
<div id="branding">
<div class="l-content">
<img src="/programmingshit/images/branding/branding.png" alt="" width="911" height="200" />
</div>
</div>
<div class="l-content text">

<p>В стандартной модели <code>Branding</code> задаётся урл, для которого брендирование, период активности, автомат для&nbsp;состояний, ну и все описанные выше свойства кастомные.</p>
<p>Логика выбора брендирования — в классе <code>BrandingSelector</code>, для каждого свойства выбирается первый брендинг с&nbsp;ним:</p>
<div class="highlight"><pre><code class="ruby"><span class="k">class</span> <span class="nc">BrandingSelector</span>
  <span class="kp">attr_reader</span> <span class="ss">:controller</span><span class="p">,</span> <span class="ss">:urls</span>

  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">controller</span><span class="p">)</span>
    <span class="vi">@controller</span> <span class="o">=</span> <span class="n">controller</span>
  
    <span class="vi">@urls</span> <span class="o">=</span> <span class="o">[</span><span class="n">controller</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">fullpath</span><span class="p">,</span> <span class="s2">&quot;*&quot;</span><span class="o">]</span>
    <span class="k">if</span> <span class="n">controller</span><span class="o">.</span><span class="n">action_name</span> <span class="o">==</span> <span class="s1">&#39;show&#39;</span> <span class="o">&amp;&amp;</span> <span class="n">controller</span><span class="o">.</span><span class="n">respond_to?</span><span class="p">(</span><span class="ss">:resource</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">controller</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:resource</span><span class="p">)</span><span class="o">.</span><span class="n">respond_to?</span><span class="p">(</span><span class="ss">:parent_url</span><span class="p">)</span>
      <span class="vi">@urls</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="n">controller</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:resource</span><span class="p">)</span><span class="o">.</span><span class="n">parent_url</span><span class="p">)</span>
    <span class="k">end</span>
    <span class="vi">@urls</span> <span class="o">=</span> <span class="vi">@urls</span><span class="o">.</span><span class="n">flatten</span>
  <span class="k">end</span>

  <span class="sx">%w{css top_banner sidebar_banner image}</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">method</span><span class="o">|</span>
    <span class="n">define_method</span> <span class="nb">method</span> <span class="k">do</span>
      <span class="p">(</span><span class="n">branding</span> <span class="o">=</span> <span class="n">first_branding_with</span><span class="p">(</span><span class="nb">method</span><span class="p">))</span> <span class="o">&amp;&amp;</span> <span class="n">branding</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">first_branding_with</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
    <span class="n">brandings</span><span class="o">.</span><span class="n">find</span><span class="p">{</span><span class="o">|</span><span class="n">b</span><span class="o">|</span> <span class="n">b</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">#{</span><span class="nb">method</span><span class="si">}</span><span class="s2">?&quot;</span><span class="p">)}</span>
  <span class="k">end</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">brandings</span>
    <span class="vi">@brandings</span> <span class="o">||=</span> <span class="no">Branding</span><span class="o">.</span><span class="n">current</span><span class="o">.</span><span class="n">scoped_by_url</span><span class="p">(</span><span class="n">urls</span><span class="p">)</span><span class="o">.</span><span class="n">sort_by</span><span class="p">{</span><span class="o">|</span><span class="n">b</span><span class="o">|</span> <span class="n">urls</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">url</span><span class="p">)}</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre>
</div>
<p>Если бы я не поленился сделать <code>has_many</code>-роуты для подкастов (для отдельной передачи я использую <code>/podcasts/miks-noizar</code> вместо гипотетического <code>/flows/mixes/miks-noizar</code>, например), то можно было бы всю систему завязать полностью на иерархии урлов, иначе пришлось лепить костыль в&nbsp;виде метода <code>parent_url</code>, который для подкаста возвращает <code>/flows/#{flow.permalink}</code>, в принципе это даёт какое-то пространство для игры: например постам в блоге можно было бы поставить <code>/blog</code>.</p>
<p>Ну и как-то выводим это:</p>
<div class="highlight"><pre><code class="erb"><span class="cp">&lt;%</span> <span class="k">if</span> <span class="n">css</span> <span class="o">=</span> <span class="vi">@branding_selector</span><span class="o">.</span><span class="n">try</span><span class="p">(</span><span class="ss">:css</span><span class="p">)</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="x">  &lt;style media=&quot;screen&quot; type=&quot;text/css&quot;&gt;</span>
<span class="x">    </span><span class="cp">&lt;%=</span> <span class="n">css</span><span class="o">.</span><span class="n">html_safe</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="x">  &lt;/style&gt;</span>
<span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span><span class="x"></span>
</code></pre>
</div>
</div>]]>
    </content>
  </entry>
  
  <entry>
    <title>
      <![CDATA[Мета-теги для Facebook минимально и достаточно]]>
    </title>
    <link type="text/html" href="http://mindscan.msk.ru/programmingshit/meta-tegi-dlya-facebook-minimalno-i-dostatochno.html"/>
    <updated>2011-08-21T10:00:00+04:00</updated>
    <id>http://mindscan.msk.ru/programmingshit/meta-tegi-dlya-facebook-minimalno-i-dostatochno</id>
    <content type="html">
      <![CDATA[<div class="l-content">
<p>В хэлпере устанавливаем дефолтные <a href="http://developers.facebook.com/docs/opengraph/">свойства</a> для всего сайта, например:</p>
<div class="highlight"><pre><code class="ruby"><span class="k">def</span> <span class="nf">meta</span>
  <span class="vi">@meta</span> <span class="o">||=</span> <span class="p">{</span>
    <span class="c1"># helper to get a page title for the current url</span>
    <span class="s1">&#39;og:title&#39;</span>     <span class="o">=&gt;</span> <span class="n">title</span><span class="p">,</span>
    <span class="s1">&#39;og:type&#39;</span>      <span class="o">=&gt;</span> <span class="s1">&#39;article&#39;</span><span class="p">,</span>
    <span class="s1">&#39;og:url&#39;</span>       <span class="o">=&gt;</span> <span class="n">request</span><span class="o">.</span><span class="n">url</span><span class="p">,</span>
    <span class="s1">&#39;og:site_name&#39;</span> <span class="o">=&gt;</span> <span class="n">t</span><span class="p">(</span><span class="s1">&#39;titles.default&#39;</span><span class="p">),</span>
    <span class="s1">&#39;og:image&#39;</span>     <span class="o">=&gt;</span> <span class="n">image_path</span><span class="p">(</span><span class="s1">&#39;logo-share.jpg&#39;</span><span class="p">),</span>
    <span class="s1">&#39;fb:admins&#39;</span>    <span class="o">=&gt;</span> <span class="s1">&#39;..., ..., ...&#39;</span>
  <span class="p">}</span>
<span class="k">end</span>
</code></pre>
</div>
<p>Выводим в лейауте:</p>
<div class="highlight"><pre><code class="erb"><span class="cp">&lt;%</span> <span class="n">meta</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="x">  </span><span class="cp">&lt;%=</span> <span class="n">tag</span> <span class="ss">:meta</span><span class="p">,</span> <span class="ss">:property</span> <span class="o">=&gt;</span> <span class="n">k</span><span class="p">,</span> <span class="ss">:content</span> <span class="o">=&gt;</span> <span class="n">v</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span><span class="x"></span>
</code></pre>
</div>
<p>На страницах, где свойства нужно закастомайзить, просто мёрджим их в <code>meta</code>. Например, для&nbsp;<a href="http://radiofollow.me/podcasts/post-chillwave-srfr-vypusk-2">подкаста</a> в&nbsp;темплейте <code>podcasts/show</code>:</p>
<div class="highlight"><pre><code class="erb"><span class="cp">&lt;%</span> <span class="n">meta</span><span class="o">.</span><span class="n">merge!</span><span class="p">(</span>
  <span class="s1">&#39;og:description&#39;</span> <span class="o">=&gt;</span> <span class="n">resource</span><span class="o">.</span><span class="n">lead</span><span class="p">,</span> 
  <span class="s1">&#39;og:image&#39;</span>       <span class="o">=&gt;</span> <span class="n">image_path</span><span class="p">(</span><span class="n">resource</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
<span class="p">)</span> <span class="cp">%&gt;</span><span class="x"></span>
</code></pre>
</div>
<p>Piece of cake!</p>
</div>]]>
    </content>
  </entry>
  
 
</feed>
