# Suggest alternatives for Facets paramix?

**URL:** <https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486>\
**Category:** Ruby\
**Created:** [April 1, 2008, 12:27am UTC](https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486 "2008-04-01T00:27:42Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![igotimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/85f322/32.png) [@igotimac](https://www.ruby-forum.com/u/igotimac)\
**Post date:** [April 1, 2008, 12:27am UTC](https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486/1 "2008-04-01T00:27:42Z")

</div>

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](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?

Jacob

---

<div class="post-metadata">

**Author:** ![igotimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/85f322/32.png) [@igotimac](https://www.ruby-forum.com/u/igotimac)\
**Post date:** [April 1, 2008, 1:34am UTC](https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486/2 "2008-04-01T01:34:40Z")

</div>

On Mar 31, 6:27 pm, “Jacob B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> controller. great.  
> paramix gives me access to those hash parameters in my self.included(base)  
> 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 S., George M.

# 

# 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 S.

# - George M.

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

---

<div class="post-metadata">

**Author:** ![igotimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/85f322/32.png) [@igotimac](https://www.ruby-forum.com/u/igotimac)\
**Post date:** [April 1, 2008, 3:26am UTC](https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486/3 "2008-04-01T03:26:06Z")

</div>

On Mar 31, 2008, at 4:27 PM, Jacob B. wrote:

> But all of that takes a fair amount of up-front class\_eval to add the  
> make\_resourceful class method to everything.

??

module SqlSearch

def SqlSearch.bless other, options = {}  
stuff\_with options  
other.send :include, self  
end

end

class Module  
def sqlsearch options = {}  
SqlSearch.bless self, options  
end  
end

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![igotimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/85f322/32.png) [@igotimac](https://www.ruby-forum.com/u/igotimac)\
**Post date:** [April 7, 2008, 8:51pm UTC](https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486/4 "2008-04-07T20:51:39Z")

</div>

Hey Tran,

Thanks for re-adding Paramix to facets!  
I seem to be getting a conflict with another thing called Delegator in  
class\_eval.

So this seems to work better:

def self.append\_features(base)  
base.modspace.module\_eval %{  
def #{base.basename.to\_s}(parameters, &block)  
Paramix::Delegator.new(#{base}, parameters, &block)  
end  
}  
end

and I also had to change the order of things in append\_features so that  
the  
include is last, because I want to be able to reference mixin\_parameters  
in  
self.included:

```
def append_features(base)
  base.mixin_parameters[delegate_module] = parameters

  base.module_eval do
    define_method(:mixin_parameters) do
      base.mixin_parameters
    end
  end

  base. __send__ (:include, delegate_module)

  base.module_eval(&@base_block) if base_block
end

```

Can we get these changes in the next version of facets?

thanks,  
Jacob

On Mon, Mar 31, 2008 at 9:25 PM, ara.t.howard [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![igotimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/85f322/32.png) [@igotimac](https://www.ruby-forum.com/u/igotimac)\
**Post date:** [April 1, 2008, 2:28am UTC](https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486/5 "2008-04-01T02:28:00Z")

</div>

On Mar 31, 7:34 pm, Trans [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I worked on it last night, but it’s a tough nut.

Huh… it may have just a fallen into place. What do you think of:

require ‘facets/module/basename’  
require ‘facets/module/modspace’

module Paramix # or PatrametricMixin ?

```
def self.append_features(base)
  base.modspace.module_eval %{
    def #{base.basename.to_s}(parameters, &block)
      Delegator.new(#{base}, parameters, &block)
    end
  }
end

# It you want to define the module method by hand. You
# can use Parmix.new instead of Parmix::Delegator.new.

def self.new(delegate_module, parameters={}, &base_block)
  Delegator.new(delegate_module, parameters, &base_block)
end

#

class Delegator < Module

  attr :delegate_module
  attr :parameters
  attr :base_block

  def initialize(delegate_module, parameters={}, &base_block)
    @delegate_module = delegate_module
    @parameters = parameters
    @base_block = base_block
  end

  def append_features(base)
    base. __send__ (:include, delegate_module)
    base.parametric_options[delegate_module] = parameters
    base.module_eval do
      define_method(:parametric_options) do
        base.parametric_options
      end
    end
    base.module_eval(&@base_block) if base_block
  end

  def [](name)
    @parameters[name]
  end

end

```

end

class Module

```
# Store for parametric mixin parameters.
#
# Returns a hash, the keys of which are the parametric mixin

```

module  
# and the values are the parameters associacted with this module/  
class.  
#  
# class C  
# include P(:x=\>1)  
# end  
#  
# C.parametric\_options[P] #=\> {:x=\>1}  
#  
def parametric\_options  
@parametric\_options ||= {}  
end

end

# Try it out

if **FILE** == $0

```
module O
  include Paramix

  def x
    parametric_options[O][:x]
  end
end

# If doing it by hand instead of using include Paramix.
#def O(options)
# Paramix.new(O, options)
#end

class X
  include O(:x=>1)
end

x = X.new
p x.x

p X.ancestors

```

end

T.

---

<div class="post-metadata">

**Author:** ![igotimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/85f322/32.png) [@igotimac](https://www.ruby-forum.com/u/igotimac)\
**Post date:** [April 7, 2008, 9:45pm UTC](https://www.ruby-forum.com/t/suggest-alternatives-for-facets-paramix/133486/6 "2008-04-07T21:45:25Z")

</div>

On Apr 7, 2:50 pm, “Jacob B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> def #{base.basename.to_s}(parameters, &block)
> Paramix::Delegator.new(#{base}, parameters, &block)
> end
> }
> 
> ```
> 
> end

Ah, good catch, I will fix.

> ```
> end
> end
> 
> base. __send__ (:include, delegate_module)
> 
> base.module_eval(&@base_block) if base_block
> end
> 
> ```

Yep. I ran into that too and have already made that change.

> Can we get these changes in the next version of facets?

Yep. And I will be releasing 2.4.2 in a matter of days.

Thanks Jacob,  
T.
