# Shared-0.4.2

**URL:** <https://www.ruby-forum.com/t/shared-0-4-2/152918>\
**Category:** Ruby\
**Created:** [November 9, 2008, 8:43pm UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918 "2008-11-09T20:43:44Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 9, 2008, 8:43pm UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/1 "2008-11-09T20:43:44Z")

</div>

NAME  
shared.rb

DESCRIPTION  
super simple super power sharing of instance and class level code

INSTALL  
gem install shared

URIS  
[http://rubyforge.org/projects/codeforpeople](http://rubyforge.org/projects/codeforpeople)  
[http://codeforpeople.com/lib/ruby/](http://codeforpeople.com/lib/ruby/)

HISTORY  
0.4.2  
initial version

SAMPLES

\<========\< samples/a.rb \>========\>

~ \> cat samples/a.rb

```
 # shared.rb is a very simple and very powerful method of sharing

```

code between  
# classes.  
#  
require ‘shared’

```
   shared(:code) do
     def classname() self.class.name end
   end

   class Foo
     include shared(:code)
   end

   class Bar
     include shared(:code)
   end

   p Foo.new.classname #=> "Foo"

   p Bar.new.classname #=> "Bar"

```

~ \> ruby samples/a.rb

```
 "Foo"
 "Bar"

```

\<========\< samples/b.rb \>========\>

~ \> cat samples/b.rb

```
 # shared.rb allows natural declaration of both instance and class-

```

level  
# methods - it’s more than simple module inclusion  
#

```
   require 'shared'

   shared('methods') do
     def self.class_method() 40 end

     def instance_method() 2 end
   end

   class C
     include shared('methods')
   end

   p(C.class_method + C.new.instance_method) #=> 42

```

~ \> ruby samples/b.rb

```
 42

```

\<========\< samples/c.rb \>========\>

~ \> cat samples/c.rb

```
 # shared.rb works equally well with individual objects in

```

addition to the  
# normal class level usage  
#

```
   require 'shared'

   shared(:meta_tools) do
     def singleton_class &block
       singleton_class =
         class << self
           self
         end
       block ? singleton_class.module_eval(&block) : singleton_class
     end
   end

   a = %w( a b c )

   a.extend shared(:meta_tools)

   a.singleton_class do
     def to_range() first .. last end
   end

   p a.to_range #=> "a".."c"

```

~ \> ruby samples/c.rb

```
 "a".."c"

```

\<========\< samples/d.rb \>========\>

~ \> cat samples/d.rb

```
 # an example use-case for shared.rb is sharing code bewteen

```

classes that  
# require both class level and instance level behaviour to be  
shared  
#

```
   require 'shared'

   shared(:acts_as_named) do
     validates_precence_of :name

     def to_html() "<blink> #{ name } </blink>" end
   end

   class Model
     def Model.validates_precence_of(*a) end

     def name() 'zaphod' end

     include shared(:acts_as_named)
   end

   p Model.new.to_html #=> "<blink> zaphod </blink>"

```

~ \> ruby samples/d.rb

```
 "<blink> zaphod </blink>"

```

\<========\< samples/e.rb \>========\>

~ \> cat samples/e.rb

```
 # it's important to note that the shared code is injected into

```

the reciever  
# fresh on each call and, in that way, the effect is rather macro  
like  
#

```
   require 'shared'

   share(:instance_tracker) do
     const_set :Instances, []

     def self.instances() const_get :Instances end

     def self.new *a, &b
       obj = super
     ensure
       instances << obj
     end
   end

   class Foo
     include shared(:instance_tracker)
   end

   class Bar
     include shared(:instance_tracker)
   end

   2.times{ Foo.new }
   40.times{ Bar.new }

   p(Foo.instances.size + Bar.instances.size)

```

~ \> ruby samples/e.rb

```
 42

```

enjoy.

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

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 9, 2008, 9:49pm UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/2 "2008-11-09T21:49:41Z")

</div>

ara howard wrote:

> NAME  
> shared.rb  
> …  
> enjoy.

shared and enjoyed 😉

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 9, 2008, 10:03pm UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/3 "2008-11-09T22:03:04Z")

</div>

Ara Howard wrote:

> NAME  
> shared.rb
> 
> DESCRIPTION  
> super simple super power sharing of instance and class level code

Hi Ara

Thanks a lot for sharing another of your fine libraries 🙂  
May I ask why I would introduce the dependency ‘shared’ instead of using  
rubys native code sharing facility that is inheritance and (IMO more  
powerful) modules? Where do you see the striking advantages of shared?

Regards  
Stefan

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 9, 2008, 10:35pm UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/4 "2008-11-09T22:35:25Z")

</div>

On Nov 9, 2008, at 2:00 PM, Stefan R. wrote:

> Hi Ara
> 
> Thanks a lot for sharing another of your fine libraries 🙂  
> May I ask why I would introduce the dependency ‘shared’ instead of  
> using  
> rubys native code sharing facility that is inheritance and (IMO more  
> powerful) modules? Where do you see the striking advantages of shared?
> 
> Regards  
> Stefan

well, for starters it _is_ based on modules 😉 the striking  
advantage is, as a for instance, that you can do this in rails

in lib/shared.rb

shared :before\_filters do  
before\_filter :foo  
before\_filter :bar

def foo() end  
def bar() end  
end

in app/controllers/foo\_controller.rb

class Foo \< ApplicationController  
include shared(:before\_filters)  
end

in app/controllers/bar/controller.rb

class Bar \< ApplicationController  
include shared(:before\_filters)  
end

this is absolutely not easily done with modules. shared.rb has all  
the advantages of ruby module sharing _plus_ the simplicity of  
completely POLS class level method sharing.

another example, which is not easily done using modules

in lib/shared.rb

shared :home\_controller do  
before\_filter :must\_have\_user

def index  
render ‘shared/home’  
end

protected  
def must\_have\_user() end  
end

in app/controllers/teacher/home\_controller.rb

class Teacher::HomeController \< ApplicationController  
include shared(:home\_controller)  
end

in app/controllers/student/home\_controller.rb

class Student::HomeController \< ApplicationController  
include shared(:home\_controller)  
end

so, in that example, we can directly setup a public method (index  
action) and protected method, and call a class method. try doing that  
with modules and you’ll see that it’s rather un-natural. the call to  
before\_filter, for instance, cannot simply be wrapped with the normal  
‘ClassMethods’ hack, but must actually be deferred because it only  
_exists_ in the target classes - aka it doesn’t exist in the mixin but  
only exists in the mixxee (controllers) making it a chicken-and-egg  
issue when code sharing is desired.

shared let’s you factor out chunks of code _exactly_ as you would have  
typed them before and then, later, to inject them into classes or  
module or objects _exactly as if you’d entered the code there_

make sense?

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

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 9, 2008, 10:37pm UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/5 "2008-11-09T22:37:11Z")

</div>

On Nov 9, 2008, at 2:00 PM, Stefan R. wrote:

> Hi Ara
> 
> Thanks a lot for sharing another of your fine libraries 🙂  
> May I ask why I would introduce the dependency ‘shared’ instead of  
> using  
> rubys native code sharing facility that is inheritance and (IMO more  
> powerful) modules? Where do you see the striking advantages of shared?
> 
> Regards  
> Stefan

one last thing - shared.rb is only 44 lines of code so i really don’t  
expect you to introduce a dependancy, rather i expect you to steal it  
and drop it into your project’s lib dir and be done with it. it’s  
small enough to simply cut and paste into any existing project as well.

if you want to depend on it, however, the gem makes it easy.

cheers.

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

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 9, 2008, 11:36pm UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/6 "2008-11-09T23:36:04Z")

</div>

Ara Howard wrote:

> shared :before\_filters do  
> before\_filter :foo  
> before\_filter :bar
> 
> def foo() end  
> def bar() end  
> end
> 
> in app/controllers/foo\_controller.rb
> 
> class Foo \< ApplicationController  
> include shared(:before\_filters)  
> end
> 
> in app/controllers/bar/controller.rb
> 
> class Bar \< ApplicationController  
> include shared(:before\_filters)  
> end

module SharedBeforeFilters  
def self.included(by)  
by.before\_filter :foo  
by.before\_filter :bar  
end

def foo(); end  
def bar(); end  
end

in app/controllers/foo\_controller.rb  
class Foo \< ApplicationController  
include SharedBeforeFilters  
end

in app/controllers/bar\_controller.rb  
class Bar \< ApplicationController  
include SharedBeforeFilters  
end

> this is absolutely not easily done with modules.

I don’t see the problem here.

shared.rb has all

> the advantages of ruby module sharing _plus_ the simplicity of  
> completely POLS class level method sharing.
> 
> another example, which is not easily done using modules
> 
> in lib/shared.rb
> 
> shared :home\_controller do  
> before\_filter :must\_have\_user
> 
> def index  
> render ‘shared/home’  
> end
> 
> protected  
> def must\_have\_user() end  
> end
> 
> in app/controllers/teacher/home\_controller.rb
> 
> class Teacher::HomeController \< ApplicationController  
> include shared(:home\_controller)  
> end
> 
> in app/controllers/student/home\_controller.rb
> 
> class Student::HomeController \< ApplicationController  
> include shared(:home\_controller)  
> end
> 
> so, in that example, we can directly setup a public method (index  
> action) and protected method, and call a class method. try doing that  
> with modules and you’ll see that it’s rather un-natural.

module HomeController  
def self.included(by)  
by.before\_filter :must\_have\_user  
end

def index  
render ‘shared/home’  
end

protected  
def must\_have\_user() end  
end

in app/controllers/teacher/home\_controller.rb  
class Teacher::HomeController \< ApplicationController  
include HomeController  
end

in app/controllers/student/home\_controller.rb  
class Student::HomeController \< ApplicationController  
include HomeController  
end

Again, I don’t see the issue. But maybe I miss the obvious or something  
:-/

> make sense?

Not sure yet. But thanks for the explanations!

Regards  
Stefan

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 10, 2008, 12:39am UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/7 "2008-11-10T00:39:51Z")

</div>

Ara Howard wrote:

> On Nov 9, 2008, at 3:33 PM, Stefan R. wrote:
> 
> > Again, I don’t see the issue. But maybe I miss the obvious or  
> > something
> 
> what you are missing is that you are good @ ruby 😉
> 
> seriously though, it really does get messy with class instance vars  
> and especially @@class vars. shared just let’s you forget about it.  
> mostly it’s motivated by me getting sick of writing ‘included’ hooks  
> and ‘class \<\< other’ - that’s it.
> 
> cheers.
> 
> a @ [http://codeforpeople.com/](http://codeforpeople.com/)

Ok. Then one request:  
Add the global methods to Kernel instead of Object (as they are, as I  
understand them, quasi-global methods and not instance methods) and make  
them private (to not disable method\_missing for them).

Regards  
Stefan

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 10, 2008, 12:37am UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/8 "2008-11-10T00:37:51Z")

</div>

On Nov 9, 2008, at 3:33 PM, Stefan R. wrote:

> Again, I don’t see the issue. But maybe I miss the obvious or  
> something

what you are missing is that you are good @ ruby 😉

seriously though, it really does get messy with class instance vars  
and especially @@class vars. shared just let’s you forget about it.  
mostly it’s motivated by me getting sick of writing ‘included’ hooks  
and ‘class \<\< other’ - that’s it.

cheers.

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

---

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [November 10, 2008, 1:43am UTC](https://www.ruby-forum.com/t/shared-0-4-2/152918/9 "2008-11-10T01:43:19Z")

</div>

On Nov 9, 2008, at 4:37 PM, Stefan R. wrote:

> Ok. Then one request:  
> Add the global methods to Kernel instead of Object (as they are, as I  
> understand them, quasi-global methods and not instance methods) and  
> make  
> them private (to not disable method\_missing for them).

both good ideas. done.

HISTORY 0.4.3  
- added version info  
- move methods from Object to Kernel and made them private (thx  
Stefan R.)

just pushed to rubyforge.

cheers.

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