Use Polymorph or STI or.

25 views
Skip to first unread message

Travis Eubanks

unread,
Dec 16, 2015, 4:43:57 PM12/16/15
to rubyonra...@googlegroups.com
Im creating an expense report.

I don't know if Im on the right path but heres what im thinking...
When submitting an expense report the user could have travel expenses,
parking expenses, cell phone expenses or even meal expenses.

Each expense available shares 3 common attributes
-cost, occurrence, GL code

(some expenses will need additional attributes).

My first thought was to use STI:

class User < ActiveRecord::Base
end

class Expense < ActiveRecord::Base
(which have the cost, occurrence, GL code attributes)
end

class Travel < Expense
end

class Entertainment < Expense
(and this class and some others will be needing additional attributes)
end

/////////////////

1. A user selects a month and year this expense will belong to
2. A user then selects which 'type' of expense they're going to fill out
(i.e. Travel expense)
3. User submits that form
4 Repeat as needed

I want to be able to:
view all expenses for a user
view all user expenses associated with a month/year
View all user expenses via a 'type' of expense

I wanted to use STI but not all models will be all the same as some will
have additional attributes so then I thought okay maybe polymorphism
will be needed. Any help would be gratifying thank you!

--
Posted via http://www.ruby-forum.com/.

Colin Law

unread,
Dec 16, 2015, 5:03:31 PM12/16/15
to Ruby on Rails: Talk
I would probably start by doing it the simple way with a single table
for expenses where the table contains all the fields for all expense
types. Then have an expense_type field (don't call it just type as
that is a reserved word in Rails). Don't worry about the fact that
some fields will be empty on some expense types. Obviously User
has_many expenses, Expense belongs_to user.

It might be worth using STI but I would start the simple way and see
how it pans out. Refactoring for that sort of change should not be
difficult.

You might want to consider having expense_type as a table so that you
can add expense types without changing the code. Expense belongs_to
expense_type, but that may or may not be appropriate for your
requirement.

Colin

>
> --
> Posted via http://www.ruby-forum.com/.
>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/49a7d926ea0564896ab20d1ff65f79c2%40ruby-forum.com.
> For more options, visit https://groups.google.com/d/optout.

Travis Eubanks

unread,
Dec 17, 2015, 7:26:44 AM12/17/15
to rubyonra...@googlegroups.com
> It might be worth using STI but I would start the simple way and see
> how it pans out. Refactoring for that sort of change should not be
> difficult.
>
> You might want to consider having expense_type as a table so that you
> can add expense types without changing the code. Expense belongs_to
> expense_type, but that may or may not be appropriate for your
> requirement.
>
> Colin



Ok so it would be just one form with the options of selecting the type
of expense. Then for my requirements I could just use scopes when
querying (i.e. "Give me all expenses for this user that are business
entertainment.")n essentially right?

Cause each expense has a pre defined GL code for it so would you think
it would be best to build a Case and When method to preset those before
it saves?

Colin Law

unread,
Dec 17, 2015, 8:42:49 AM12/17/15
to Ruby on Rails: Talk
On 17 December 2015 at 12:25, Travis Eubanks <li...@ruby-forum.com> wrote:
>> It might be worth using STI but I would start the simple way and see
>> how it pans out. Refactoring for that sort of change should not be
>> difficult.
>>
>> You might want to consider having expense_type as a table so that you
>> can add expense types without changing the code. Expense belongs_to
>> expense_type, but that may or may not be appropriate for your
>> requirement.
>>
>> Colin
>
>
>
> Ok so it would be just one form with the options of selecting the type
> of expense.

Now you are asking (I think) about what your user interface should
look like. That is up to you.

> Then for my requirements I could just use scopes when
> querying (i.e. "Give me all expenses for this user that are business
> entertainment.")n essentially right?

Using scopes is often a good idea, it can save typing and aid understanding.

>
> Cause each expense has a pre defined GL code for it so would you think
> it would be best to build a Case and When method to preset those before
> it saves?

I have no idea what you are asking here. Sorry.

Colin

Travis Eubanks

unread,
Dec 17, 2015, 12:30:43 PM12/17/15
to rubyonra...@googlegroups.com
> I have no idea what you are asking here. Sorry.
>
> Colin
I meant using a case statement. Sorry that was very poorly worded.

def which_expense_type(expense)

case expense.expense_type

when "Travel"
expense.gl_code = arbitrary_number
when "Parking"
expense.gl_code = arbitrary_number
end

end

Colin Law

unread,
Dec 17, 2015, 12:40:13 PM12/17/15
to Ruby on Rails: Talk
On 17 December 2015 at 17:29, Travis Eubanks <li...@ruby-forum.com> wrote:
>> I have no idea what you are asking here. Sorry.
>>
>> Colin
> I meant using a case statement. Sorry that was very poorly worded.
>
> def which_expense_type(expense)
>
> case expense.expense_type
>
> when "Travel"
> expense.gl_code = arbitrary_number
> when "Parking"
> expense.gl_code = arbitrary_number
> end

Is the gl code a unique number that identifies the type? If so then
that should be stored in the db but the string should not, since it
can be determined from the string. Alternatively put the string in
the db and not the code. It is almost always a bad idea to store
redundant data in the db.

Colin

Travis Eubanks

unread,
Dec 17, 2015, 6:36:30 PM12/17/15
to rubyonra...@googlegroups.com
> Is the gl code a unique number that identifies the type? If so then
> that should be stored in the db but the string should not, since it
> can be determined from the string. Alternatively put the string in
> the db and not the code. It is almost always a bad idea to store
> redundant data in the db.
>

Yeah, the gl_code will be a set number. For instance all travel
expenses will have a gl code of 8907 and all employee meals will have a
gl code of 5201 and so on.

Cause I'd like when a user chooses a type of expense that that expenses
gl_code will be saved as appropriate.

This is because the final step in the reporting is to gather the total
cost of each gl code and display it. Some expenses share the same gl
code too.. make sense ?

Colin Law

unread,
Dec 18, 2015, 4:49:59 AM12/18/15
to Ruby on Rails: Talk
It is important to separate user interface issues from database
issues. There is no need (from what I understand) to have both name
and gl code in the database as if you (the programmer) knows one then
you are able to determine the other. If you want both on the UI then
that is no problem, just work the other one out when you need to
display it.

Colin

Travis Eubanks

unread,
Dec 18, 2015, 7:35:20 AM12/18/15
to rubyonra...@googlegroups.com
> It is important to separate user interface issues from database
> issues. There is no need (from what I understand) to have both name
> and gl code in the database as if you (the programmer) knows one then
> you are able to determine the other. If you want both on the UI then
> that is no problem, just work the other one out when you need to
> display it.

OKay okay so basically instead of categorizing them by their name as a
string just categorize them by their gl_code and the gl_code is what
will be saved in the db and I can just work out displaying the expense
type name on the UI.

The only thing is the employee that is inputing their expense doesnt
always know the gl_code or if ever because to them its meaningless (to
the endpoint person its important)

So maybe When they choose what kind of expense it is make it a dropdown
list with the Expense type name and the gl_code and then it'll just save
the gl_code.

This would be a belongs_to has_many relationship between expenses and
gl_codes

PS thanks for helping thus far Colin. I'm the only developer here at my
work and have no one to bounce ideas off of or thoughts so this has been
helpful

Colin Law

unread,
Dec 18, 2015, 8:34:50 AM12/18/15
to Ruby on Rails: Talk
On 18 December 2015 at 12:34, Travis Eubanks <li...@ruby-forum.com> wrote:
>> It is important to separate user interface issues from database
>> issues. There is no need (from what I understand) to have both name
>> and gl code in the database as if you (the programmer) knows one then
>> you are able to determine the other. If you want both on the UI then
>> that is no problem, just work the other one out when you need to
>> display it.
>
> OKay okay so basically instead of categorizing them by their name as a
> string just categorize them by their gl_code and the gl_code is what
> will be saved in the db and I can just work out displaying the expense
> type name on the UI.
>
> The only thing is the employee that is inputing their expense doesnt
> always know the gl_code or if ever because to them its meaningless (to
> the endpoint person its important)
>
> So maybe When they choose what kind of expense it is make it a dropdown
> list with the Expense type name and the gl_code and then it'll just save
> the gl_code.
>
> This would be a belongs_to has_many relationship between expenses and
> gl_codes

That was not what I thought you were doing, I thought you were just
going to include the gl_code in the expenses table. However there may
well be an argument for having an expense_types table with
Expense belongs_to expense_type
ExpenseType has_many expenses

In that case you could put both the string and gl code in the expense
type table and there is no need for any code to work out one from the
other. Note the difference here is that each expense type will only
be saved in the db once so there is no redundant data. As you
originally described it I thought you were going to save both gl code
and string in each expense record so there would be multiple instances
of each in the db.

Colin

Travis Eubanks

unread,
Dec 18, 2015, 10:32:03 AM12/18/15
to rubyonra...@googlegroups.com
> That was not what I thought you were doing, I thought you were just
> going to include the gl_code in the expenses table. However there may
> well be an argument for having an expense_types table with
> Expense belongs_to expense_type
> ExpenseType has_many expenses

I think this is the most appropriate way to handle this at this stage.
Then I'll just build all the possible expense types that our company
allows in the database so the dropdown would make sense then..

EXPENSE
occurrence
cost
description
expense_type_id

EXPENSE_TYPE
name
gl_code


Grab an expense type
e = ExpenseType.where(gl_code: 9090)

display me the expenses that relate to this gl_code
e.expenses

Colin Law

unread,
Dec 18, 2015, 10:43:57 AM12/18/15
to Ruby on Rails: Talk
Looks good to me.

Colin

Travis Eubanks

unread,
Dec 18, 2015, 7:50:05 PM12/18/15
to rubyonra...@googlegroups.com
Got the main feature done. Thank you for your help Colin and talk
throughs. What a difference it makes!
Reply all
Reply to author
Forward
0 new messages