Accessing a class's variables from an included module

I created a mixin module called BaseProduct. This module has an
initialize method in it. I am trying to use some meta-programming to
set variables in initialize from the class that the module is in
included in.. I pass a CSV row into the initialize method and it needs
to set all the variables. Its a bit confusing trying to explain it, but
here is what it looks like:

Note: the real world scenario is a bit more complicated using different
objects, but I simplified it here to use a "product" scenario.

There's a lot of recommendation against overloading initialize for
AR::Base classes:
http://www.google.co.uk/search?sourceid=chrome&ie=UTF-8&q=rails+overload+initialize

Regardless, I think you're "solving" your problem the wrong way -
you're *never* going to be able to instanciate an object without a CSV
row; is that really what you want? How will the rest of your
application work when you just want to query the DB for
ShirtProduct.first?

And have you *really* designed to have a different table for different
types of product? I can only imagine lots of pain that will be caused
by that further down the line.

I'd suggest a look at polymorphism.

def initialize(attributes = nil,row)
   super(attributes)
   <table_fields_from_class>.each_with_index do |field,i|
     #NOTE: row is an array of values (csv row to array)
     eval("self.#{field} = row[#{i}]")
   end
end
end

Don't use eval for this - send("#{field}=", value) will do the trick

I dont want to have to code an initialize method for every type of
product and I thought it would be much easier to use metaprogramming and
just pass an array of fields to a base initialize method. I may be way
off here and there may be a completely different design pattern that
would support this use case better, but this is what I originally came
up with. I have tried several things with attr_accessor, CONSTANTS,
etc.. but I have not been able to get the initialize method to see
variables I set in the class. I am probably missing something simple as
I don't fully understand the module's scope of access to the class...
seems pretty straight forward vice-versa (class from module), but the
other way around is confusing me a bit. let me know if you got any
ideas. THANKS!

If you choose to go down the constant route, remember that constants are scoped lexically. Try something like self.class::SOME_CONSTANT

Michael's advice is also sensible - writing a create_from_csv_row method is probably sounder

Fred

Thanks guys for the quick responses.. looks like I will go back to the
drawing board. I was trying to force it in the initialize method to
save a line of code, but creating create_from_csv_row is a much better
solution giving the problems you guys outlined here. Looks like
polymorphism may solve some of my problems if I can rework my legacy db
schema a bit.

Regardless, I think you're "solving" your problem the wrong way -
you're *never* going to be able to instanciate an object without a CSV
row; is that really what you want? How will the rest of your
application work when you just want to query the DB for
ShirtProduct.first?

I actually included a check which I left out of the simplified code,
which will allow regular use of initialize method if I leave out the
row:

def initialize(attributes = nil,row=nil)
    super(attributes)
    unless row.blank?
      #ugly code goes here
    end
end

I was messing around with this some more and I figured out I can use
class variables to achieve what I was trying to do. Set the class var
in first line of the module: @@table_fields and then reset it in the
class. The module has access to it in the class var in the initialize
method after this. Although I am scrapping this design in favor of what
was suggested.. figured I would still post what I came up with.

Michael Pavling wrote:

class ShirtProduct < ActiveRecord::Base
end

class PantsProduct < ActiveRecord::Base
end

And have you *really* designed to have a different table for different
types of product? I can only imagine lots of pain that will be caused
by that further down the line.

I'd suggest a look at polymorphism.

My original example is polymorphism using mixin modules/duck typing.
Are you referring to STI? I read a while back that STI was a bad choice
unless your fields are almost the same for every subclass. I am using
sort of a hybrid form of STI as you can see in my current design below.
Can you explain which implementation of polymorphism you were referring
to? In my use case the fields can vary a good bit from type to type,
and the types share about 20% of the fields with the parent class. I am
more concerned about sharing methods than I am fields in these
associations, but I do need to use a parent table to retrieve all
records from every subclass, so I don't have to do a bunch of crazy
joins. My real use case is as follows. If you have 5 minutes to read
my lengthy use case, can you explain which design you would choose and
why?

USE CASE:
I am rewriting some software I use to track affiliate network
transactions and I am going to release it open source, so I want to make
sure the design is sound. The original software was basically a quick
hack written in a day to get some info in my tables. But as I expand my
use of these tables I realize the limitations and I need something that
is designed well and maintainable.

An affiliate network = website that tracks clicks from a publisher
website over to a merchant website and records if a purchase is made.
The affiliate network then records transactions from the merchant
website and makes them available to the publisher so they can see how
much commission they earned from each sale. There are 8 major affiliate
networks that I pull transactions from right now and in the next 5
years, maybe that will grow to 20 or 30... and maybe up to 100 if
someone adds smaller networks to my open source branch.

In the most basic form a transaction (which will be a single
instance/database row of the class) includes a date, a sale amount, and
a commission amount. Each network has a different way of representing
this data and they all include additional fields that are different.

I want to preserve the integrity of the original data from each network
in my database in case I need it later on.. otherwise I would just
manipulate the data when I pull it and insert it into one table with the
common fields (date,sale,commission,network) and drop the rest of the
data. I also need to get the transactions in various formats (csv,xml)
from various sources using REST & SOAP, so each subclass (affiliate
network) will have some custom functionality in grabbing the data. For
these 2 reasons, I was planning on having a separate model and table for
each subclass.

So here is my current design. I created a mixin module called
BaseTransaction for all the shared functionality. Then I have a class
called GeneralTransaction that is an activerecord model. I have a
seperate transaction subclass for each affiliate network...
AffiliateOneTransaction, etc. Each subclass uses the BaseTransaction
mixin module for shared functionality. I am trying to remember, but I
think I chose the mixin module method because I could not use Ruby
inheritence "<" with activerecord and have a seperate table for each
subclass. A GeneralTransaction is inserted every time a subclass record
is inserted and GeneralTransaction has subclass & subclass_id fields to
reference the records in the subclass table. Seems a little bit hairy
to do it this way, but it will work. I am just trying to figure out if
there is a more "correct" way to do this design. Any thoughts and
suggestions are much appreciated. Thanks if you took the time to read
my lengthy post!