Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replaced menu partials with Refinery::Pages::MenuPresenter. #2069

Merged
merged 1 commit into from
Dec 18, 2012

Conversation

parndt
Copy link
Member

@parndt parndt commented Dec 7, 2012

This has many advantages not least of which is that we can test it without requesting pages.

@ugisozols @robyurkowski Merges on top of #2068 if you guys approve.

@parndt
Copy link
Member Author

parndt commented Dec 7, 2012

@ugisozols for bonus points can you please rewrite the current specs that basically just check the menu's output to unit tests? 👍

@keithpitty
Copy link
Contributor

@parndt sounds like a nice example of therapeutic refactoring for you!

@parndt
Copy link
Member Author

parndt commented Dec 7, 2012

@keithpitty the partials are dead; long live the presenter! So happy.

:dom_id => 'menu',
:nav => :nav,
:ul => :ul,
:li => :li,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For one, why not just make it a private attr_reader? A class having to read its attributes out of a hash seems weird to me.

Second, allowing customizability of the specific tag that gets used seems of little utility. I'd replace line 33 with a method that rendered the list item to allow a subclass of MenuPresenter to customize list items if it were so desired.

@phiggins
Copy link
Contributor

phiggins commented Dec 7, 2012

I wanted to do this for a long time. Good work @parndt! 🍊

@parndt
Copy link
Member Author

parndt commented Dec 7, 2012

@phiggins updated a couple things; great idea about the attr_readers too. Gotta go out all day but will address later (unless someone else can).

@phiggins
Copy link
Contributor

phiggins commented Dec 7, 2012

(unless someone else can)

Real subtle. :trollface:

@parndt
Copy link
Member Author

parndt commented Dec 7, 2012

Totally

@parndt
Copy link
Member Author

parndt commented Dec 9, 2012

@parndt
Copy link
Member Author

parndt commented Dec 11, 2012

So we have an issue whereby we've hit a limitation when having a many-deep nested set it hits SQL quite a lot. I've discussed this with @simi at great length and we haven't come up with a solution yet. It's not a new issue but it's something that we should really deal with.

One idea I had after waking up is that we could delegate URL building to some other module that Page (but actually MenuItem) could delegate to. This would mean menu_items would need to have smarter attributes for to_param to be in there. And the menu would have to be instructed to build a nested URL or something.

page.has_children? && page.descendants.any?(&method(:selected_page?))
end

def selected_page_or_descendant_page_selected?(page)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is called with menu_item as a parameter. Should we continue to use that name throughout these private methods for clarity about what class the parameters are?

This has many advantages not least of which is that we can test it without requesting pages.

* Using config_accessor and attr_accessor instead of passing options around.
* Added leaf? to MenuItem and made use of has_children? in the MenuPresenter
* All methods besides initialize and to_html are private to this class.
* Moved Refinery::Core#menu_css to the Refinery::Pages::MenuPresenter.
* Uses MenuItem#depth instead of scanning ancestors.
* Renamed levels to max_depth and added within_max_depth?
* Refactored Menu and MenuItem as proper objects, not pretending to be hashes or arrays (ht: @awagener)
* Move Menu#initialize logic to Menu#append so that more items can be appended after initialize.
* Moved all page presenters and their specs under app/presenters and spec/presenters where they belong.
robyurkowski added a commit that referenced this pull request Dec 18, 2012
Replaced menu partials with Refinery::Pages::MenuPresenter.
@robyurkowski robyurkowski merged commit 24170e4 into menu_refactor Dec 18, 2012
ugisozols added a commit that referenced this pull request Dec 18, 2012
@keram
Copy link
Contributor

keram commented Dec 18, 2012

are there any benchmarks for this change?
this is big change and I'm also not to sure about including this to 2.1 because this may be one of the biggest changes in refinery logic and makes incompatibility with existing applications.
Also new documentation abour overriding menu would by needed because as I think, from view of the web developer, menu partial template was one of the most overrided templates and I think now customize menu may be for developers harder ;/
m.

@parndt
Copy link
Member Author

parndt commented Dec 18, 2012

Benchmarks generally lie ;-) so I this ran myself in development, test and production modes with lots of differently sized menus and the performance is very good, save for the problems identified in issue #2087 which are unrelated to this refactor and were already an issue. On my system, which is just a 13" Macbook Pro, the performance was around 8ms in development and 3ms in production mode to render the entire menu of as many pages as you like. This performance declines as more pages are nested below other pages but this was an existing problem which, I think, is now much easier to solve and if not in 2.1.0 then it can be relatively transparently solved in 2.1.1, 2.1.2 etc without a change required to the public API of the presenter (MenuPresenter#initialize and MenuPresenter#to_html methods). In future this can also be trivially extended to support MenuPresenter#to_json or MenuPresenter#to_csv or MenuPresenter#to_whatever_format_you_want. This is also the basis for allowing multiple different menus inside Refinery in a future version, for example a footer menu, which I'm quite excited about.

Customising the menu and upgrading between different versions is now much easier because you only have to override single methods (i.e. menu_presenter_decorator) or define your own presenter (i.e. class MyMenuPresenter < Refinery::Pages::MenuPresenter) but we are in the process of writing the documentation that will guide you through this stuff.

The point that menu partial was one of the most popular templates to override made it such a good candidate for refactor. I've dealt with so, so many applications which have had this overridden and then when it came time to upgrade this was the place that had the most errors. It was a complete pain to try to figure out the differences between the versions whereas now it is much cleaner and easier.

If you really wanted, you could ignore the presenter completely and still keep using the old partial approach (just override header, menu and menu_branch from 2-0-stable and they will continue to work) but this is not shipping by default with Refinery anymore.

Do you think I should put the partials back in with a deprecation warning for any applications that are upgrading and have the header overridden? I figured this wouldn't work because the user would most likely also have both menu partials overridden anyway so no notice would be seen anyway. This will be a major point highlighted in the upgrade notes and any blog post we write about the release of 2.1.0. No doubt we'll still have lots of questions on the user group but we always do! :-)

I'm much, much happier with the menu presenter than I ever was with the menu partials, which I've been unhappy about since well before version 1.0. I hope that I've explained my point of view without rambling too much. Let me know if I can improve on anything that I've said and I'm also interested to hear your further thoughts on this.

Thanks! 👍

@pdostal
Copy link

pdostal commented Aug 5, 2014

@parndt here it's http://refinerycms.com/guides/menu-presenter
...but I'm beginner and I actually need to build custom menu and it's not so easy :)

There is even StackOverflow thread http://stackoverflow.com/questions/14759712/rails-bootstrap-navbar-and-refinerycms with few different ways how to override simple menu.

@gwagener
Copy link
Contributor

gwagener commented Aug 5, 2014

@pdostal How custom does it need to be? I've managed to make a perfectly functional Bootstrap menu by only changing MenuPresenter's config in an initializer. If you need custom contents in your menu there's https://github.com/isaacfreeman/refinerycms-menus/tree/rails-4-1(the branch that works with Rails 4 and Refinery master). To be honest, Gitter or IRC are probably better places to ask questions.

@pdostal
Copy link

pdostal commented Aug 5, 2014

@gwagener It wasn't question, I just said that it isn't easy for me. But thanks for your advice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants