Forum: Rails Engines development Engines as Mephisto Plugins

402602a60e500e85f2f5dc1ff3648ecb?d=identicon&s=25 Sven Fuchs (Guest)
on 2008-01-31 19:37
(Received via mailing list)
Hi James,

like I mentioned a while back Rick asked me regarding Engines as a
basis for Mephisto plugins.

Mephisto comes with its own implementation of plugins that share
controllers, views, routes, schemas (migrations) etc. as well as some
config stuff. Rick asked me to look into using Engines instead and he
suggested this as a feature for Mephisto 1.0

I believe Mephisto could benefit from using all the major Engines
functionality. But there are some features that aren't currently
supported by Engines and I'd like to discuss to what extend these
could possibly be added to Engines instead of having them in Mephisto.

These are:

1. About info: we've omitted about.yml from Engines for Rails 2.0
recently and you already mentioned that this could possibly be
restored. On the one hand Rick said that he doesn't really care about
this, but on the other hand people actually seem to use this
information (e.g. the plugin authors website is displayed in the
Mephisto admin interface and people use this link to lookup
information about the plugin).

2. Configuration info: Mephisto provides means to configure a plugin
through an option directive. E.g. in a feedback form plugin there
might be an option to configure the confirmation message that's
displayed when the feedback for has been submitted (bad example but
you get the idea). The option and its default value is defined in the
plugin, it's current value is pulled from the database if a record is
present (otherwise the default value is used). Mephisto could switch
from using ActiveRecord as a storage for plugin configuration data to
something else, e.g. another YAML file, Ruby code or whatever.

A possible solution for both requirements that I personally like could
be:

With Rails 2.0 plugins we can do all the about and configuration stuff
from within init.rb because this file is evaluated within the plugin's
scope. Because init.rb is overwritten when the plugin get's
reinstalled (so the config customization would get lost) we could look
for a (e.g.) config.rb file and evaluate it alongside with the plugin
init.rb file if it's present. This config.rb file would allow to
define something like:

author 'James'
version '1.0'
website 'http://...'

option :feedback_confirm_msg, 'Thanks!'
option :foo, 'bar'

What do you think?


--
sven fuchs      svenfuchs@artweb-design.de
artweb design    http://www.artweb-design.de
grünberger 65    + 49 (0) 30 - 47 98 69 96 (phone)
d-10245 berlin    + 49 (0) 171 - 35 20 38 4 (mobile)
00e3a96684ab390a350b0271e98741d3?d=identicon&s=25 Nshbrown Nshbrown (nshb)
on 2008-02-01 10:15
(Received via mailing list)
That has to go in the wall of fame. A milestone as it will. A core
commiter
wanting Engines as a feature of their own app infrastructure? I love it
:)

As far as feature #2 goes, it would need to be outside of the plugin
code/checkout. The best feature of an engine is the ability to override
whatever you want through a linear stack track. A key concept of an
engine
is that the code can be used with an external and have whatever changes
you
personally need overriden in your own app such as /config/initializers/
and
such. It would be sad to see this feature sacrificed due to
implementation.

I like the about.yml files. I still use them in all my plugins. They
could
surely be used as you mentioned, and probably even more uses to come out
of
it. Doesn't hurt anything by being there? Only helps as far as I see it.
05d703f649ef1d07e78d7b479fb4c4ac?d=identicon&s=25 James Adam (Guest)
on 2008-02-01 12:41
(Received via mailing list)
On 31/01/2008, Sven Fuchs <svenfuchs@artweb-design.de> wrote:
> like I mentioned a while back Rick asked me regarding Engines as a
> basis for Mephisto plugins.

It's great news that Rick has found the engines plugin useful.

> 1. About info: we've omitted about.yml from Engines for Rails 2.0
> recently and you already mentioned that this could possibly be
> restored. On the one hand Rick said that he doesn't really care about
> this, but on the other hand people actually seem to use this
> information (e.g. the plugin authors website is displayed in the
> Mephisto admin interface and people use this link to lookup
> information about the plugin).

Adding the about.yml information is something we can definitely
re-include. Originally, we would simply load about.yml into a Hash
which can be accessed from the plugin instance:

about.yml
---
:author: James
:url: http://interblah.net
:version: 2.0.1
:description: Blah blah

becomes

plugin = Engines.plugins[:my_plugin]
plugin.about
# ==> { :version => "2.0.1", :author => "James", :url =>
"http://interblah.net" ... }

This is relatively easy to support - in fact, is there any reason why
this couldn't be implemented as a patch to Rails core itself?
Regardless, my only suggestion would be that the plugins mechanism is
not particular about the specific keys in about.yml - anything can be
present. If Mephisto expects a particular set of keys to be present,
that should be enforced in the application itself.

> A possible solution for both requirements that I personally like could
> author 'James'
> version '1.0'
> website 'http://...'
>
> option :feedback_confirm_msg, 'Thanks!'
> option :foo, 'bar'
>
> What do you think?
>

So the config.rb would be stored somewhere outside of /vendor/plugins?
I'm not sure this is a particularly good fit for the engines plugin
itself - it seems better that Mephisto makes some class available to
its plugins to support this. Something like

  create_table :plugin_configs do |t|
    t.string :plugin
    t.string :key
    t.string :value
  end

So in a table we have tuples of plugin name, key and value. Next lets
set up a base class that can access this table

mephisto/lib/plugin_config.rb:
  class PluginConfig < ActiveRecord::Base

    # this lets us set and store default values in subclasses of
PluginConfig
    class_inheritable_hash :defaults
    def self.default(key, value)
      defaults[key.to_s] = value
    end

    # Try and load a stored config tuple - otherwise, return any stored
default
    def self.config[](key)
      stored_value(key) || defaults[key.to_s]
    end

    # Create or overwrite any existing tuple for this plugin
    def self.config[]=(key, value)
      config = stored_config(key)
      if config
        config.update_attribute(:value, value)
      else
        create(:plugin => self.name, :key => key, :value => value)
      end
    end

    def self.stored_value(key)
      stored_config = find_by_key_and_plugin(key, self.name)
      stored_config ? stored_config.value : nil
    end

    # I imagine Mephisto itself will want to load all of the stored
config tuples
    # for a particular plugin
    def all_stored_configuration_options
      find_all_by_plugin(self.name)
    end

    # Returns all configuration options declared by the subclass,
including any
    # defaults. Probably useful in the Mephisto admin interface too.
    def all_configuration_options
      stored_configs = all_stored_configuration_options
      stored_configs_and_defaults = defaults.dup
      stored_configs.each do |config|
        stored_configs_and_defaults[config.key] = config.value
      end
      stored_configs_and_defaults
    end
  end


vendor/plugins/my_plugin/init.rb

  class MyPlugin < PluginConfig
    default :admin_email, "me@myapp.com"
  end

vendor/plugins/my_plugin/lib/some_thing.rb

  class SomeThing
    # ...
    def send_email(body)
      send_email_to(MyPlugin.config[:admin_email], body)
    end
    # ...
  end


.... anyway. That's just off the top of my head, but the point is that
I'm not sure that it's anything that the engines plugin should really
handle explicitly. Any thoughts?
05d703f649ef1d07e78d7b479fb4c4ac?d=identicon&s=25 James Adam (Guest)
on 2008-02-01 12:46
(Received via mailing list)
On 01/02/2008, Nathaniel Brown <nshb@inimit.com> wrote:
> As far as feature #2 goes, it would need to be outside of the plugin
> code/checkout. The best feature of an engine is the ability to override
> whatever you want through a linear stack track. A key concept of an engine
> is that the code can be used with an external and have whatever changes you
> personally need overriden in your own app such as /config/initializers/ and
> such. It would be sad to see this feature sacrificed due to implementation.

I'm not sure what you mean here - I think you're suggesting that
configuration should set in the application codebase, rather than
within the plugin, right? Which I generally agree with, although I
think in the case of Mephisto, which almost certainly wants to provide
a web interface for setting this, setting that in config/initializers
is going to be tricky at best...
402602a60e500e85f2f5dc1ff3648ecb?d=identicon&s=25 Sven Fuchs (Guest)
on 2008-02-01 15:17
(Received via mailing list)
Am 01.02.2008 um 12:41 schrieb James Adam:
> Adding the about.yml information is something we can definitely
> re-include.

Cool!

> becomes
>
> plugin = Engines.plugins[:my_plugin]
> plugin.about
> # ==> { :version => "2.0.1", :author => "James", :url =>
> "http://interblah.net" ... }

That's a reasonable approach, IMO.

> This is relatively easy to support - in fact, is there any reason why
> this couldn't be implemented as a patch to Rails core itself?

I can't see any.

> Regardless, my only suggestion would be that the plugins mechanism is
> not particular about the specific keys in about.yml - anything can be
> present.

I agree.

> So the config.rb would be stored somewhere outside of /vendor/plugins?
> I'm not sure this is a particularly good fit for the engines plugin
> itself -

I imagined it to be something a long the lines of Rails' config/
database.yml which provides application specific config data. Likewise
a [plugin_root]/config.yml could define plugin specific configs. The
plugin could ship with config.example.yml with defaults and comments.

> it seems better that Mephisto makes some class available to
> its plugins to support this. Something like
>
>  create_table :plugin_configs do |t|
>    t.string :plugin
>    t.string :key
>    t.string :value
>  end
[...]
> .... anyway. That's just off the top of my head, but the point is that
> I'm not sure that it's anything that the engines plugin should really
> handle explicitly. Any thoughts?

This actually is how Mephisto works today. :))

Personally I feel that a) having a standard way of customizing
configuration is a need that would fit into Engines perfectly, but b)
ActiveRecord as a storage engine for this need feels a bit too
heavyweight for being used in Engines.

How about:

#plugin.rb - if present, defines some arbitrary properties and options
author 'James'
website '...'
option :foo, 'bar' # 'bar' is the default value

#config.rb - if present, defines customized option values
foo 'baz'

Hmm, actually I myself am not fully convinced of this. But you get the
idea. I'd like to see a way of providing about info, defining options
w/ default and customized option values in a simple manner.

--
sven fuchs      svenfuchs@artweb-design.de
artweb design    http://www.artweb-design.de
grünberger 65    + 49 (0) 30 - 47 98 69 96 (phone)
d-10245 berlin    + 49 (0) 171 - 35 20 38 4 (mobile)
402602a60e500e85f2f5dc1ff3648ecb?d=identicon&s=25 Sven Fuchs (Guest)
on 2008-02-01 15:18
(Received via mailing list)
Am 01.02.2008 um 10:14 schrieb Nathaniel Brown:
> That has to go in the wall of fame. A milestone as it will. A core
> commiter wanting Engines as a feature of their own app
> infrastructure? I love it :)

It's certainly great feedback :)

> As far as feature #2 goes, it would need to be outside of the plugin
> code/checkout. The best feature of an engine is the ability to
> override whatever you want through a linear stack track. A key
> concept of an engine is that the code can be used with an external
> and have whatever changes you personally need overriden in your own
> app such as /config/initializers/ and such. It would be sad to see
> this feature sacrificed due to implementation.

I'd see this like config/database[.example].yml which you check out
when you check out an application (like Mephisto), rename and
customize it.

> I like the about.yml files. I still use them in all my plugins. They
> could surely be used as you mentioned, and probably even more uses
> to come out of it. Doesn't hurt anything by being there? Only helps
> as far as I see it.

Me2 :)



> suggested this as a feature for Mephisto 1.0
> restored. On the one hand Rick said that he doesn't really care about
> plugin, it's current value is pulled from the database if a record is
> reinstalled (so the config customization would get lost) we could look
>
>
> Engine-Developers mailing list
> Engine-Developers@lists.rails-engines.org
> http://lists.rails-engines.org/listinfo.cgi/engine...

--
sven fuchs      svenfuchs@artweb-design.de
artweb design    http://www.artweb-design.de
grünberger 65    + 49 (0) 30 - 47 98 69 96 (phone)
d-10245 berlin    + 49 (0) 171 - 35 20 38 4 (mobile)
05d703f649ef1d07e78d7b479fb4c4ac?d=identicon&s=25 James Adam (Guest)
on 2008-02-01 20:58
(Received via mailing list)
On 01/02/2008, Sven Fuchs <svenfuchs@artweb-design.de> wrote:
> Am 01.02.2008 um 12:41 schrieb James Adam:
> > Adding the about.yml information is something we can definitely
> > re-include.
>
> Cool!
>
> > This is relatively easy to support - in fact, is there any reason why
> > this couldn't be implemented as a patch to Rails core itself?
>
> I can't see any.

http://dev.rubyonrails.org/ticket/10979

Go wild with your verification :)
402602a60e500e85f2f5dc1ff3648ecb?d=identicon&s=25 Sven Fuchs (Guest)
on 2008-02-02 11:37
(Received via mailing list)
Gone wild :)


Am 01.02.2008 um 20:57 schrieb James Adam:

>>
> Engine-Developers mailing list
> Engine-Developers@lists.rails-engines.org
> http://lists.rails-engines.org/listinfo.cgi/engine...

--
sven fuchs      svenfuchs@artweb-design.de
artweb design    http://www.artweb-design.de
grünberger 65    + 49 (0) 30 - 47 98 69 96 (phone)
d-10245 berlin    + 49 (0) 171 - 35 20 38 4 (mobile)
This topic is locked and can not be replied to.