Should rails models be concerned with other models for the sake of skinny controllers?

Question :

Should rails models be concerned with other models for the sake of skinny controllers?,

Answer :

I read everywhere that business logic belongs in the models and not in controller but where is the limit?
I am toying with a personnal accounting application.

Account  Entry  Operation  

When creating an operation it is only valid if the corresponding entries are created and linked to accounts so that the operation is balanced for exemple buy a 6-pack :

o=Operation.new({:description=>"b33r", :user=>current_user, :date=>"2008/09/15"})  o.entries.build({:account_id=>1, :amount=>15})  o.valid? #=>false  o.entries.build({:account_id=>2, :amount=>-15})  o.valid? #=>true  

Now the form shown to the user in the case of basic operations is simplified to hide away the entries details, the accounts are selected among 5 default by the kind of operation requested by the user (intialise account -> equity to accout, spend assets->expenses, earn revenues->assets, borrow liabilities->assets, pay debt assets->liabilities …) I want the entries created from default values.

Read More  Best way to play MIDI sounds using C#

I also want to be able to create more complex operations (more than 2 entries). For this second use case I will have a different form where the additional complexity is exposed.This second use case prevents me from including a debit and credit field on the Operation and getting rid of the Entry link.

Which is the best form ? Using the above code in a SimpleOperationController as I do for the moment, or defining a new method on the Operation class so I can call Operation.new_simple_operation(params[:operation])

Isn’t it breaking the separation of concerns to actually create and manipulate Entry objects from the Operation class ?

I am not looking for advice on my twisted accounting principles 🙂

edit — It seems I didn’t express myself too clearly.
I am not so concerned about the validation. I am more concerned about where the creation logic code should go :

assuming the operation on the controller is called spend, when using spend, the params hash would contain : amount, date, description. Debit and credit accounts would be derived from the action which is called, but then I have to create all the objects. Would it be better to have

#error and transaction handling is left out for the sake of clarity  def spend    amount=params[:operation].delete(:amount)#remove non existent Operation attribute    op=Operation.new(params[:operation])    #select accounts in some way    ...    #build entries    op.entries.build(...)    op.entries.build(...)    op.save  end  

or to create a method on Operation that would make the above look like

def spend    op=Operation.new_simple_operation(params)    op.save  end  

this definitely give a much thinner controller and a fatter model, but then the model will create and store instances of other models which is where my problem is.

Read More  Is there any list datatype in MySQL stored procedures, or a way to emulate them?

,

but then the model will create and store instances of other models which is where my problem is.

What is wrong with this?

If your ‘business logic’ states that an Operation must have a valid set of Entries, then surely there is nothing wrong for the Operation class to know about, and deal with your Entry objects.

You’ll only get problems if you take this too far, and have your models manipulating things they don’t need to know about, like an EntryHtmlFormBuilder or whatever 🙂

Read More  Is there anything wrong with this query?

That’s the answer Should rails models be concerned with other models for the sake of skinny controllers?, Hope this helps those looking for an answer. Then we suggest to do a search for the next question and find the answer only on our site.

Disclaimer :

The answers provided above are only to be used to guide the learning process. The questions above are open-ended questions, meaning that many answers are not fixed as above. I hope this article can be useful, Thank you