简体   繁体   中英

creating dynamic helper methods in rails

I am trying to create a bunch of dynamic helper methods like these:

show_admin_sidebar
show_posts_sidebar
show_users_sidebar

So far I have this in my helper.rb file:

#spits out a partial 
def show_sidebar(name, show_sidebar = true)
  @content_for_sidebar = render :partial => "partials/#{name}"                       
  @show_sidebar = show_sidebar
end

def show_sidebar?
  @show_sidebar
end

In my application layout file I have this: (NB - I'm using HAML):

- if show_sidebar?
  = yield(:sidebar)

This allows me to say the following in my views:

- show_sidebar(:foo)
- show_sidebar(:bar)

And this renders the desired partial.

The problem with this is that I can only add one sidebar per page. So, I figure I need to have dynamic methods like: show_admin_sidebar, show_foo_sidebar.

So I have tried to do this:

def show_#{name}_sidebar(show_sidebar = true)
@name = name  
@content_for_#{@name}_sidebar = render :partial => "partials/#{@name}"                       
  @show_sidebar = show_sidebar
end

and then in my layout:

- if show_sidebar?
  = yield("{@name}_sidebar")

But rails does not like this at all.

I have tried almost everything I can think of in my helper file and nothing works.

The reason I am using helper methods for this is because I want my content div to be 100% page width unless there is a sidebar present in which case the main content goes into a smaller div and the sidebar content goes into it's own..

If I can't get this working, then I can easily fix the problem by just adding the partials manually but I'd like to get my head round this....

Anyone got any experience with this kind of thing?

The entire approach to this was bizarrely overcomplicated, didn't follow Rails conventions at all, nor make the slightest bit of sense, and shame on prior respondents for enabling this approach instead of helping him to simplify. My apologies for being 13 months late with the answer.

Your controller should be deciding if a sidebar is to be shown or not, and setting an instance variable @side_bar_name to either nil or a sidebar name string. Then somewhere in shared view code, probably views/layouts/application.html.erb, you would have something as simple as this:

<% if @side_bar_name %>
<%= render :partial => "partials/#{@side_bar_name}" %>
<% end %>

Or better yet:

<%= render(:partial => "partials/#{@side_bar_name}") if @side_bar_name %>

If you want to use a helper (which is not a bad idea for keeping your code DRY and readable) it would basically be the same code, just moved into the helper.

<%= side_bar_helper %>

def side_bar_helper
  render(:partial => "partials/#{@side_bar_name}") if @side_bar_name
end

What the controller does is up to you. It would probably do something like this:

if session[:show_side_bar]
  # maybe use cookies instead of session, or store user preference in a database
  @side_bar_name = session[:side_bar_name]
end

Here is a solution for you, however I wouldn't suggest too much metaprogramming:

#Add the following snippet to the proper helper module:
['admin','user','whatever'].each do |name|
  class_eval{
    "def show_#{name}_sidebar(show_sidebar = true)
       @name = #{name}  
       @content_for_#{@name}_sidebar = render :partial => 'partials/#{@name}'                       
       @show_sidebar = show_sidebar
     end"
  }
end

def show_#{name}_sidebar(show_sidebar = true)

That doesn't look like valid Ruby to me. Are you parsing and evaling this yourself or just throwing that right in the file and expecting it to work?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM