Sidebars


#1

I love sidebars, sidebars are cool.

I’m less enamoured of our current implementation of 'em, because
they’re components and components are slow and a pain in the bum to
test.

With that in mind I’ve been playing with turning them into plugins
that delegate to a controller for almost everything. The basic parent
might look something like (with lots of handwaving)

class PluggableSidebar
@@subclasses = {}
cattr_accessor :controller
class << self
# Keep track of our subclasses and have them keep track of theirs
def inherited; …; end
def subclasses; … ; end

def available_sidebars
  subclasses.select {|sidebar| sidebar.subclasses.empty?}
end

end

class SetupSidebarFilter
class << self
def before(controller)
PluggableSidebar.controller = controller
end
def after(controller)
PluggableSidebar.controller = nil
end
end
end

def method_missing(*args)
if @@controller
@@controller.send(*args)
else
raise NoMethodError, “undefined method #{args[0]} for
#{self.class}”
end
end

def render(*args)
@performed = true
@@controller.render_to_string(*args)
end

def performed?
@performed || false
end

def configuration_wrapper
with_include_path(self.class.view_path) do
configure
render :partial => “configure”, :locals => {sidebar => self}
unless peformed?
end
end

def index
with_include_path(self.class.view_path) do
content
render :partial => “content”, :locals => {sidebar => self} unless
peformed?
end
end
end

Lots of stuff missing, obviously, but the basic goal is to turn
the Sidebar parent class into something that feels like a controller
to someone writing one, but which can be called with a helper without
having to go through the rather heavyweight process of rendering a
component.

Also, I want to be able unify the current Sidebar and
SidebarController classes in such a way that a Sidebar can be
serialized to YAML and stored on the blog object, and in a
:staged_sidebars key in the flash.

Thoughts?


#2

This looks pretty reasonable, at least in principal. Care to providean
example of what one of the existing sidebars would look like, andhow the
sidebar views fit into the picture?

Scott
On 3/20/06, Piers C. removed_email_address@domain.invalid wrote:> I love sidebars,
sidebars are cool.>> I’m less enamoured of our current implementation of
'em, because> they’re components and components are slow and a pain in
the bum to> test.>> With that in mind I’ve been playing with turning
them into plugins> that delegate to a controller for almost everything.
The basic parent> might look something like (with lots of handwaving)>>
class PluggableSidebar> @@subclasses = {}> cattr_accessor
:controller> class << self> # Keep track of our subclasses and
have them keep track of theirs> def inherited; …; end> def
subclasses; … ; end>> def available_sidebars>
subclasses.select {|sidebar| sidebar.subclasses.empty?}> end>
end>> class SetupSidebarFilter> class << self> def
before(controller)> PluggableSidebar.controller = controller>
end> def after(controller)> PluggableSidebar.controller =
nil> end> en!
d> end>> def method_missing(*args)> if @@controller>
@@controller.send(*args)> else> raise NoMethodError,
“undefined method #{args[0]} for #{self.class}”> end> end>> def
render(*args)> @performed = true>
@@controller.render_to_string(*args)> end>> def performed?>
@performed || false> end>> def configuration_wrapper>
with_include_path(self.class.view_path) do> configure>
render :partial => “configure”, :locals => {sidebar => self} unless
peformed?> end> end>> def index>
with_include_path(self.class.view_path) do> content> render
:partial => “content”, :locals => {sidebar => self} unless peformed?>
end> end> end>> Lots of stuff missing, obviously, but the basic goal
is to turn> the Sidebar parent class into something that feels like a
controller> to someone writing one, but which can be called with a
helper without> having to go through the rather heavyweight process of
renderin!
g a> component.>> Also, I want to be able unify the current Sidebar and>
SidebarController classes in such a way that a Sidebar can be>
serialized to YAML and stored on the blog object, and in a>
:staged_sidebars key in the flash.>> Thoughts?>> --> Piers C.
removed_email_address@domain.invalid> http://www.bofh.org.uk/>
_______________________________________________> Typo-list mailing list>
removed_email_address@domain.invalid>
http://rubyforge.org/mailman/listinfo/typo-list>


#3

“Scott L.” removed_email_address@domain.invalid writes:

This looks pretty reasonable, at least in principal. Care to
providean example of what one of the existing sidebars would look
like, andhow the sidebar views fit into the picture?

Okay, here’s how I hope to make the amazon controller work:

Given a basedir of RAILS_ROOT/vendor/plugins/pluggable_controllers/ we
would have:

lib/amazon_sidebar.rb
class AmazonSidebar < PluggableSidebar

self.display_name defaults to self.short_name.ucfirst, so no need

to implement it here because short_name defaults to ‘amazon’

def self.description
“Adds sidebar links to any amazon books linked in the body of the
page”
end

config_accessor defines an attr accessor with a default.

Could possibly have it take enough information that the nice form

helpers that rails provides can build a config form automagically,

but that’s for later

config_accessor :associate_id, :default => ‘justasummary=20’
config_accessor :maxlinks, :default => 4
config_accessor :title, :default => ‘Cited books’

default initializer works like the standard ActiveRecord::Base

initializer, so the admin controller can do things like:

sidebar_class_for[0].new(params[actives][0])

self.default_config – no need to implement, we just

AmazonSidebar.new will set the correct defaults.

attr_accessor :asins

def content
self.asins = params[:contents].to_a.inject([]) do |list, item|
list | item.whiteboard[:asins].to_a
end.compact[0, self.maxlinks]
if asins.empty?
render :text => ‘’
end
end

def configure
end
end

views/amazon/_content.rhtml # possibly content.rhtml
<% unless sidebar.asins.blank? -%>

<%=h sidebar.title %>

<%= render :partial => 'link', :collection => sidebar.asins %>
<% end -%>

views/amazon/_link.rhtml


#4

“Scott L.” removed_email_address@domain.invalid writes:

I’d really, really like to find a way to keep the sidebar code and views
bundled together in the same directory structure. From what I can see here,
you’re breaking the two apart as a sort of natural consequence of dropping
components. Can we please find a way to stick them back together?

Ah… now I was deliberately trying to reflect the same structure as
the rest of rails; there’s nothing to stop us having a structure like:

vendor/plugins/pluggable_sidebars/sidebars/amazon:
amazon_sidebar.rb
_content.rhtml
_configure.rhtml

ie, just have 'em sat side by side. It’s all in how you implement
‘with_include_path’

Hmm… I think this might be the way to go, that way we can sling
extra sidebars around as simple tarballs that can go pretty much
anywhere in the include path. I can imagine a day when complex
sidebars get their own gem installation and you either include them
with environment.rb or do

./script/generate sidebar foo

which copies the appropriate files from the gem directory and dumps
'em in your vendor/plugins/pluggable_sidebars/sidebars directory where
they’ll get picked up by init.rb

Of course, YAGNI applies, so I’ll not actually implement that until
someone demonstrates a need for it, but it does give us a potential
route to letting people distribute sidebars rather neatly.

Another possible layout for the sidebar’s directory gos something like
this:

amazon/amazon_sidebar.rb
/views/_content.rhtml
_configure.rhtml
/tests/test_amazon.rb

Especially handy if we can write a test_sidebars task that will run
those
tests.

In other words, it’s all up in the air, I haven’t implemented anything
yet, so now’s a good time to think about what the API is going to be
like.


#5

I’d really, really like to find a way to keep the sidebar code and
views
bundled together in the same directory structure. From what I can see
here,
you’re breaking the two apart as a sort of natural consequence of
dropping
components. Can we please find a way to stick them back together?

Scott


#6

I’m trying to migrate a user’s database from 2.6.0 to svn trunk, but
rake migrate (with full trace) gives the following error:

[phil@pepe:~/websites/typo-svn]$ rake --trace migrate
(in /home/phil/websites/typo-svn)
** Invoke migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute migrate
Merging Comments into Contents table
rake aborted!
undefined method title' for #<Bare21Comment:0x8e49724> /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/base.rb:1501:inmethod_missing’
./db/migrate//21_superclass_comments.rb:30:in up' ./db/migrate//21_superclass_comments.rb:26:inup’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/connection_adapters/abstract/database_statements.rb:51:in
transaction' /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/transactions.rb:91:intransaction’
./db/migrate//21_superclass_comments.rb:16:in up' /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:228:inmigrate’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:223:in
migrate' /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:190:inup’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:181:in
migrate' /usr/local/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/tasks/databases.rake:3 /usr/local/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:inexecute’
/usr/local/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:in
execute' /usr/local/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:180:ininvoke’
/usr/local/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:in run' /usr/local/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:inrun’
/usr/local/lib/ruby/gems/1.8/gems/rake-0.6.2/bin/rake:7
/usr/local/bin/rake:18
[phil@pepe:~/websites/typo-svn]$

I have a current Typo-svn running fine (http://fak3r.com) but that one
I’ve migrated as I’ve went along, so I never had to do a big jump like
this one. What should I look at first here?

Thanks

P

http://fak3r.com - you dont have to kick it


#7

Ugh. The problem is that the schemas from before 2.5 weren’t all the
same–some databases had fields that others didn’t. One of those is the
‘title’ field in comments. The original migrations were very careful
not to
depend on any of the questionable fields; it looks like the bare
migration
patch missed one.

I’m away from my SVN tree at the moment, I’ll fix this later today if no
one
else gets to it first.

Scott