Wednesday, 31 March 2010

Rails - Day 15 - Rails Forms Part II

Rails  - Day 1 - The RubyGem Love Story
Rails -  Day 10 - Testing Rails Controllers
Rails -  Day 13 -ActiveRecord Relationships Part II
Rails - Day 15 - Rails Forms Part II
In the last post we introduced the rails form builder and showed how easy it is to render a simple form using a simple model object.

I want to go into much more detail with a pseudo real example because most of the posts about rails forms and ActiveRecord that I have come across illustrate exactly what I did in the last post and show how to use the form builder and a simple model object.  Nearly all these examples show a simple model with a one to one mapping on a single table.  This is not very real world.

In this post I want to show how to use a form builder with a slightly more complex model.

In the past few posts, we have been building up a simple application that will record the expenses a small business owner might incur. 

Below is the view that is rendered from the new action of the ExpensesControlller where a user will add a new expense:



In the last post we were able to create an Expense object that captured the Paid by Director, Expense date, External reference and Posting Description attributes.

We covered ActiveRecord relationships in this post and defined the relationships between the expense object and its child objects.

The Expense model is a complex object with two child objects defined by the the relationships below. 


We are now going to use the form builder to both set the and retrieve attributes of the child objects through an HTML form.

Our first step is to fill the Expense Type dropdown that you can see in the screenshot at the start of the post with any records that exist in the expense_types table.

The form builder contains a select method which works well for belongs_to relationships.  The first argument of the select method is the foreign key of the belongs_to relationship which in our case is expense_type_id.  

We could create a select method similar to the following which has the ActiveRecord call ExpenseType.all to the database defined in the view and I have seen this done quite a lot:



We could do that but this feels dirty and ugly.  Such a call to the database has no place in our view and instead we add the following code to the new action of the ExpensesController:


The collect method of the array object will iterate over the array and provide a block that allows us to return a new array with different elements.  I think I am right in saying that the map and collect methods are the same.  A new array is created for each element in the original array that contains the id and name needed to render the option elements of the dropdown.

We then update our select method to use the instance variable @expense_types instead of the ActiveRecord call:


This makes me feel much better.  The ExpenseType.all call is now in the controller which of course makes it a lot more testable and tidy than adding it directly to the form builder select method.  We can also mock the call to ExpenseType.all which I prefer for testing purposes over direct database calls.

The select method will take care of the Expense belongs_to ExpenseType relationship.  

There is also a has_one relationship that defines the association between Expense and ExpensePayment as we discussed in this post.  

The ExpensePayment model object will take care of this part of the UI:


We also stated in this post that the VAT and Gross attributes are actually derived fields from the Net attribute.

The calculation for VAT is ((Net / 100) * 17.5) 
The calculation for Gross is (Net + VAT).

So the only attribute we are concerned with recording from the user is the Net attribute.  We should use JQuery and Ajax to update the derived fields Vat and Gross as the user inputs their values.

Nested Attributes

Nested attributes allow you to save attributes on associated records through the parent which is exactly the behaviour we want for our Expense has_one ExpensePayment relationship.  By default nested attribute updating is turned off but you can enable it using the accepts_nested_attributes_for class method.  When you enable nested attributes an attribute writer (property set in .NET speak) is defined on the model.  The attribute writer is named after the association, which means that in our example, a new method will be dynamically added to the Expense model:expense_expense_payment=

Enabling nested attributes on a one to one association allows us to create both the Expense and Expense_payment in one go from a params hash that would be passed in from a rails form builder generated form.

In order to test this, we create the following failing test:


You can see from the above that the hash contains a child hash named :expense_payment_attributes that will represent the child ExpensePayment model object.  To make the above test pass, we update the Expense model to the following:


The changes have incorporated the following:

  1. To make the expense_payment attributes available through nested forms we need to add the :expense_payment_attributes convention to the attr_accessible method.  We mentioned  attr_accessible in the last pos tand this method restricts what methods can be accessed via a web form.  This is often overlooked and is a potential security hole.  Shame on you if your models do not include this.
  2. We define the relationship as nested by using the accepts_nested_attributes_for method.
  3. We have also updated the has_one statement to has_one :expense_payment, :dependent => :destroy which tells ActiveRecord to cascade the delete of the child object when the Expense is deleted.

Nested Model Form

In the view that will render the new action, we simply use the fields_for method to expose the fields of the nested model:



It is worth mentioning that we are using the text_field_tag method instead of the text_field method for the readonly attributes vat and gross.

This will generate the following HTML:



You can see that the p.text_field :net expression has generated an input text element with a name attribute of expense[expense_payment][net] which models the Expense has_one ExpenseType relationship and is what rails uses to build the params hash of the relationship.

If we inspect the params hash that is passed to the create action of the ExpenseController by adding the code raise params.to_yaml to the action, we get the following output:


You can see that the expense_payment_attributes hash is nested within the parent expense hash.  This means that we can create an expense object from the form fields in our create action:

We are going to mention validation in the next post but if we now fill out the required fields and submit the form, the create action completes successfully.

In order to check that the ExpensePayment has made it into the database, we can spark up the rails console with the command ruby script/console and enter the expression ExpressionPayment.all.


We can see from the above that our relationship is successfully created.

I wanted to write this post because in my opinion, a lot of the posts on rails forms do not go into this level of detail for defining relationships.

I personally do not like having to add the accepts_nested_attributes_for method and would like the framework pick this up automatically.  If anyone who knows rails better than me can suggest a better way than this or maybe argue that this way is a good way then please leave a comment.

In the next post, I am going to touch on how to validate your rails model.


Rails - Day 14 - Rails Forms Part I

Rails  - Day 1 - The RubyGem Love Story
Rails -  Day 10 - Testing Rails Controllers
Rails -  Day 13 -ActiveRecord Relationships Part II
Rails - Day 15 - Rails Forms Part II
In the last post we finished off our sparse introduction to Rails ActiveRecord.  

We have now created the UI shell of our example application and we also have tested and defined our model that reflects the job in hand.  We re now ready to complete the server side code to tie the two together.

At the time I was writing this post, ASP.NET MVC 2.0 has just arrived and it is fairly obvious that they have taken a lot of their new ideas for their form builders from the rails form builders. 

We have already defined mark up for how the page will look



At the moment our new.html.haml page looks like this:


We have a simple table contained in a div.

Form Helpers

We are now going to refactor our page to take advantage of the Form helpers that come as part of the Rails library.  Form helpers are designed to make working with models easier compared to using standard HTML elements by providing a set of methods for creating forms based on your models.  The core method of this helper, form_for, gives you the ability to create a form for a model instance.  This helper generates the HTML for forms, providing a method for each type of input (e.g. text, password, select etc.).  When the form is submitted, the form inputs will be bundled into the params object and passed back to the controller.

In our example, we are going to create a form for the expense model object.  First we will only work on saving the Expense object and then move onto saving the Expense's child objects ExpenseType and ExpensePayment objects.  To take advantage of the rails form helpers, we refactor the above haml to the following:



The form_for method is possibly the most popular helper used when generating a form that binds to one type of object.  The parameter you pass through fomfor f is of type FormBuilder which offers the other methods you can see like check_box, date_select, text_field, text_area etc.

The above will generate the following HTML:



You can see from the above that the form is going to post to the /expenses url.  This URL is identical to the index action url of the ExpensesController but you should also notice that the method of the form above is of type post.  Rails maps the plural url and the post method to an action called create that is one of the seven default actions that rails creates for us with every resource we create. 

Another item of noteworthy mention is how the formbuilder has constructed the name fields of the inputs that you can see in the above html.  For example the checkbox for the Paid by Director field has a name attribute of expense[paid_by_director] which has been generated from the check_box method:

=f.check_box :paid_by_director,  { :class => 'check' }

When we submit this form rails will use nesting to nest the paid_by_director attribute inside a hash called expense.  Rails uses this to group the attributes of a single model inside a single hash.

It is also worth noting that for the checkbox, the formbuilder has generated 2 inputs for the f.check_box call.  One input is obviously of type checkbox but the other is a hidden field.  The hidden field is used to record the state of the checkbox when it is posted.  If a checkbox is not checked then it will not appear in the form post collection.  In this case rails will use the value in the hidden field.

When the form is submitted, the form inputs will be bundled into the params hash.

As I have mentioned in the last couple of posts, we are being good little TDD soldiers and because of this, we create the following functional test or controller test to test the create action of the .  I introduced functional testing in this post.

We create the following test to test passing the form fields to the form:




This is exactly the type of hash that gets routed to the create action of our ExpensesController from the above HTML form that is generated from our HAML.

If we want to know exactly what values are being passed to our create action, we can create add the following code to the create action:

Which will display the values of the params hash that is created when the submit button is clicked and should display something like the following in your browser of choice:

Another way of doing this is to change the action to the following:

Here we are raising an exception and calling the to_yaml method of the params hash to display the details of the hash hierarchically:


This will of course cause our test to fail so we will fall back to the original.

We have now tested that our create expense form is hooked up correctly.  We now need to add the code to complete the deed of creating a new expense.  We do this test first.

We update the previously created functional test to the following which is pretty reflective of a full functional test:


We are using flexmock to mock out the ActiveRecord calls as I am not a great believer in writing tests that run against the database.

We mock out the class methods of the Expense object to return exactly what we want to drive our tests in a more logical manner.

We then write the code to make the create action pass:

From the above, you should notice the following:

  1. We are creating a new Expense instance from the params hash that contains the form fields.  We are assigning this new object to the @expense instance variable.  This technique of setting multiple attributes at one time on a model is called mass assignment.
  2. The ActiveRecord save method returns a boolean that indicates whether the save was successful or not.
  3. In the event of a successful save, we are placing a notice in the flash provider and redirecting the index action which we access using the short cut convention expenses_url.  The flash provider is a way to pass temporary objects between actions.   Anything you place in the flash will be exposed to the very next action and then cleared out.  This is a great way of doing notices and alerts.  I seem to remember something similar in Castle.Igloo that later became Rhino.Igloo.
  4. If the save was not successful, we redirect back to the new action.

One problem that is often ignored with mass assignment is that any method can be called from a model that is contained in the params hash including database calls.  In order to prevent this we add the attr_accessible  method to our model and define the methods that we want editable.  To accomplish this, we update the Expense model class:


If we the save is successful, the browser will be redirected to the index action that displays all the Expenses.  We need to update the code to actually render the expenses from the database.

In order to do this, we add a new functional test that checks that the index method runs with records in the database:


Now we update our index.html.haml to the following:



If we successfully insert a record, we are greeted with the following confirmation in the expenses index view:

This post is much longer than I intended so I will leave things here.

In the next post, I will illustrate how to save the Expense as a whole.  This will include the child objects that are part of the complex expense object.






Tuesday, 30 March 2010

Rails - Day 13 -ActiveRecord Relationships Part II

Rails  - Day 1 - The RubyGem Love Story
Rails -  Day 10 - Testing Rails Controllers
Rails -  Day 13 -ActiveRecord Relationships Part II
Rails - Day 15 - Rails Forms Part II
In the last post, we started to define the relationships for a mock expenses tracking application that you can clone from github here.

We are creating a pseudo application to record the expenses that might incur for a small business.

We have created a mock UI below which we are using to drive the structure of the Expense model.



In the last post, we defined how an Expense model object is associated with an ExpenseType model object.

In the screenshot above, you can see that there are 3 inputs for the NetVat and Gross values of every expense that is entered into the system.

An ExpensePayment model object will be created to capture this logic and will be associated with the parent Expense model object. The next step is to generate the files that will aid us in our endeavour of creating an ExpensePayment model with the following command:

ruby script/generate model ExpensePayment  

This generates the following files:


We want to define the usage of this new object before we create the class itself.

The generator has kindly hinted that this a good idea and has created a test/unit/expense_payment_test.rb file which we will update with the following test case to ensure that we can at least store and display the correct payment attributes in the format we expect:



One thing of note is the crazy include ActionView::Helpers statement which appears after the class declaration.  The include method will mixin a module's methods at the instance level that will become methods of the instance.  You can see above that we have 2 calls to number_to_currency at the end of the test case.  The number_to_currency method is mixed in to the ExpensePaymentTest class instance from the ActionView::Helpers module as is defined in the include statement.  Mixins are ridiculously easy in ruby compared to the hoops you have to jump through in C# to achieve a similar experience.  As the methods suggest, they will format the two totals from the ExpensePayment object.

This test will not pass as the ExpensePayment object has not yet been created but as we are using TDD, the behaviour of the object can be defined up front before running the migration.  If we look at the UI at the top of the page, you should see 3 input fields for netvat and gross.  It is safe to say that only net attribute needs persisted to the database as we can derive both the gross and the VAT incurred from the net total.  You can see below how we set this value in the above code with the lines:

payment = ExpensePayment.new

payment.net = 3.23
payment.vat_at_payment = 17.5

We are also storing a vat_at_payment attribute because if you live in a crazy mixed up place like the UK, the VAT rate might vary from month to month as the government tries to recoup all the money it has spent dishing out to banks and waging wars against third world countries.  

We then create the following migration to create the expense_payments table.  The expense_payments table will only contain the net and vat_at_payment fields:



That still leaves the vat and gross attributes which are formatting to assert their values in the above test.  The model is updated to add these attributes:



If we run the above test, it now passes.  We have created a usable ExpensePayment object using the power of TDD.  We should of course create test cases for nil objects but I will leave that as an exercise for you the reader.

belongs_to and has_one newbie Confusion

We now want to define the relationship between Expense and ExpensePayment.

In the last post, we illustrated the ActiveRecord belongs_to relationship.  There is a probably lesser known has_one relationship that to be honest, I had a bit of a problem getting my head around.  Searching the web for answers seemed to suggest this is a bit of a grey area for newbies like myself. The belongs_to relationship seems to be a better fit when linking to pre-existing objects.  For example, in the previous post, it was stated that an Expense belongs_to ExpenseType.  The ExpenseType objects were created before linking the Expense to the ExpenseType.

So in this example, we are going to say that an Expense has_one ExpensePayment.  has_one makes more sense in this scenario because when we create an Expense, we are also creating an ExpensePayment object at the same time.  

As always, we write a test to flesh out our desired behaviour:



Next a migration is created to add the expense_id foreign key to the expense_payments table with the command:

ruby script/generate migration add_expense_id_to_expense_payment


This newly created migration is updated to the following:

The development and test environments are migrated with the following consecutive commands: 

rake db:migrate
rake environment RAILS_ENV=test db:migrate


Then the Expense model is updated to the following:

And lastly the ExpensePayment model is updated to the following:


This slightly confusing and contradictory relationship is now defined.  The tests now pass and we can progress to the UI.

That is it for ActiveRecord relationships which can be slightly ambiguous in places.  I have not mentioned many to many relationships but there are exactly 1,043,293 examples on the web for you to discover. 

Next up, I want to mention forms in Rails.



Rails - Day 13 -ActiveRecord Relationships Part II

Rails -  Day 10 - Testing Rails Controllers
Rails -  Day 12 -ActiveRecord Relationships Part I

In the last post, we started to define the relationships for a mock expenses tracking application that you can clone from github here.

We are creating a pseudo application to record the expenses that might incur for a small business.

We have created a mock UI below which we are using to drive the structure of the Expense model.



In the last post, we defined how an Expense model object is associated with an ExpenseType model object.

In the screenshot above, you can see that there are 3 inputs for the NetVat and Gross values of every expense that is entered into the system.

An ExpensePayment model object will be created to capture this logic and will be associated with the parent Expense model object. The next step is to generate the files that will aid us in our endeavour of creating an ExpensePayment model with the following command:

ruby script/generate model ExpensePayment  

This generates the following files:


We want to define the usage of this new object before we create the class itself.

The generator has kindly hinted that this a good idea and has created a test/unit/expense_payment_test.rb file which we will update with the following test case to ensure that we can at least store and display the correct payment attributes in the format we expect:



One thing of note is the crazy include ActionView::Helpers statement which appears after the class declaration.  The include method will mixin a module's methods at the instance level that will become methods of the instance.  You can see above that we have 2 calls to number_to_currency at the end of the test case.  The number_to_currency method is mixed in to the ExpensePaymentTest class instance from the ActionView::Helpers module as is defined in the include statement.  Mixins are ridiculously easy in ruby compared to the hoops you have to jump through in C# to achieve a similar experience.  As the methods suggest, they will format the two totals from the ExpensePayment object.

This test will not pass as the ExpensePayment object has not yet been created but as we are using TDD, the behaviour of the object can be defined up front before running the migration.  If we look at the UI at the top of the page, you should see 3 input fields for netvat and gross.  It is safe to say that only net attribute needs persisted to the database as we can derive both the gross and the VAT incurred from the net total.  You can see below how we set this value in the above code with the lines:

payment = ExpensePayment.new

payment.net = 3.23
payment.vat_at_payment = 17.5

We are also storing a vat_at_payment attribute because if you live in a crazy mixed up place like the UK, the VAT rate might vary from month to month as the government tries to recoup all the money it has spent dishing out to banks and waging wars against third world countries.  

We then create the following migration to create the expense_payments table.  The expense_payments table will only contain the net and vat_at_payment fields:



That still leaves the vat and gross attributes which are formatting to assert their values in the above test.  The model is updated to add these attributes:



If we run the above test, it now passes.  We have created a usable ExpensePayment object using the power of TDD.  We should of course create test cases for nil objects but I will leave that as an exercise for you the reader.

belongs_to and has_one newbie Confusion

We now want to define the relationship between Expense and ExpensePayment.

In the last post, we illustrated the ActiveRecord belongs_to relationship.  There is a probably lesser known has_one relationship that to be honest, I had a bit of a problem getting my head around.  Searching the web for answers seemed to suggest this is a bit of a grey area for newbies like myself. The belongs_to relationship seems to be a better fit when linking to pre-existing objects.  For example, in the previous post, it was stated that an Expense belongs_to ExpenseType.  The ExpenseType objects were created before linking the Expense to the ExpenseType.

So in this example, we are going to say that an Expense has_one ExpensePayment.  has_one makes more sense in this scenario because when we create an Expense, we are also creating an ExpensePayment object at the same time.  

As always, we write a test to flesh out our desired behaviour:



Next a migration is created to add the expense_id foreign key to the expense_payments table with the command:

ruby script/generate migration add_expense_id_to_expense_payment


This newly created migration is updated to the following:

The development and test environments are migrated with the following consecutive commands: 

rake db:migrate
rake environment RAILS_ENV=test db:migrate


Then the Expense model is updated to the following:

And lastly the ExpensePayment model is updated to the following:


This slightly confusing and contradictory relationship is now defined.  The tests now pass and we can progress to the UI.

That is it for ActiveRecord relationships which can be slightly ambiguous in places.  I have not mentioned many to many relationships but there are exactly 1,043,293 examples on the web for you to discover. 

Next up, I want to mention forms in Rails.



Monday, 29 March 2010

Rails - Day 12 -ActiveRecord Relationships Part I

Rails  - Day 1 - The RubyGem Love Story
Rails -  Day 10 - Testing Rails Controllers
Rails -  Day 13 -ActiveRecord Relationships Part II
Rails - Day 15 - Rails Forms Part II
In the last post, I touched briefly on unit testing and ActiveRecord.

I also mentioned that we are driving the model from the UI that has been created before the model:



I also confessed that the tight coupling to the database which is a result of the ActiveRecord pattern did not make me feel too good but is something I have learned to swallow in the name of productivity.  I will illustrate some of those productivity gains in this post that make the coupling compelling.

In the last post I created a migration and a test to create the expense object.

The Expense model object only encapsulates the Paid by Director, Expense Date, External Doc Ref and Posting Description from the above screenshot.

In this post, we will also create an ExpenseType model object and in the next post we will create an ExpensePayment model object that will be used to record our expense details. 

This is how our database schema should look when when the relationships have been defined:



If you look at the screenshot of the UI at the beginning of the post, you can see that there is an Expense Type dropdown.  Every expense that is created must have an expense type associated with it.  An example of an expense type might be travel costs or office equipment.

The first step is to create the association between expense and expense type.

The characteristics of the  Expense and ExpenseType relationship are:

  • Every Expense will have one ExpenseType associated with it.
  • Each ExpenseType can have many Expenses associated with it.

If you are familiar with Nhibernate, it can be put into the following terms:

  • An expense has a many-to-one relationship with ExpenseType.
  • An ExpenseType will have a one_to_many relationship with a Expenses.

We now need to create an ExpenseType model object.  In order to generate the appropriate model files, the following command is entered into the console:

ruby script/generate model ExpenseType which creates the following files:


Note that it is a model being generated and not a resource, no controller has been created for us and no routing has been updated.

The newly updated migration is updated to incorporate the attributes that will be required to record an expense type:



The db:migrate command will create the expense_types table.  I am not going to show the tests for this creation process, you will just have to take my word for it!! 

In a previous post, I mentioned how it was possible to seed the database with start up data by writing ruby script in the db/seeds.rb file.  In order to seed our database with some expense types, the following code is added to the db/seeds.rb file:


You can see here we are using the ActiveRecord find_or_create_by_name which will check for the existence an ExpenseType with the name that is passed to the function as an argument and if none is found, the record is created.  What you might not realise is that this method does not actually exist and is in fact an example of Ruby/ActiveRecord magic.  ActiveRecord supplies some convenience methods to find records by their attribute values.  These methods are called dynamic finders.  There are two forms of dynamic finder, find_by_xxxx and find_or_create_by_xxxx to create a record if you cannot find it.  If the ExpenseType class had an attribute named code, we could call a method named find_or_create_by_code.  We could also define the two fields to call a method named find_by_name_and_code.  This is fairly mind blowing stuff but when you actually look into the mechanics it seems less surreal.  If you are familiar with Ruby then it probably won't come as a great surprise to learn that this magic is carried out in the ruby catch-all for unknown methods called method_missing:



These posts are not about Ruby but ActiveRecord uses this technique to create many aesthetically pleasing convenience methods that we can utilise in order to both query and execute modifications against the database.  Much of the magic that occurs in Ruby takes place in method_missing.

Getting back to the seeds.rb file, this pseudo method, will create the record in the database if it encounters an unknown value for the name value.  What should not escape your attention that this is all happening in one line of code.  All the plumbing is happening in the framework.  It is examples like this that make me feel less queasy about the tight coupling between the database and the model.

The easiest way to see what records are in the database is to spark up the excellent rails console that runs in the context of our application.  If we enter the following command ruby script/console, we can execute ruby commands in the context of our current project.  Below, you can see I am typing ExpenseType.all to query the expese_types table and display the data that has been added via the seeds.rb file:


ActiveRecord Relationships

So far, we have created the Expense object, and also created and seeded the ExpenseType object but how is the relationship defined between the two objects?  Remember, we are saying that an Expense has one associated Expense Type.

In rails ActiveRecord, the relationship is expresssed as saying that an Expense belongs_to an ExpenseType.  belongs_to specifies a one to one association with another class.  This method should only be used if the class belonging to the other class contains the foreign key.

There is of course a convention for this foreign key relationship that negates the need to specify it anywhere in configuration or code.  The convention is that the foreign key takes the form of the name of the model followed by an underscore and id.  So in this case we will add a new field to the expenses table called expense_type_id.

As I mentioned in the last post, we are driving out our model test first using TDD like the good little ALT.NETters that we are and create the following test:



Obviously, this test will fail as the database schema has not been updated and the relationship has not been defined.

The first step is to create a new migration.  A migration is create with the following command: 

ruby script/generate migration add_expense_type_to_expense
:


The following code is added to the newly created migration file:


I run the migration with the rake db:migrate command.

There is one gotcha that has caught me out more than once and left me howling at the moon and to the Gods.  In a previous post, I mentioned rails environments  When we run the comand rake db:migrate, the migration is ran against the environment we are currently in which more than likely is not the test environment.  To run the migration against the test environment, we can either change environments by entering the command set RAILS_ENV = test or we can complete the task in one line as we are doing below with the command:

 rake environment RAILS_ENV=test db:migrate:


We are not done yet and we need to add some code to our model classes to specify the relationship.

The Expense model class is updated to the following:



The ExpenseType model class is updated to the following:



As aesthetics are really important with rails, the above belongs_to and has_many macros leave little to the imagination as to their true meaning.  

The above test can now be run with the command rake test:units or by by pressing ctrl + F9 in RubyMine.

In RubyMine we get the nice green bar that we all love and cherish:


In the next post, I will illustrate the relationship between the Expense model object and the yet to be created ExpensePayment model object.