Skip to content

Instantly share code, notes, and snippets.

@ugisozols
Last active April 18, 2017 09:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ugisozols/6805942 to your computer and use it in GitHub Desktop.
Save ugisozols/6805942 to your computer and use it in GitHub Desktop.
Refinery CMS - updated MenuPresenter guide
h2. Additional Menus
This guide will show you how to:
* configure and use +Refinery::Pages::MenuPresenter+
* use a decorator to add custom functionality to +Refinery::Page+ class
* override Refinery's view
endprologue.
h3. Requirements
Lets start with requirements. I tried to bring them together in the follwoing steps:
* We need to add additional navigation menu in the footer section of each page right above Refinery's copyright notice.
* Admin should be able to specify which pages appears in the footer menu so I'm thinking we'll add a checkbox under "Advanced options" in the page edit form.
* Data about whether page shows up in the footer should be persisted to database.
Alright, it's time to dive deep into the code.
h3. Adding +show_in_footer+ column to +refinery_pages+ database table
The requirement was to persist the data to database so we will start by creating a migration which will add +show_in_footer+ column to +refinery_pages+ database table. Open up terminal and type:
<shell>
rails generate migration add_show_in_footer_to_refinery_pages
</shell>
This will generate an empty migration. Open it and add the following code:
<ruby>
class AddShowInFooterToRefineryPages < ActiveRecord::Migration
def change
add_column :refinery_pages, :show_in_footer, :boolean, :default => false
end
end
</ruby>
h3. Decorating the Refinery::Page model
Before overriding Refinery's form view we will have to decorate +Refinery::Page+ class. Create a file +app/decorators/models/refinery/page_decorator.rb+ with this content:
<ruby>
Refinery::Page.class_eval do
attr_accessible :show_in_footer
def self.footer_menu_pages
where :show_in_footer => true
end
end
</ruby>
We added +show_in_footer+ to allowed attributes list so that it doesn't raise mass-assignment error each time someone tries to save the page. We also added +footer_menu_pages+ class method to abstract away ActiveRecord query method.
h3. Overriding form view
As I previously mentioned it lets make it so that "Show in footer" checkbox appears right after admin clicks "Advanced options" when editing page so we will have to override [_form_advaned_options.html.erb partial](https://github.com/refinery/refinerycms/blob/2-1-stable/pages/app/views/refinery/admin/pages/_form_advanced_options.html.erb). Type this in the terminal:
<shell>
rake refinery:override view=refinery/admin/pages/_form_advanced_options.html
</shell>
Now open +_form_advanced_options.html.erb+ partial and add the following code right after h2 HTML tag:
<html>
<div class='field'>
<span class='label_with_help'>
<%= f.label :show_in_footer, "Show in footer" %>
</span>
<%= f.check_box :show_in_footer %> Show this page in the footer menu
</div>
</html>
The end result should look like this:
!/system/images/W1siZiIsIjIwMTMvMTAvMDMvMDZfMzdfMTNfOTMzX3Nob3dfaW5fZm9vdGVyLnBuZyJdXQ/show_in_footer.png!
h3. Creating and configuring the Presenter
Now lets focus on the presener itself. Once instantiated, it is also possible to configure its CSS/HTML using this instance. We will use a Rails helper to instantiate a new instance of +Refinery::Pages::MenuPresenter+ and also configure it there. We're taking this approach because we don't want to pollute the view with configuration code.
Open ApplicationHelper and add this code:
<ruby>
def footer_menu
menu_items = Refinery::Menu.new(Refinery::Page.footer_menu_pages)
presenter = Refinery::Pages::MenuPresenter.new(menu_items, self)
presenter.dom_id = "footer_menu"
presenter.css = "footer_menu"
presenter.menu_tag = :div
presenter
end
</ruby>
We create an instance of +Refinery::Menu+ by passing a collection of footer pages (+Refinery::Page.footer_menu_pages+) to it. We need it because it will be the data that will be "presented" by +Refinery::Pages::MenuPresenter+. We assign this instance to a variable called +presenter+ in order to configure this presenter. I want my footer menu to be wrapped inside of a +div+ tag instead of the default +nav+ tag and I also want it to have a CSS class and an ID of +footer_menu+ instead of the default +menu+ one:
<ruby>
presenter.dom_id = "footer_menu"
presenter.css = "footer_menu"
presenter.menu_tag = :div
</ruby>
Now that we have configured the menu presenter we need to return it because we'll have to call +.to_html+ on it in the view later on.
h3. Rendering the Menu in the View
Requirement was for the footer menu to appear just above Refinery's copyright notice. To do that we will simply override Refinery's footer view:
<shell>
rake refinery:override=refinery/_footer
</shell>
Next, add this code above the existing code:
<erb>
<%= footer_menu.to_html %>
</erb>
h3. Taking a look at it
Now it's time to take a look at how everything is working. Edit a couple of pages and for some of them check "Show in footer" checkbox located under "Advanced options". Now go to the root url of your site and take a look at the bottom - you should see links for pages for which you checked "Show in footer" checkbox. Also here's how the generated HTML should look:
<html>
<div class="footer_menu" id="footer_menu">
<ul>
...
</ul>
</div>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment