Thursday, September 26, 2013

attr_accessible list in rails / Mass assignment


The attr_accessible list is used as a security precaution in certain versions of rails to ensure people can not get access to model variables by modifying form data. If you want to turn off the mass assignment protection in your dev/test environments, you can do so by modifying your environment configuration file in /environments.

Look for  "config.active_record.mass_assignment_sanitizer = :strict"

I don't really think you should need turn this off, but if you are running into mass assignment exceptions with your testing tools you can't resolve by adding attributes to your attr_accessible list, it might be useful.

Simple one to many relationship in ruby on rails

I am pretty new to rails, recently I ran into some confusion about how to make a one to many association in one of my model objects. Where I have many foos, whom all reference one bar.

(Please note, in rails it is common practice to not define foreign keys in the underlying datasource. You define foreign key relations and most object validation in the model objects themselves. )

At first I was trying to use a has_one association so my class looked like this

class Foo < ActiveRecord::Base

  attr_accessible :some_data, :bar_id

  has_one :bar

  validates_presence_of :bar

end

This did not work well, the primary reason being is that has_one refers to a one to one relationship, which is not what I was trying to set up. It turns out that for a one to many we need to use the belongs_to relationship. Each bar has many foos, so each foo belongs to a bar. The rule of thumb is to think of where the foreign key would be defined in the database and that's where the belongs_to relationship should exist. 

Ok, so now I have 

class Foo < ActiveRecord::Base

  attr_accessible :some_data, :bar_id

  belongs_to :bar

  validates_presence_of :bar

end

This is actually the correct version of the code. Although, as I was writing my tests, I had this class defination instead :

class Foo < ActiveRecord::Base

  attr_accessible :some_data, :bar

  belongs_to :bar

  validates_presence_of :bar

end

I had accidentally made the accesible attribute the :bar variable itself, instead of it's associated ID. This works for some simple model tests, but not once you start trying to hook up the controller tests, or a functional form / view with the controller. This is how the default scaffold expects to be able to interact with the object, and probably most of rails. So do yourself a favor and make sure to use :bar_id.