# Ruby, Rails & Inheritance

**URL:** <https://www.ruby-forum.com/t/ruby-rails-inheritance/101973>\
**Category:** Rails\
**Created:** [February 7, 2006, 12:10pm UTC](https://www.ruby-forum.com/t/ruby-rails-inheritance/101973 "2006-02-07T12:10:10Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dim](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ebca7d/32.png) [@dim](https://www.ruby-forum.com/u/dim)\
**Post date:** [February 7, 2006, 12:10pm UTC](https://www.ruby-forum.com/t/ruby-rails-inheritance/101973/1 "2006-02-07T12:10:10Z")

</div>

Hi!

I am looking for a solution for the following problem:

## Some of my models share some attributes and also was in need for some extra features, so I created a class “RecordWithFeatures”:

class RecordWithFeatures \< ActiveRecord::Base  
# @Override  
def self.descends\_from\_active\_record?  
superclass == RecordWithFeatures  
end

```
# @Override

```

def self.class\_name\_of\_active\_record\_descendant(klass)  
…  
end  
…  
end

## class SomeModel \< RecordWithFeatures … end

Ok, everything works fine, but I would also like to pass some  
class-methods to my models as soon as the inherit RecordWithFeatures.

## Example: All models have an attribute “context\_id”, so every model includes these 2 lines

## belongs\_to :context validates\_presence\_of :context

What can I do to add those automatically? If I include them into the  
RecordWithFeatures class, they are valid for RecordWithFeatures only,  
but it’s not RecordWithFeatures, but it’s children, that should belong  
to “context”.

Thanks for all hints  
Dim

---

<div class="post-metadata">

**Author:** ![dim](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ebca7d/32.png) [@dim](https://www.ruby-forum.com/u/dim)\
**Post date:** [February 7, 2006, 12:58pm UTC](https://www.ruby-forum.com/t/ruby-rails-inheritance/101973/2 "2006-02-07T12:58:06Z")

</div>

A nice construct in Ruby for sharing code between classes but without  
the  
messyness of requiring a common ancestor is the mixin pattern. (  
[http://www.rubycentral.com/book/tut\_modules.html](http://www.rubycentral.com/book/tut_modules.html))

## If there are elements that you’d like to share you can make it more clear what is going on via something like the the following. The only thing is I’m not 100% sure it will work with the belongs\_to and validates\_presence\_of

let me know!

module ContextRecord  
belongs\_to :context  
validates\_presences\_of :context

def foo  
# shared method…  
end  
end

class SomeModel \< ActiveRecord::Base  
include ContextRecord  
end

- Byron

---

<div class="post-metadata">

**Author:** ![dim](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ebca7d/32.png) [@dim](https://www.ruby-forum.com/u/dim)\
**Post date:** [February 7, 2006, 3:14pm UTC](https://www.ruby-forum.com/t/ruby-rails-inheritance/101973/3 "2006-02-07T15:14:51Z")

</div>

Thanks for the reply, but it’s not that easy as it seems. My  
RecordWithFeatures overloads the “find” method. Implementing the  
functionality as a module would completely overWRITE the find method.

I had already a discussion on that on this list, it’s not trivial,  
because “find” uses recursive calls, so there are two options for the  
implementation.

First (as I did), subclassing AR and overriding find. The second (I also  
tried) writing a module and aliasing the find method. The second one  
works great, but from a coder’s point of view, it is really messy,  
because in some cases it can break “find” completetly.

Now I post both solutions, maybe someone have an idea how (if) those can  
be improved.

## The first one: Extending AR

class RecordWithFeatures \< ActiveRecord::Base  
def self.descends\_from\_active\_record?  
superclass == RecordWithFeatures  
end  
def self.class\_name\_of\_active\_record\_descendant(klass)  
…  
end

def self.without\_context\_scope  
begin  
Thread.current[:bypass\_context\_scope] = true  
result = yield  
ensure  
Thread.current[:bypass\_context\_scope] = nil  
end  
return result  
end

def self.bypass\_context\_scope?  
Thread.current[:bypass\_context\_scope] == true  
end

def self.find(\*args)  
unless bypass\_context\_scope?  
with\_scope(:find =\> {:conditions =\> “…”}) do  
return without\_context\_scope { super }  
end  
end  
super  
end

def self.find\_context\_neutral(\*args)  
return without\_context\_scope { find(\*args) }  
end  
end

## class SomeModel \<\< RecordWithFeatures belongs\_to :context validates\_presence\_of :context end

## And now the other one with “including” and “aliasing”!

module ContextRecord  
def self.included(base) # :nodoc:  
base.extend ClassMethods  
end

module ClassMethods  
def bound\_to\_context  
belongs\_to :context  
validates\_presence\_of :context  
class\_eval { extend ContextRecord::SingletonMethods }  
include InstanceMethods  
class \<\< self  
alias\_method :original\_find, :find  
alias\_method :find, :find\_with\_context\_scope  
end  
end  
end

module SingletonMethods  
def without\_context\_scope  
begin  
Thread.current[:bypass\_context\_scope] = true  
result = yield  
ensure  
Thread.current[:bypass\_context\_scope] = nil  
end  
return result  
end

```
def bypass_context_scope?
  Thread.current[:bypass_context_scope] == true
end

def find(*args)
  unless bypass_context_scope?
    with_scope(:find => {:conditions => "..."}) do
      return without_context_scope {original_find(*args)}
    end
  end
  original_find(*args)
end

def find_context_neutral(*args)
  without_context_scope {original_find(*args)}
end

```

end

module InstanceMethods  
# …  
end  
end  
ActiveRecord::Base.class\_eval { include ContextRecord }

## class SomeModel \<\< ActiveRecord::Base bound\_to\_context end

Thanks  
Dim

---

<div class="post-metadata">

**Author:** ![dim](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ebca7d/32.png) [@dim](https://www.ruby-forum.com/u/dim)\
**Post date:** [February 7, 2006, 8:41pm UTC](https://www.ruby-forum.com/t/ruby-rails-inheritance/101973/4 "2006-02-07T20:41:56Z")

</div>

On Feb 7, 2006, at 3:10 AM, Dim wrote:

> but it’s not RecordWithFeatures, but it’s children, that should belong  
> to “context”.

Use the Class#inherited hook:

$ ruby -w  
class X  
def self.inherited(klass)  
puts “Inherited by #{klass}”  
end  
end  
class Y \< X; end  
Inherited by Y

So I think you would have:

def self.inherited(klass)  
klass.belongs\_to :context  
klass.validates\_presense\_of :context  
end

–  
Eric H. - removed\_email\_address@domain.invalid - [http://segment7.net](http://segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)

---

<div class="post-metadata">

**Author:** ![dim](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ebca7d/32.png) [@dim](https://www.ruby-forum.com/u/dim)\
**Post date:** [February 7, 2006, 8:45pm UTC](https://www.ruby-forum.com/t/ruby-rails-inheritance/101973/5 "2006-02-07T20:45:11Z")

</div>

On Feb 7, 2006, at 3:54 AM, Byron S. wrote:

> A nice construct in Ruby for sharing code between classes but  
> without the messyness of requiring a common ancestor is the mixin  
> pattern. ([http://www.rubycentral.com/book/tut\_modules.html](http://www.rubycentral.com/book/tut_modules.html))

But he _has_ a common ancestor, so he doesn’t need mixins.

> If there are elements that you’d like to share you can make it more  
> clear what is going on via something like the the following. The  
> only thing is I’m not 100% sure it will work with the belongs\_to  
> and validates\_presence\_of - let me know!

… maybe you should test it? Otherwise this just adds noise.

> include ContextRecord  
> end

This is a violation of DRY. Don’t do that. Use subclassing as Dahl  
and Nygaard intended.

–  
Eric H. - removed\_email\_address@domain.invalid - [http://segment7.net](http://segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)
