Как я клеил брендирование для Follow me

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

В стандартной модели Branding задаётся урл, для которого брендирование, период активности, автомат для состояний, ну и все описанные выше свойства кастомные.

Логика выбора брендирования — в классе BrandingSelector, для каждого свойства выбирается первый брендинг с ним:

class BrandingSelector
  attr_reader :controller, :urls

  def initialize(controller)
    @controller = controller
  
    @urls = [controller.request.fullpath, "*"]
    if controller.action_name == 'show' && controller.respond_to?(:resource) && controller.send(:resource).respond_to?(:parent_url)
      @urls.insert(-2, controller.send(:resource).parent_url)
    end
    @urls = @urls.flatten
  end

  %w{css top_banner sidebar_banner image}.each do |method|
    define_method method do
      (branding = first_branding_with(method)) && branding.send(method)
    end
  end

  def first_branding_with(method)
    brandings.find{|b| b.send("#{method}?")}
  end

  private

  def brandings
    @brandings ||= Branding.current.scoped_by_url(urls).sort_by{|b| urls.index(b.url)}
  end
end

Если бы я не поленился сделать has_many-роуты для подкастов (для отдельной передачи я использую /podcasts/miks-noizar вместо гипотетического /flows/mixes/miks-noizar, например), то можно было бы всю систему завязать полностью на иерархии урлов, иначе пришлось лепить костыль в виде метода parent_url, который для подкаста возвращает /flows/#{flow.permalink}, в принципе это даёт какое-то пространство для игры: например постам в блоге можно было бы поставить /blog.

Ну и как-то выводим это:

<% if css = @branding_selector.try(:css) %>
  <style media="screen" type="text/css">
    <%= css.html_safe %>
  </style>
<% end %>