Doubts on what association to choose

Hello everyone,

I’m a beginner Rails developer and right now am building a sample
project
to show off at some job apply. The app is rather simple, I guess, but I
have come to some doubts on what associations to chose and why.

Basically a User can create a bill(being its creditor) and the billing
can
have many other Users(as their debtors), so you can track up billings
you
share with other persons, like rent, market, food orders etc, and
control
what each one got to pay you.

Right now I have the following model:

class User < ActiveRecord::Base
has_many :billings, foreign_key: “creditor_id”, dependent: :destroy
has_many :debts, foreign_key: “debtor_id”, dependent: :destroy
end

class Billing < ActiveRecord::Base
belongs_to :creditor, class_name: “User”
has_many :debts, dependent: :destroy
end

class Debt < ActiveRecord::Base
belongs_to :billing
belongs_to :user
end

would this be the better approach? Or something like:
User has_many billings through debts
Billing has_many debts ?

And in that case, would appreciate some help to model those
associations,
because I’m still kinda lost on this flow.

Thanks in advance,
Diego Dillenburg Bueno

Assuming a single creditor and multiple debtors for a single billing,
you
will need a one to one relationship for the creditor -> billing
(belongs_to
on the billing, as you have done), but a many to many relationship for
debts -> users.

Generally, it’s better to implement the many-to-many as a has_many
:through
so you can add logic. It’s probably doubly important when there is money
involved!

I would rethink the dependent: destroy though. You probably want to use
a
soft delete instead, or else you will lose your past transactions.

On 21 September 2014 05:37, Diego Dillenburg Bueno <

Won’t I be able to add the logic I need for debts using has_many
belongs_to? Basically all that I would need is to gather which debts
I(as
the user) have and be able to(in future) toggle their ‘paid/unpaid’
status.
Or would it be better to have a relationship table? via has_many
through?

As of the soft deleting I’m gonna narrow it down haha at first I’m just
trying to build some concrete functionality, this is just to show some
coding skills for an internship, gonna try 'n develop it much further
when
I get the time and skills.

Anywyay, thanks for helping!
Diego Dillenburg Bueno

2014-09-21 20:47 GMT-03:00 Timothy M. [email protected]:

Hi Diego,

You’re correct when you say you can add the logic for a has_many /
belongs_to (which is a one to many relationship), but as far as I’m
aware,
you need a has_many :through for adding logic to a many-to-many
relationship.

Good luck with the internship!
Timothy.

On 22 September 2014 12:37, Diego Dillenburg Bueno <

Diego,

You actually have a very good question here.

I don’t quite see all the foreign keys here, and I only grok 75% of your
specific data model, so I will answer your question generally and give
you some options rather than specifically tell you how to do it.

You probably read that the rails default is to use the class name as the
association name. In the case of multiple associations to the same
classes – possibly through join tables – this is actually a confusing
way to name your associations.

Consider something that is not your data model: An “Article” that has
both an Author (user object) and an Editor (user object)

The standard way to write your association is like so:

class Article < ActiveRecord::Base
belongs_to :user
end

But the problem here is that you actually want two relationships to two
different user objects (one for author and another for editor).

As you have already discovered, you can use a different name for the
association name, as long as you pass class_name as an option to your
association declaration, like so:

class Article < ActiveRecord::Base
belongs_to :author, class_name: “User”
belongs_to :editor, class_name: “User”
end

In the example above, your Article table would have a foreign key for
author and editor (my personal naming convention is to name these
author_user_id and editor_user_id, that way the field conveys both the
relationship itself and the class that it relates to).

The is a really, really good idea because the worst thing in an app is
to have a relationship to a user_id and as the future developer be
scratching your head wondering if the original developer intended that
to be a “editor” or an “author”. I strongly recommend using this style
of naming convention when you will have multiple relationships to the
same classes, as you have in the example below (a user’s relationship to
a billing can be either as a creditor or as a debtor).

Remember, the association name you give is for you (& Rails) to identify
that association elsewhere in your codebase. Although the default is to
use the name of the foreign class, it is by no means required.

As far as you actual question (should you use a direct relationship
between User and Debt or should you use the has_many :through
relationship, using the billings as a join table) – I think I
understand that correctly — there is no one better to answer that than
you. (Without knowing more about your data model I can’t advise).

But I can say that you should avoid duplicitous relationships (also
known as circular dependancies). Note that if one relationship describe
a creditor and the second one describes a debtor, that doesn’t actually
count as duplicitous (for the purpose of my argument). It would be
duplicitous if a foreign key describes the same relationship already
described in another place (like a different foreign key or through a
join table). That’s what you want to avoid.

The confusing part of your data model is that a Debt belongs_to a user
(is that a creditor or debtor relationship? See how using non-default
association names as explained above can be advantageous?)

If the context of the Debt record only has meaning by being related to a
Billing, then it probably doesn’t make sense to also make it have a
user_id (since you can derive that user by examining the relationship to
the Billing object). Again, since you have some tricky stuff going on
with debtors/creditors understand that I may not be understanding your
data model fully.

I would recommend you create an old-fashioned ERD (Entity Relationship
Diagram) on a napkin. Also you might want to learn a little bit about
the ancient art of “3rd Normal Form”.

Hope this help!

Jason

Thank you very much for the attention, guys!
I think I have nailed the association modelling. And as of the debt
relationship. It would be like: Someone pay for a bill(creditor) for
many
other people(those are debtors), that’s why I need to have 0, 1 or
multiple
debtors in one billing. That’s where I keep track of who owes
me(creditor)
money for that billing.

Now I’ve dived into a far more hairy problem:

I’m trying to dinamically generate nested forms(so I can input how many
debtors I want at the billing creation)
I got it to work once, but now I don’t know what I might possibly have
changed so it’s not working anymore.
Tried rbates railscast, then his gem nested_form, then cocoon and
couldn’t
get none of them to work properly anymore.
I tracked down the problem to be basically that: whenever I click the
link
to add fields it’s not triggering the creation of the new object, e.g. a
Billing is created on action New but it’s not creating the further
billing.debts that I need to store the multiple debtors I input in the
forms.

I’m really lost at that point, tried everything, I just need to finish
this
functionality so I can add the ‘paid/unpaid’ status toggling and finish
it.
If any of you guys can help me I’d reaaally appreciate!

The code is in my github: http://www.github.com/diegodlilenburg/codero
I don’t know which files are really relevant to this so I think it’s
easier
that I provide the full code, but mostly the functionalities are set in
the
views/billings, application_helper, application.js and the
billings_controller.
All that code refers to the rbates railscast about nested forms(196 and
197
episodes) I can’t subscribe atm to see the revised version.

Any help trying to find the error would be awesome. I’m getting to my
deadline. haha

Oh, and by the way, that 3rd normal form seems interesting, will take a
look at it.

Thank you all again for the help!
Diego Dillenburg Bueno

2014-09-22 12:54 GMT-03:00 Jason Fleetwood-Boldt [email protected]:

Diego ,

Is the link working ? im getting a 404 error from github that repo does
not
exist.

Regards
Vivek

On Tue, Sep 23, 2014 at 10:43 AM, Diego Dillenburg Bueno <

On 23 September 2014 07:38, Colin L. [email protected] wrote:

forms.

First look in development.log and check that the correct action is
being invoked and that the params are correct. Then you have to debug
your code. There are more sophisticated debug methods, but for a
start you can then put debug statements in the action to find out what
is going wrong. You can use logger.info to print stuff to the server
window to follow what is going on. For example
logger.info “At some interesting point in the code”
and
logger.info someobject.inspect

Also look at

Colin

On 23 September 2014 06:13, Diego Dillenburg Bueno
[email protected] wrote:

debtors I want at the billing creation)
I got it to work once, but now I don’t know what I might possibly have
changed so it’s not working anymore.
Tried rbates railscast, then his gem nested_form, then cocoon and couldn’t
get none of them to work properly anymore.
I tracked down the problem to be basically that: whenever I click the link
to add fields it’s not triggering the creation of the new object, e.g. a
Billing is created on action New but it’s not creating the further
billing.debts that I need to store the multiple debtors I input in the
forms.

First look in development.log and check that the correct action is
being invoked and that the params are correct. Then you have to debug
your code. There are more sophisticated debug methods, but for a
start you can then put debug statements in the action to find out what
is going wrong. You can use logger.info to print stuff to the server
window to follow what is going on. For example
logger.info “At some interesting point in the code”
and
logger.info someobject.inspect

Then you should be able to work out where it is going wrong.

Having said that I assume that you have already worked right through a
good tutorial such as railstutorial.org (which is free to use online).
If not then go and do that first, it will save you time in the long
run.

Colin

Sorry, little typo there. corret is:
GitHub - diegodillenburg/codero: Controle Financeiro para Repúblicas I typed my name wrong
hahaha.
@Collin, yeh I have debugparams in my views, which I learned on
railstutorial, that’s how I somehow identified my problem. Anyway, I
think
I’ve managed to find the problem but still trying to find a way to work
it
around.
It’s either something related to my CSS messing up where the JS wants to
apply its action or the way I render the form and fields_for

2014-09-23 3:39 GMT-03:00 Colin L. [email protected]:

I think I know what it is now, but no clue why it happens.
It won’t work whenever I open a html tag before <%= form_for @billing do
|billing| %> and close it before <%= f.fields_for :debts do |builder| %>

Anyone ever been through this or something similar? It must be some
failure
at the application.js script but I have no clue at all on how to handle
it.

2014-09-23 4:36 GMT-03:00 Diego Dillenburg Bueno
[email protected]
:

On 23 September 2014 09:20, Diego Dillenburg Bueno
[email protected] wrote:

I think I know what it is now, but no clue why it happens.
It won’t work whenever I open a html tag before <%= form_for @billing do
|billing| %> and close it before <%= f.fields_for :debts do |builder| %>

Do you mean you have

…? if so then that is
not valid html. A useful technique when strange things are happening
is to copy the html source out of the browser and paste it into the
w3c html validator to check the html is valid. [1]

Colin

[1] The W3C Markup Validation Service