Forum: Ruby on Rails Links on the left hand side - are components necessary?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
D521c0db52fe0b14d799dd669d536098?d=identicon&s=25 Tony Mobily (merc)
on 2006-06-07 19:08
Hello,

Maybe this is super-trivial...
I need to have a list of links on the left hand side of my application,
for *every* single page.

So, I've created a layout called "main" (main.rhtml)  under
view/layouts, and included >layout "main"< in pretty all of my
controllers.

main.rhtml has, amongst all the other HTML stuff:

<%= render_component :controller=> 'dli/extras', :action=>
'show_lookup_links'%>

This is the component to display the links:

class Dli::ExtrasController < ApplicationController
  uses_component_template_root
  Link=Struct.new(:name,:controller,:action)

  def show_lookup_links
    @links=[]
    @links << Link.new("Channels", "/lookup/channel", "index")
    @links << Link.new("Password durations",
"/lookup/password_duration", "index")
    render :layout=>false
  end

end

Now: the list of links will need to change according to the user's
permission. So, there is quite a lot of logic involved here.

What are my options, if I don't want to use components?

The only solution I can think of is to add a method to the general
application controller (application.rb).  However, how do call such an
action from main.rhtml? It looks like I need to be able to specify
controller _and_ action, which brings me back to components...

Can somebody please enlighten me? I feel that I am heading the wrong
way, and...

Thanks,

Merc.
6d57db44c5a4e0721cc7f78cf0ce308a?d=identicon&s=25 Stephen Bartholomew (steveb)
on 2006-06-07 19:48
Components are going out of favour anyway so you're best off with
partials:

<%= render :partial => 'foo/bar' %>

then in app/views/foo/_bar.rhtml you include your code.  You can add the
logic into a before_filter method that creates an instance variable that
the partial can access.

You could also create a helper method in
app/helpers/application_helper.rb:

def my_helper(options = {})
  # make code
end

Then you can just call it in your templates:
<%= my_helper :option1 => 'foo', :option2 => 'bar' %>

The first method is probably best though.  If you're generating a list
of links, i would create a before_filter in application_controller that
loads the links into a collection then pass this to the partial:

- application_controller.rb
before_filter :load_menu

def load_menu
  # load links into @links
end

- main.rhtml
<ul>
 <%= render :partial => 'link', :collection => @links %>
</ul>

- _link.rhtml
<li><%= link %></li>

Check out
http://api.rubyonrails.org/classes/ActionControlle...
for more information about partials.

Hope that helps,

Steve

Tony Mobily wrote:
> Hello,
>
> Maybe this is super-trivial...
> I need to have a list of links on the left hand side of my application,
> for *every* single page.
>
> So, I've created a layout called "main" (main.rhtml)  under
> view/layouts, and included >layout "main"< in pretty all of my
> controllers.
>
> main.rhtml has, amongst all the other HTML stuff:
>
> <%= render_component :controller=> 'dli/extras', :action=>
> 'show_lookup_links'%>
>
> This is the component to display the links:
>
> class Dli::ExtrasController < ApplicationController
>   uses_component_template_root
>   Link=Struct.new(:name,:controller,:action)
>
>   def show_lookup_links
>     @links=[]
>     @links << Link.new("Channels", "/lookup/channel", "index")
>     @links << Link.new("Password durations",
> "/lookup/password_duration", "index")
>     render :layout=>false
>   end
>
> end
>
> Now: the list of links will need to change according to the user's
> permission. So, there is quite a lot of logic involved here.
>
> What are my options, if I don't want to use components?
>
> The only solution I can think of is to add a method to the general
> application controller (application.rb).  However, how do call such an
> action from main.rhtml? It looks like I need to be able to specify
> controller _and_ action, which brings me back to components...
>
> Can somebody please enlighten me? I feel that I am heading the wrong
> way, and...
>
> Thanks,
>
> Merc.
119af50160cabfe1fb6f2f05f5018c64?d=identicon&s=25 James Ludlow (Guest)
on 2006-06-07 19:54
(Received via mailing list)
On 6/7/06, Tony Mobily <merc@mobily.com> wrote:
>   def show_lookup_links
>     @links=[]
>     @links << Link.new("Channels", "/lookup/channel", "index")
>     @links << Link.new("Password durations",
> "/lookup/password_duration", "index")
>     render :layout=>false
>   end

This looks like trouble.  You're going to be better off if you use
link_to() and let Rails build the paths that it needs.  When I see
"/lookup/channel" hardcoded it sets off warning bells.

> Can somebody please enlighten me? I feel that I am heading the wrong
> way, and...

One thing that you could do to get away from using a component would
be to put the common pieces of your nav as partials in
/app/view/shared.  Your layout(s) could then use this shared nav RHTML
code as needed.

-- James
6ef8cb7cd7cd58077f0b57e4fa49a969?d=identicon&s=25 Brian Hogan (Guest)
on 2006-06-07 19:57
(Received via mailing list)
What's wrong with just putting

<%=link_to_unless_current "Home", :controller=>"main", :action=>"index"
%>

in your main.rhtml file

If they're always the same across all pages, why make the extra work?
If you need them to be dynamically generated, then use render :partial
as stated in an earlier post.
5d15c6821f3c3054c04b85471824ba7c?d=identicon&s=25 Kevin Olbrich (Guest)
on 2006-06-07 20:01
(Received via mailing list)
On Wednesday, June 07, 2006, at 7:48 PM, Stephen Bartholomew wrote:
>app/helpers/application_helper.rb:
>loads the links into a collection then pass this to the partial:
> <%= render :partial => 'link', :collection => @links %>
>
>> view/layouts, and included >layout "main"< in pretty all of my
>>   uses_component_template_root
>> end
>>
>_______________________________________________
>Rails mailing list
>Rails@lists.rubyonrails.org
>http://lists.rubyonrails.org/mailman/listinfo/rails

This is basically how I have done it.  A partial to display the links.
In my case, I am using the user_engine/login_engine combo, so all I have
to do is run a query against the permissions table to get a list of
actions that are allowed.  It's not perfect as it is because there are
several actions that you really wouldn't want users to call directly
(i.e., an 'edit' action needs an id to work).

Another approach would be to pre-generate a list of menu items and then
use 'link_if_authorized' instead of 'link_to'.  This will make them show
up only if the user has permission to access them (it's included in the
user_engine).


_Kevin
D521c0db52fe0b14d799dd669d536098?d=identicon&s=25 Tony Mobily (merc)
on 2006-06-08 03:34
Hello,

Brian Hogan wrote:
> What's wrong with just putting
>
> <%=link_to_unless_current "Home", :controller=>"main", :action=>"index"
> %>
>
> in your main.rhtml file
>
> If they're always the same across all pages, why make the extra work?

From my post:

"Now: the list of links will need to change according to the user's
permission. So, there is quite a lot of logic involved here."

> If you need them to be dynamically generated, then use render :partial
> as stated in an earlier post.

Yep - that's exactly what I'm doing.

Merc.
D521c0db52fe0b14d799dd669d536098?d=identicon&s=25 Tony Mobily (merc)
on 2006-06-08 06:33
Hi,

>>   def show_lookup_links
>>     @links=[]
>>     @links << Link.new("Channels", "/lookup/channel", "index")
>>     @links << Link.new("Password durations",
>> "/lookup/password_duration", "index")
>>     render :layout=>false
>>   end
>
> This looks like trouble.  You're going to be better off if you use
> link_to() and let Rails build the paths that it needs.  When I see
> "/lookup/channel" hardcoded it sets off warning bells.

Oh no, it's not. /lookup/channel is _actually_ a contoller's name which
lives in a separate directory (I put a whole bunched of controllers
under "lookup/..." and called them Lookup::ChannelController, for
example).

Merc.
This topic is locked and can not be replied to.