开发者

Simple way to specify sidebar in the controller

I'm wrestling with something that should be very simple - specify a sidebar at the controller level. With layouts you can do this:

layout 'admin'

so I'd like to do the same for a sidebar, with something like this:

sidebar 'search'

I know I could specify the sidebar markup with content_for in the views, but I'd rather specify the sidebar at the controller level and not repeat code in (and clutter up) my views. I'd also like to be able to share sidebars between controllers.

At the moment I've got this in an initializer (a plugin seems like overkill for something so simple):

module Sidebar
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def sidebar(partial)
      # neither of these two work...
      @sidebar = partial
      instance_variable_set('@sidebar', partial)
    end
  end
end

ActionController::Base.send(:include, Sidebar)

and then in my layout I'm trying

<%= render "shared/#{@sidebar}" %>

but to no avail...

Does anyone know what I'm doing wrong, or if indeed I'm go开发者_如何学Going about this the right way at all? Any help is greatly appreciated!


This is a scope issue. The view requires an instance variable but your sidebar method works in the class scope.

module Sidebar
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def sidebar(partial)
      before_filter do |controller|
        controller.instance_eval { @sidebar = partial }
      end
    end
  end
end

ActionController::Base.send(:include, Sidebar)

If all your controllers include a sidebar, then you can consider to define an instance variable in your application controller.

class ApplicationController < ActionController::Base

  attr_accessor :sidebar

end

module Sidebar
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def sidebar(partial)
      before_filter do |controller|
        controller.sidebar = partial
      end
    end
  end
end

ActionController::Base.send(:include, Sidebar)

Also, if you don't have other methods, you can simplify your mixin even further.

class ApplicationController < ActionController::Base
  attr_accessor :sidebar
end

module Sidebar
  def sidebar(partial)
    before_filter do |controller|
      controller.sidebar = partial
    end
  end
end

ActionController::Base.extend(Sidebar)

Personally I don't like too much this approach. I prefer to define the content of a sidebar in the view file and fallback to a standard value in case no custom value is set.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜