In part 1 we added a placeholder page for our new budget feature and updated our navigation. This time out we are going to look at adding some actual content to the budget page.
Today we’ll be looking to replace our placeholder budget page with some actual content. We’ll create the basic content we want to display and update our code so the user can set their budget.
As previously mentionned I’m not sure this is really a “follow along” type of series, but it is possible to follow along if you wish.
If you’ve been following along you can continue with the code from part 1, or you can grab the code from GitHub.
Clone the Repo:
After grabbing the code we should set our local Ruby version and run
Next let’s create a new branch for today’s work.
With that out of the way, let’s get to it!
Where we’re starting from
Let’s fire up the server and have a quick look at our current budget page.
Not too impressive! The first thing I notice is we are missing the
current income versus expenses widget that shows up on the other pages, i.e.
So let’s work on that first.
Adding content to the budget page
First off, let’s get that widget displayed, this is an easy change.
Adding the widget
A pretty simple change, we’ve added a few
divs and included the widget via
<%= render 'shared/mtd_ytd' %>.
We now see the widget showing up.
Next let’s figure out how to display each of our categories along with the current amount spent on that category for the current month. For now we won’t worry about the
budgeted field or any functionality related to the
Displaying our categories on the Budget page
I’ve manually added in some test data in order to have a few categories and transactions in the database. One thing to note is we should already have a backend query that we can adapt for use on our
Budget page. If we view the reports page, we’ll see our expense report is displaying the exact data we are after.
Looking at how the data is being loaded on the reports page, we’re using a method called
expenses_by_category_and_date_range. So we just need to call into that method from the
BudgetController. The method takes in a date range of the format
dd mmm YYYY:TO:dd mmm YYYY.
Loading the data
So let’s update the controller code.
Pretty simple, we build up our
range parameter to pass into
expenses_by_category_and_date_range. Then we use the
sum value returned by the method to populate a new
spent attribute on the
category model. In this way we end up with a list of categories along with how much has been spent on those categories for the current month.
spent attribute isn’t something we’ll be adding to the database so we can just use an
attr_accessor. Let’s update the model:
One other thing to make note of is we’re populating the
spent attribute by comparing the values of the
category.id field. The
expenses_by_category_and_date_range method does not currently return the category id, so we need to update the method to do so.
/app/models/user.rb …line 87
Simple, we just added the
id in the
Now it’s time to update the UI!
Displaying the data
Let’s update the view.
So a bit of a code dump, but all we’ve really got here is some HTML with a bit of logic mixed in. We’ve got an
if statement to check if we have any categories to display. If not we output a message indicating the user needs to create some categories. If we do have category records to display we display them in a table. We’re rendering the individual category items in a seperate file via
<%= render 'budget_item', item: item %> so we’ll need to create that.
And with that we now have a pretty decent initial outline of what our page will display.
Adding the budget field
Before stopping for today, let’s add the new
budgeted field. We have a few options for this. We could create a new database table containing a
user_id and a
budgeted value. However I think it is reasonable to simply add a new field to the existing
categories table. This avoids the complexity (albeit minor) of adding a new database table / model and logically it is reasonable to think that for each category record a field exists that indicates the amount a user has budgeted for that category.
So let’s create a migration for the new field.
We’ll update the migration as follows:
And now we can run the migration.
We need to make a small change to the
Category model so that we can access the
Now we just need to update
_budget_item.html.erb… since we want the user to be able to set the value of the
budgeted field we’ll use the functionality of the best_in_place gem to allow for this.
So we’ve added the field and made it editable via the
best_in_place gem. Since we already have an
update method on the
Category controller we don’t need to make any backend changes. When an edit occurs it will be sent to the
update method of
_budget_item.html.erb changes in place we now have an editable
What about tests?
Actually before wrapping up for the day, let’s take care of one more thing. As we’ve been building out this new functionality we’ve been neglecting our tests… let’s remedy that!
Since we’ve updated our database, the first step is to update our test database.
Now let’s update the tests for our category model. We’ll add
respond_to tests for the two new fields we added.
Straightforward, looking at the rest of the
category_spec, I think it would also make sense to add a validation for the new budget field. We’ll add this at the end of the spec.
We also need to add the actual validation.
And with that, let’s ensure the
category model tests pass:
Budget page tests
Now we should create some tests for the actual budget page. We’ll need a new file for this.
As far as the content of the test goes… I am going to vomit out some code and won’t provide much of an explanation… I feel the code is pretty self explanatory however. So our test looks like:
Let’s ensure the budget tests all pass.
And then just for good measure, let’s run the entire suite.
Sweet all looks good!
That’s it for today, we can merge our changes and we can remove our current working branch.
Thanks for reading and I hope you enjoyed the post!