views:

47

answers:

3

My web app, up until this point, has been fairly straight forward. I have Users, Contacts, Appointments and a few other things to manage. All of these are easy - it's just one model per section so I just did a scaffold for each, then modified the scaffolded code to fit my need. Pretty easy...

Unfortunately I am having a problem on this next section because I want the 'Financials' section of my app to be more in depth than the other sections which I simply scaffolded. For example, when the user clicks the 'Contacts' link on the navigation bar, it just shows a list of contacts, pretty straight forward and is in line with the scaffold. However, when the user clicks the 'Financials' link on the navigation bar, I want to show the bank accounts on the left of the page and a few of the transactions on the right.

So the financials tab will basically work with data from two models: transactions and bank_accounts. I think I should make the models (transactions & bank_accounts) and then make a controller called Financials, then I can query the models from the Financials controller and display the pages in app/views/financials/

Am I correct in this app layout? I have never worked with more than the basics of scaffolding so I want to ensure I get this right!

Thank you!

A: 

I don't have a huge amount of experience with Ruby on Rails, or MVC work in general, but I think you're going about it the right way. You generally want a model object (and by extension, database table) for data-oriented resources... That is, your models should correspond to your "nouns". Your controller's actions are your "verbs", and to me it makes perfect sense to categorize them how you like.

In this case, I would say that putting a bunch of "verbs" under financials, which interact with two model object types as needed, makes sense IF AND ONLY IF it makes sense to you for you to organize it like this. (Bear in mind that you can also evaluate how well organized and intuitive the corresponding URLs feel to you, though I'm sure most MVC purists would add that you should never just rely on examining the URLs!)

So in summary, I think you're doing everything right here, as long as it makes sense to you. Yes, you'll have to write your views and controller actions yourself, though you can start using ruby script/generate controller financials action1 action2 [...]; that at least gives you skeletons of the view files and empty controller actions.

Platinum Azure
A: 

If you are comfortable with scaffolding then i would suggest that you generate a scaffold for both

transactions: script/generate scaffold transaction financial_id:integer ...

bank_accounts: script/generate scaffold bank_account financial_id:integer ...

and financials script/generate scaffold financials ...

In your transactions model, add this:

class Transaction < ActiveRecord::Base
  belongs_to :financial
end

In your bank_account model, add this:

class Bank_account < ActiveRecord::Base
  belongs_to :financial
end

In your financial model, add this:

class Financial < ActiveRecord::Base
  has_many :transactions
  has_many :bank_accounts
end

Now from your financials controller you can use something like this:

def index
  @financial = Financial.find(params[:id])

  #This fetches all bank_accounts related to financial
  @bank_accounts = @financial.bank_accounts

  #This fetches all transactions related to financial
  @transactions = @financial.transactions
end

In your views you can view all the bank accounts belonging to a particular financial by just doing this:

<% @bank_accounts.each do |bank_account| -%>
   <%=h bank_account.something_here %> <!-- something_here is the column name corresponding to your bank_account table.  -->
   <%=h bank_account.something_here %> <!-- something_here is the column name corresponding to your bank_account table.  -->
   <%=h bank_account.something_here %> <!-- something_here is the column name corresponding to your bank_account table.  -->
   .
   .
   .
<% end -%>

In your views you can view all the transactions belonging to a particular financial by adding something similar:

<% @transactions.each do |transaction| -%>
   <%=h transaction.something_here %> <!-- something_here is the column name corresponding to your bank_account table.  -->
   <%=h transaction.something_here %> <!-- something_here is the column name corresponding to your bank_account table.  -->
   <%=h transaction.something_here %> <!-- something_here is the column name corresponding to your bank_account table.  -->
   .
   .
   .
<% end -%>

Remember, while creating a new transaction/bankaccount use the id belonging to the particular financial. Hope this helps. Cheers! :)

Shripad K
I'm unsure if this is the best way to implement the relationships for these models. Presumably, accounts and transactions have a one-to-many relationship. Forcing them both to be children of a model for the purpose of creating a controller and view simply to show the information for two related models together is more of a work-around than anything else.
Shaun
You are right. But i just tried answering the immediate problem that @user363243 was facing keeping only in mind that some X and Y model is tied up with a Z controller. I did not presume anything more as it was not explicitly asked. :)
Shripad K
Hey guys, thanks for the great help! The only problem with the example above is that 'financials' was just a way for me to group bank_accounts and their related transactions. I could have called it 'Banking Center' or anything. That being said, I couldn't actually do something like @financial = financial.find(params[:id])
A: 

It sounds to me as if you want two views:

However, when the user clicks the 'Financials' link on the navigation bar, I want to show the bank accounts on the left of the page and a few of the transactions on the right.the transactions on the right.

Keep in mind that one screen doesn't always mean one view in MVC. Conceptually, a view simply renders model data so the user can do something meaningful with it through controller actions. Rails muddies this up a bit by having you create a file in a views/ directory for each screen, so it's easy to think that one screen means one view. However, you can also call layouts within views in Rails, and these layouts are themselves views.

Putting transactions and accounts in separate views means each would have a controller to handle the user's interaction with each segment of data. The account controller, for example, would handle the event where the user selects an account to view additional information about an account. This would result in fetching transactions to show the user. The user could then interact with a transaction in an attempt to reconcile, void, or contest it. This would invoke logic in the transaction controller.

While this does a good job of removing the coupling from your controllers, this may seem like it couples the two views. However, the coupling is one-way: the account list includes logic specific to the transaction view (i.e. updating it when you select an account). The transaction view remains reusable in other areas of the application. For the most part, the account listing remains reusable as well, especially if you isolate it into a separate layout. The only difference you'd need for this specific screen is the handling of when a user clicks on an account.

If you merge everything into a financials view, it's still possible to keep things loosely-coupled, but it becomes more difficult to do so. The additional layer takes extra effort and may subconsciously guide you to merge everything up together.

Of course, either way works, and you could easily argue that the final design is an exercise that is best left to the developer's preference. I simply offer my interpretation of how one would most-accurately stick to the patters Rails attempts to guide developers to using.

Shaun
I'm having a hard time understanding this - sorry, but i'm pretty new to rails! Are you suggesting that I should have a controller for each model (bank_accounts and transactions) and reference those controllers from the financials controller that I will make? If that's not what you mean, I don't understand. :(
You would have two models and two controllers: one of each for bank_accounts and transactions. Each controller would manage actions associated with views and interact with the model.You would have many models depending on how your user needed to view or interact with the data. In the example you give, your "Finances" page would have two views one it: a Bank Account listing on the side that allowed user to click and select an account, and a Transaction listing in the main pane that showed relevant transactions.
Shaun
ok, when you say "In the example you give, your "Finances" page would have two views one it: a Bank Account listing on the side that allowed user to click and select an account, and a Transaction listing in the main pane that showed relevant transactions." Are you meaning partials when you say views?I ask this because I could load a partial from another directory (i.e. app/views/bank_accounts/_accounts.html.erb and app/views/transactions/_transaction_list.html.erb)
Yes, that is what I meant. I referred to them as views in that, as far as MVC is concerned, they are views for those models/controllers. However, as far as Rails is concerned, you'd make them both partials inside a parent view.
Shaun