Shawn Shawn - 1 year ago 37
Ruby Question

Can access ActiveRecord object, but not its attributes

I'm rendering a view in Rails using

. Here,
is a record that
has_many :procedure_step_actions
, each of which
belongs_to :error
, which is a
that has (among some relations to other models) an integer
that I'm trying to access and print out to the page. Here's my template:

<%= form_for @procedure_step do |f| %>
<%= f.nested_fields_for :procedure_step_actions do |act| %>
<%= act.object.error.code %>
<% end %>
<% end %>

When I run this, I get
undefined method 'code' for nil:NilClass
. Okay, so my relations are messed up and I can't access
, right? Changing my template to display that instead yields
, which is what one would expect of a functioning relation. Dumping its contents to the screen using
shows all the attributes of the record, including
, but I still can't access it with the original template! Clearly
is not
, so Rails telling me that
doesn't make any sense to me.

Frustrated, I tried to work around the problem by using
. This printed the correct JSON for the record with all its attributes. Using
on this gave me a correct
of all the attributes, but using
to try to access the code gives me
undefined method '[]' for nil:NilClass
. Again, I know that object isn't
, but Rails still refuses to allow me to access it.

Running out of ideas, I tried to use regular expressions to pull the code out of the raw JSON string.
#<MatchData "\"code\":69" 1:"69">
, which is right. I used
to try to access the code number that was matched, but again I got
undefined method '[]' for nil:NilClass

Enough with ActiveRecord, I thought to myself. I decided to turn to raw SQL queries. I got the ID of the error in question using
, then printed that to the screen first to make sure I could access it. Luckily, I could. Then I inserted it into my SQL query with
"... WHERE id = #{act.object.error_id}"
. I refreshed the page again and was greeted with a SQL error. It showed the final SQL query string I had generated, but it ended with
WHERE id =
. The ID of the error didn't get added to the string.
gave a similar error.

I'm totally out of ideas. What could possibly be preventing me from accessing one simple integer in so many different ways?


One thing I can see right off the bat is you are violating Law of Demeter here


The form object obviously has to stay but you can delegate access to the subobjects by making a method on the procedure_step which can help with handling nulls, and other error cases.

Try delegating that first as I'm not sure if the scope that is created by nested_forms_for will allow the ActiveRecord::Relation object to perform properly. I'll double check locally.

A delegation might look like the following

class ProcedureStepActions
   belongs_to :error
   def error_code


Other things that might be helpful are the version of Ruby and Rails you are using and any other additional gems or libraries.