From: Trans Date: 2008-04-01T08:34:01+09:00 Subject: Re: Suggest alternatives for Facets paramix? On Mar 31, 6:27 pm, "Jacob Burkhart" wrote: > I Can't seem to find any documentation or explanation as to why paramix has > been forcibly deprecated from facets:http://facets.rubyforge.org/doc/changes.html > > And apparently that lack of documentation means not too many other people > were making use of this cool tool. > > You see a similar technique used a lot in rails. For example, you'll add > the make_resourceful plugin and now all of your controller have the class > method make_resourceful. (And that takes some arguments) And when you call > it ends up including some module from the plugin that adds things to your > controller. great. > > But all of that takes a fair amount of up-front class_eval to add the > make_resourceful class method to everything. > > For simple add-ons I like to use paramix. > > For example, I have a simple module called SqlSearch, and I do > > include SqlSearch, :on => ['name', 'content'] > > paramix gives me access to those hash parameters in my self.included(base) > call in the module. So much simpler and cleaner than declaring class method > everywhere, and there's a clear and definite association here. You KNOW to > look for a SqlSearch module to find out what's going on I could instead > have defined the sql_search class method on ActiveRecord::Base... but then > I have to have require 'sql_search', I can't just have the const_missing > SqlSearch trigger the load needed.... messiness? > > Anybody get what I'm talking about? Why get rid of such a useful thing? > What's a good alternative? > > I debate making my own such thing, something like: > > include_mod SqlSearch, :on => ['name', 'content'] > > and then the callback is self.mod_included(base)... feels hackity > > Any thoughts? Hi Jacob, It was a bit premature of me to remove it. My apologies. I encountered some conflicts between it and other libs and had to reconsider it. The idea is great, no doubt. Unfortunately the implementation was invasive --it overrode #include and #extend. Considering it further I felt it would be better to deprecate it rather then continue to promote a non- robust lib; and I've already started on a new version. I'm hoping to manage a highly robust implementation with much the same interface, except using captialize methods rather than overriding #include. Eg. class X include PMix(:parm=>"foo") end I worked on it last night, but it's a tough nut. If you (or anyone else) is interested in implementing this please take a whack. Hopefully I can get it into next Facets release. (2.4.1 in a week or so). In the mean time I've include a copy of the old version below if you need a (copy and paste) fix asap. T. ---- Here's the old deprecated version of paramix.rb ---- # TITLE: # # Parametric Mixins # # SUMMARY: # # Parametric Mixins provides parameters for mixin modules. # # COPYRIGHT: # # Copyright (c) 2005 Thomas Sawyer, George Moschovitis # # LICENSE: # # Ruby License # # This module is free software. You may use, modify, and/or redistribute this # software under the same terms as Ruby. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # # AUTHORS: # # - Thomas Sawyer # - George Moschovitis require 'facets/module/name' # for basename # = Parametric Mixins # # Parametric Mixins provides parameters for mixin modules. # Module parameters can be set at the time of inclusion or extension, # then accessed via an instance method of the same name as the included # module. # # == Synopsis # # module Mixin # def hello # puts "Hello from #{Mixin(:name)}" # end # end # # class MyClass # include Mixin, :name => 'Ruby' # end # # m = MyClass.new # m.hello -> 'Hello from Ruby' # # You can view the full set of parameters via the #mixin_parameters # class method, which returns a hash keyed on the included modules. # # MyClass.mixin_parameters #=> {Mixin=>{:name=>'Ruby'}} # MyClass.mixin_parameters[Mixin] #=> {:name=>'Ruby'} # # To create _dynamic mixins_ you can use the #included callback # method along with mixin_parameters method like so: # # module Mixin # def self.included( base ) # parms = base.mixin_parameters[self] # base.class_eval { # def hello # puts "Hello from #{parms(:name)}" # end # } # end # end # # More conveniently a new callback has been added, #included_with_parameters, # which passes in the parameters in addition to the base class/module. # # module Mixin # def self.included_with_parameters( base, parms ) # base.class_eval { # def hello # puts "Hello from #{parms(:name)}" # end # } # end # end # # We would prefer to have passed the parameters through the #included callback # method itself, but implementation of such a feature is much more complicated. # If a reasonable solution presents itself in the future however, we will fix. class Module # Store for module parameters. This is local per module # and indexed on module/class included-into. def mixin_parameters ; @mixin_parameters ||= {} ; end alias_method :include_without_parameters, :include def include(*args) params = args.last.is_a?(Hash) ? args.pop : {} args.each do |mod| mixin_parameters[mod] = params if mod.basename define_method( mod.basename ) do |key| if params.key?(key) params[key] else super if defined?( super ) end end end end r = include_without_parameters(*args) for mod in args if mod.respond_to?(:included_with_parameters) mod.included_with_parameters( self, params ) end end r end alias_method :extend_without_parameters, :extend def extend(*args) params = args.last.is_a?(Hash) ? args.pop : {} args.each do |mod| (class << self; self; end).class_eval do mixin_parameters[mod] = params if mod.basename define_method( mod.basename ) do |key| if params.key?(key) params[key] else super if defined?( super ) end end end end end r = extend_without_parameters(*args) for mod in args if mod.method_defined?(:extended_with_parameters) mod.extended_with_parameters( self, params ) end end r end end