Mark Needham

Thoughts on Software Development

Archive for the ‘active-record’ tag

Active Record: Nested attributes

without comments

I recently learnt about quite a neat feature of Active Record called nested attributes which allows you to save attributes on associated records of a parent model.

It’s been quite useful for us as we have a few pages in our application where the user is able to update models like this.

We would typically end up with parameters coming into the controller like this:

class FoosController < ApplicationController
   def update
      # params = { :id => "1", :foo => { :baz => "new_baz", :bar_attributes => { :value => "something" } } }
      Foo.update_instance(params[:id], params[:foo])
      ...
   end
end

Our original implementation of ‘update_instance’ looked like this:

class Foo < ActiveRecord::Base
   has_one :bar
 
   class << self
      def update_instance(id, attributes_to_update)
         instance = Foo.find(id)
         instance.attributes = attributes_to_update
         instance
      end
   end
end

Unfortunately when we execute that code the ‘bar’ association gets completely removed because we didn’t specify the id of ‘bar’ when we were updating the attributes.

We need to change the code slightly to make sure it doesn’t do that:

class Foo < ActiveRecord::Base
   has_one :bar
 
   class << self
      def update_instance(id, attributes_to_update)
         instance = Foo.find(id)
         attributes_to_update[:bar_attributes][:id] = instance.bar.id
         instance.attributes = attributes_to_update
         instance
      end
   end
end

It now works as we’d expect.

There’s other cool stuff that you can do with nested attributes described on the documentation page if you have ‘has_many’ associations but for now we’re just using the simpler ‘has_one’.

Written by Mark Needham

November 9th, 2010 at 6:37 pm

Posted in Ruby

Tagged with ,

Ruby: Getting Active Record validation errors twice

without comments

I managed to create an interesting problem for myself while playing around with some code whereby I was ending up with validation errors appearing twice every time I called ‘valid?’ on a specific model.

I figured I was probably doing something stupid and in fact a few replies by Aaron Baldwin on a mailing list thread on ‘rubyonrails-talk’ helped explain exactly what I’d done:

Are you calling require ‘employee’ anywhere? If so you are likely
causing the model to load twice which causes duplicate errors because
the validates_presence_of method gets called twice.

I’d put the following code into a controller elsewhere somewhat unnecessarily since it didn’t seem to be picking up the location of my model at the time:

code_submissions_controller.rb

require 'models/code_submission'
 
class CodeSubmissionsController < ApplicationController
  def new
    CodeSubmission.new  
  end
end

require doesn’t load a file if it’s already been included but Aaron points out why it does on this occasion:

You are right that “require” will only load the file once. But if you load the class another way calling “require” will load it again.

As I understand it that controller code would also implicitly require ‘code_submission’ by the convention of inserting an underscore between the ‘CodeSubmission’ constant’s names.

We therefore effectively have the following two requires:

require 'code_submission'
require 'models/code_submission'

Which explain how the file gets loaded twice and therefore why the validation method fires twice and therefore creates two errors!

Written by Mark Needham

October 29th, 2010 at 4:27 am

Posted in Ruby

Tagged with ,