Forum: Typo Sidebars

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.
0196ff65610046d2f8ba58bc4a45f144?d=identicon&s=25 Piers Cawley (Guest)
on 2006-03-20 18:01
(Received via mailing list)
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?
Dc3f3775a7d03ba1be8958aaee881d6b?d=identicon&s=25 Scott Laird (Guest)
on 2006-03-20 18:10
(Received via mailing list)
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 Cawley <pdcawley@bofh.org.uk> 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 Cawley
<pdcawley@bofh.org.uk>> http://www.bofh.org.uk/>
_______________________________________________> Typo-list mailing list>
Typo-list@rubyforge.org>
http://rubyforge.org/mailman/listinfo/typo-list>
0196ff65610046d2f8ba58bc4a45f144?d=identicon&s=25 Piers Cawley (Guest)
on 2006-03-20 19:22
(Received via mailing list)
"Scott Laird" <scott@sigkill.org> 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? -%>
<h3><%=h sidebar.title %></h3>
<div id='amazon_links'><%=
  render :partial => 'link', :collection => sidebar.asins %>
</div>
<% end -%>

views/amazon/_link.rhtml
<iframe src=...&asins=<%= asin %>...&t=<%= sidebar.assoc_id %>


views/amazon/_configure.rhtml
<label>Associate ID</label>
<%= text_field_tag "sidebars[][associate_id]", sidebar.associate_id
%><br />
<label>Max links</label>
<%= text_field_tag "sidebars[][maxlinks]", sidebar.maxlinks %><br />
<label>Sidebar Title</label>
<%= text_field_tag "sidebars[][title]", sidebar.maxlinks %>

The thinking here is admin/sidebar has a single form, ordering gets
sorted out by drag'n'drop without having to keep sending stuff back to
the server, 'publish changes' then just submits a single form. Also,
the superclass's configure_wrapper needs to add a "<hidden
id='sidebars[][class]' value='AmazonSidebar'/>" as part of its pseudo
layout.

Even if we can't make admin/sidebar into a single form view, the
_configure partial really doesn't need to set its own form up...

Implementing this won't necessarily be straightforward, and it won't
happen overnight, but there's *far* too much DRY violation going on
with sidebars at the moment. Things like layouts to set the config
form up can be implemented independently of any larger changes.

--
Piers Cawley <pdcawley@bofh.org.uk>
Ãhttp://www.bofh.org.uk/
Dc3f3775a7d03ba1be8958aaee881d6b?d=identicon&s=25 Scott Laird (Guest)
on 2006-03-20 20:17
(Received via mailing list)
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
0196ff65610046d2f8ba58bc4a45f144?d=identicon&s=25 Piers Cawley (Guest)
on 2006-03-21 01:33
(Received via mailing list)
"Scott Laird" <scott@sigkill.org> 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.
6fd1d0d0316a3ee723703b9520fe1c38?d=identicon&s=25 phil (Guest)
on 2006-03-21 21:44
(Received via mailing list)
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:in
`method_missing'
./db/migrate//21_superclass_comments.rb:30:in `up'
./db/migrate//21_superclass_comments.rb:26:in `up'
/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:in
`transaction'
./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:in
`migrate'
/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:in
`up'
/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:in
`execute'
/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:in `invoke'
/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:in `run'
/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
Dc3f3775a7d03ba1be8958aaee881d6b?d=identicon&s=25 Scott Laird (Guest)
on 2006-03-21 21:54
(Received via mailing list)
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
This topic is locked and can not be replied to.