Acts_as_whatever


#1

Hi there,

I love the acts_as_* family that rails uses. I’ve also found I can
create something similar by dropping the following code into my
activerecord classes:

class MyClass < ActiveRecord::Base

class << self
alias_method :count_with_unapproved, :count
end

def self.find(*args)
options = extract_options_from_args!(args)
if options[:conditions].nil?
options[:conditions] = [“status = ‘approved’”]
end
args << options
super(*args)
end

def self.count(conditions = nil, joins = nil)
logger.info conditions.inspect
if conditions.nil?
conditions = “status = ‘approved’”
else
case conditions
when String then conditions += " AND status = ‘approved’"
when Array then conditions[0] +=" AND status = ‘approved’"
end
end
super(conditions, joins)
end
end

which lets me get the equivalent functionality of something like
acts_as_approved, where I can easily subdivide my records into approved
and not approved.

I’d love this to be a mixin, but when I look at the code for, say,
acts_as_paranoid I feel like the ruby novice I am. I’d like to create
other versions of this, like acts_as_private that would allow me to
divide off other things based on the setting in a private field, but
again, I don’t feel like I’m ready to create my own mixin from scratch.

I was thinking it would be cool to have mixin called “acts_as_whatever”
that you could use like this:

class MyClass < ActiveRecord::Base
acts_as_whatever :status => ‘approved’
end

which would do the same as my code above - anybody know if that’s
practical?

Then I could do things like:

class MyClass < ActiveRecord::Base
acts_as_whatever :public=> ‘true’
end

I guess alternatively I could just extend ActiveRecord::Base and make my
private or status-oriented classes extend that, or I could try again to
get my head round mixin creation.

Any thoughts?

CHEERS> SAM


#2

Hi,
I am currently studying the acts_as_whatever design because I would like
to implement something like an “acts_as_noteable.” My idea is just to
be able to have simple text notes for any given model. Of course there
would be many possible notes. The problem is that I do not want to mess
with adding new tables. I just want one “whatever” table. The problem
is that I would have to continually add fields to that one database
table everytime I make another object to be “noteable.” This is more of
a database design issue but has some relevance because if I use the
“acts_as_whatever” system or the “acts_as_taggable” style code then I
have to always manually add tables. Isn’t there a simple way to do this
without adding either tables or fields in the database (once the initial
db design if found)? To restate, I mean to say that I want to add only
rows, not tables or columns. I am sort of stuck on this db problem
(forcing me to study some db theory). I thought the people who designed
“acts_as_whatever” template might have thought about how to avoid adding
tables or fields.

Thanks for any input!

Philip


#3

The problem is that I would have to continually add fields to that
one database table everytime I make another object to be “noteable.”

Instead of making another database table every time you want to make an
object “noteable” use polymorphic associations
(http://wiki.rubyonrails.org/rails/pages/UnderstandingPolymorphicAssociations).
It’s actually the perfect instance to use them.

note.rb:

class Note << ActiveRecord::Base
belongs_to :noteable, :polymorphic => true
end

any_class_with_note.rb:

class AnyClassWithNote << ActiveRecord::Base
has_many :note, :as => :noteable
end

another_class_with_note.rb:

class AnotherClassWithNote << ActiveRecord::Base
has_many :note, :as => :noteable
end

schema.rb:

create_table “another_class_with_notes”, :force => true do |t|

end

create_table “any_class_with_notes”, :force => true do |t|

end

create_table “notes”, :force => true do |t|
t.column “title”, :string
t.column “description”, :text
t.column “user_id”, :integer
t.column “created_at”, :datetime
t.column “updated_at”, :datetime
t.column “noteable_type”, :string
t.column “noteable_id”, :integer
end


#4

Thanks for the extra information. It is helpful. My problem was that I
was trying first to think of this “acts_as_whatever” concept within the
relational modelling “sphere of influence”. Once fully understood at
the db level, then I wanted to understand it from the ORM level.
However, I wanted to have a db design which did not “store” anything
about the tables themselves. In other words I tried to design it with
E-R diagrams using only the basic techniques. Specifically I wanted to
avoid a table which was itself a list of tables which were “noteable”.
Interesting, it was not easy to keep the E-R conceptual model “flat”…
It appears that you must start storing “object meta data” somewhere
before you can implement “acts_as_whatever” on the tables. I know I am
belaboring the point. However, this is very rich fodder for the student
of the two design spheres (ORM and DB). Specifically, I hoped it would
shed some light on the relationship between “object realm” and “DB
realm”.

Thanks for the input!

Philip

Suggester wrote:

The problem is that I would have to continually add fields to that
one database table everytime I make another object to be “noteable.”

Instead of making another database table every time you want to make an
object “noteable” use polymorphic associations
(http://wiki.rubyonrails.org/rails/pages/UnderstandingPolymorphicAssociations).
It’s actually the perfect instance to use them.

note.rb:

class Note << ActiveRecord::Base
belongs_to :noteable, :polymorphic => true
end

any_class_with_note.rb:

class AnyClassWithNote << ActiveRecord::Base
has_many :note, :as => :noteable
end

another_class_with_note.rb:

class AnotherClassWithNote << ActiveRecord::Base
has_many :note, :as => :noteable
end

schema.rb:

create_table “another_class_with_notes”, :force => true do |t|

end

create_table “any_class_with_notes”, :force => true do |t|

end

create_table “notes”, :force => true do |t|
t.column “title”, :string
t.column “description”, :text
t.column “user_id”, :integer
t.column “created_at”, :datetime
t.column “updated_at”, :datetime
t.column “noteable_type”, :string
t.column “noteable_id”, :integer
end


#5

I think
acts_as_commentablehttp://www.juixe.com/techknow/index.php/2006/06/18/acts-as-commentable-plugin/plugin
will do the notes for you.