Rails data modelling with has_many through

53 views
Skip to first unread message

Pradeep Achuthan

unread,
Aug 19, 2015, 1:06:46 AM8/19/15
to Ruby on Rails: Talk
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.

Colin Law

unread,
Aug 19, 2015, 6:03:20 AM8/19/15
to Ruby on Rails: Talk
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

Elizabeth McGurty

unread,
Aug 19, 2015, 11:28:38 AM8/19/15
to Ruby on Rails: Talk
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

Colin Law

unread,
Aug 19, 2015, 2:31:19 PM8/19/15
to Ruby on Rails: Talk
On 19 August 2015 at 16:28, Elizabeth McGurty <emcg...@gmail.com> 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


t 19, 2015 at 1:06:46 AM UTC-4, Pradeep Achuthan wrote:
>>
>> 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.
>
> --
> 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/d5652e9b-2ac3-49ec-a9c6-a7804230c6b5%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

Walter Lee Davis

unread,
Aug 19, 2015, 8:07:10 PM8/19/15
to rubyonra...@googlegroups.com

On Aug 19, 2015, at 2:30 PM, Colin Law <cla...@gmail.com> wrote:

> On 19 August 2015 at 16:28, Elizabeth McGurty <emcg...@gmail.com> 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
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/CAL%3D0gLuYxmsh4h__kT4c4VeQyGhYUbEvFuLMqfe%3DXwu-bsTjRw%40mail.gmail.com.

Elizabeth McGurty

unread,
Aug 20, 2015, 11:00:21 AM8/20/15
to Ruby on Rails: Talk
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: 'f...@foo.foo', 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

Elizabeth McGurty

unread,
Aug 20, 2015, 11:04:04 AM8/20/15
to Ruby on Rails: Talk
Thanks Colin and Walter for contribution.... Liz

Elizabeth McGurty

unread,
Aug 20, 2015, 11:07:43 AM8/20/15
to Ruby on Rails: Talk
Forgot:

class User < ActiveRecord::Base
   
    has_many :user_transaction
   
  end

Reply all
Reply to author
Forward
0 new messages