Rails data modelling with has_many through

I am building an expense tracker application and I am in middle of data
modelling. I have a Users table. Each user will log his expenses with
expense type and income with income type. So I need to know how can we
set
up associations for it.
As per my understanding I have set it up as follows

User has_many :expenses, through: :transactions
User has_many :incomes, through: :transactions

Expense belongs_to :user

Income belongs_to :user

Here I am not sure what the transaction would associate and also
expene/income type.

Any suggestions/insights would be great.

On 19 August 2015 at 06:06, Pradeep A. [email protected]
wrote:

Income belongs_to :user

Here I am not sure what the transaction would associate and also
expene/income type.

What are the fields of expense and income? The answer to that
determines whether you need a transactions table and what should be in
it.

Colin

Pradeep, following pertains to more advanced folks here. I thought that
demonstrating a good solution would be easy, but I am encountering
LocalJumpError: no block given (yield) on transaction_id… I created a
transaction table, and referenced it from User has_many. Folks, what
the
problem there?
Liz

On 19 August 2015 at 16:28, Elizabeth McGurty [email protected]
wrote:

Pradeep, following pertains to more advanced folks here. I thought that
demonstrating a good solution would be easy, but I am encountering
LocalJumpError: no block given (yield) on transaction_id… I created a
transaction table, and referenced it from User has_many. Folks, what the
problem there?

Transaction is a reserved word (for database transactions oddly
enough). Change the model name.

Colin

On Aug 19, 2015, at 2:30 PM, Colin L. [email protected] wrote:

On 19 August 2015 at 16:28, Elizabeth McGurty [email protected] wrote:

Pradeep, following pertains to more advanced folks here. I thought that
demonstrating a good solution would be easy, but I am encountering
LocalJumpError: no block given (yield) on transaction_id… I created a
transaction table, and referenced it from User has_many. Folks, what the
problem there?

Transaction is a reserved word (for database transactions oddly
enough). Change the model name.

I put this site up years ago, when I was first learning Rails:
https://reservedwords.herokuapp.com

I am sure it could use some updating, but it is mostly accurate…

Walter

Okay… I have prepared the following…

First thing is that you need to know a bit about accounting. Accounting
involves a (debit/credit) ledger that delineates all business aspects of
income, expenses, …

So to build a web site with tables based on each of these is not, in my
opinion, a good idea.

So I offer the following:

Build the tables:

mysql> describe ledgers;
±------------±-------------±-----±----±--------±---------------+
| Field | Type | Null | Key | Default | Extra |
±------------±-------------±-----±----±--------±---------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ledger_item | varchar(255) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
±------------±-------------±-----±----±--------±---------------+
4 rows in set (0.01 sec)

migration:
rails generate model ledger ledger_item:string

mysql> describe ledger_lines;
±-----------------±-------------±-----±----±--------±---------------+
| Field | Type | Null | Key | Default | Extra |
±-----------------±-------------±-----±----±--------±---------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ledger_id | int(11) | YES | | NULL | |
| ledger_line_item | varchar(255) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
±-----------------±-------------±-----±----±--------±---------------+
5 rows in set (0.01 sec)

migration:
rails generate model ledger_line ledger_id:integer
ledger_line_item:string

mysql> describe user_transactions;
±-----------------±--------------±-----±----±--------±---------------+
| Field | Type | Null | Key | Default | Extra |
±-----------------±--------------±-----±----±--------±---------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | | NULL | |
| ledger_id | int(11) | YES | | NULL | |
| ledger_line_id | int(11) | YES | | NULL | |
| line_item_amount | decimal(10,0) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |

±-----------------±--------------±-----±----±--------±---------------+
7 rows in set (0.01 sec)

migration:
You try to do yourself, based on examples above

You can do your own int size, with or with date fields…

Starting anew…

MODELS:

Assuming you already have a User model/table. For the demonstration
your
User model should have id: id, and username

class Ledger < ActiveRecord::Base
has_many :ledger_line
has_many :user_transaction

end

class LedgerLine < ActiveRecord::Base
belongs_to :ledger
has_many :user_transaction

end

class UserTransaction < ActiveRecord::Base
belongs_to :user
belongs_to :ledger ## So you can retreive at ledger level
belongs_to :ledger_line ## So you can retrieve at line item level

end

seeds.rb >>> run rake db:seed, after you have created tables via rake
db:migrate

This file should contain all the record creation needed to seed the

database with its default values.

The data can then be loaded with the rake db:seed (or created

alongside
the db with db:setup).

unless Ledger.count > 0
Ledger.create!(ledger_item: ‘expense’ ) ## id: 1
Ledger.create!(ledger_item: ‘income’ ) ## id: 2

end

unless LedgerLine.count > 0
LedgerLine.create!(ledger_id: 1, ledger_line_item: ‘travel’) ## ledge
type expense…
LedgerLine.create!(ledger_id: 1, ledger_line_item: ‘office_supplies’)
LedgerLine.create!(ledger_id: 1, ledger_line_item: ‘meals’)
LedgerLine.create!(ledger_id: 2, ledger_line_item: ‘commission’) ##
ledge
type income…
LedgerLine.create!(ledger_id: 2, ledger_line_item: ‘sales’)
LedgerLine.create!(ledger_id: 2, ledger_line_item: ‘salary’)

end

I am reusing an existing user table, please disregard email,

user_alias,
user_type, and is_rapid

unless User.count > 0
User.create!(id: 1, username: ‘Pradeep’, email: ‘[email protected]’,
user_alias:
‘foo’, is_rapid: 1, user_type: 1 ) ## id: 1
end

UserTransaction.delete_all
UserTransaction.create!(user_id: 1, ledger_id: 1, ledger_line_id: 1,
line_item_amount: 12.50)
UserTransaction.create!(user_id: 1, ledger_id: 1,ledger_line_id: 2,
line_item_amount: 102.50)
UserTransaction.create!(user_id: 1, ledger_id: 1,ledger_line_id: 3,
line_item_amount: 56.15)
UserTransaction.create!(user_id: 1, ledger_id: 2,ledger_line_id: 4,
line_item_amount: 123.56)
UserTransaction.create!(user_id: 1, ledger_id: 2,ledger_line_id: 5,
line_item_amount: 45.68)
UserTransaction.create!(user_id: 1, ledger_id: 2,ledger_line_id: 6,
line_item_amount: 32.16)

End of seeds.rb file

#From this you should be able to build associations to retrieve by user,
by
ledger item, ledge line item

Thanks Colin and Walter for contribution… Liz

Forgot:

class User < ActiveRecord::Base

has_many :user_transaction

end