在rails中创建动态帮助器方法

时间:2009-12-16 21:44:06

标签: ruby-on-rails metaprogramming

我正在尝试创建一堆这样的动态辅助方法:

show_admin_sidebar
show_posts_sidebar
show_users_sidebar

到目前为止,我在helper.rb文件中有这个:

#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

在我的应用程序布局文件中,我有:(注意 - 我正在使用HAML):

- if show_sidebar?
  = yield(:sidebar)

这允许我在我的观点中说出以下内容:

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

这会产生所需的部分。

这个问题是我每页只能添加一个侧边栏。所以,我想我需要动态方法,如:show_admin_sidebar,show_foo_sidebar。

所以我试图这样做:

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

然后在我的布局中:

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

但是rails根本不喜欢这个。

我已经在我的帮助文件中尝试了几乎所有我能想到的东西,但没有任何效果。

我使用帮助方法的原因是因为我希望我的内容div是100%页面宽度,除非有侧边栏存在,在这种情况下主要内容进入一个较小的div并且侧边栏内容进入它自己的..

如果我不能使这个工作,那么我可以通过手动添加部分来轻松解决问题,但我想让我的头围绕这个.......

任何人都有这方面的经验吗?

3 个答案:

答案 0 :(得分:4)

对此的整个方法简直过于复杂,根本没有遵循Rails惯例,也没有任何意义,并且对先前的受访者感到羞耻,因为他们支持这种方法而不是帮助他简化。我很抱歉13个月的答案。

您的控制器应决定是否显示侧栏,并将实例变量@side_bar_name设置为nil或侧边栏名称字符串。然后在共享视图代码中的某个地方,可能是views / layouts / application.html.erb,你会有一些简单的东西:

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

或者更好:

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

如果你想使用一个帮助器(这对于保持你的代码DRY和可读性并不是一个坏主意),它基本上是相同的代码,只是移动到帮助器。

<%= side_bar_helper %>

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

控制器的功能取决于您。它可能会做这样的事情:

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

答案 1 :(得分:2)

这是一个适合您的解决方案,但我不会建议过多的元编程:

#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

答案 2 :(得分:0)

  

def show _#{name} _sidebar(show_sidebar = true)

对我来说,这看起来不像有效的Ruby。您是在自己解析和评估这个问题,还是只是将其放在文件中并期望它能够正常工作?