Rails Error Updating Enum on Join Table
Enums in Rails
Rails offers some really useful built-in features for enums which make working with something like enum statuses fairly straightforward.
Like this example from the Rails documentation:
It also gives you ready made scopes which is great because you’ve likely added a status in order to filter records by them anyway.
Issue
With this in mind, I thought this would be a perfect solution to a task of adding a status to an existing system.
For some context, a user in this app has many events through a join table like so:
However, while testing this functionality I kept getting a PG error:
PG::SyntaxError: ERROR: zero-length delimited identifier at or near """" (ActiveRecord::StatementInvalid)
LINE 1: ...rs_events" SET "status" = $1 WHERE "users_events"."" IS NULL
Thinking this was because I was using the in built .approved!
methods, I tried using .update(status: :approved)
and even tried explicitly setting an integer value. Not having all the rails enum methods wouldn’t be ideal but at least it’d work right?
Still got the same error. If I switched to doing a .status = 1
and .save
I wouldn’t get an error but the record obviously wouldn’t be updated.
Solution
I couldn’t find anything online about this issue, which is partly the reason for writing this post.
Because I’d used enums like this elsewhere in this app, I suspected this was something to do with the fact that I was adding the status to a joins table.
Looking back at the migrations showed that rails had created the table with a user_id and event_id, this works perfectly for doing things like user.events
etc. but I guessed that the absence of a primary key was somehow eluding the ActiveRecord where sql queries and causing the error as it was looking for an id on the users_events table.
To test this theory I retroactively added in a primary key:
But I had the same error.
As it turns out, although the model now had a primary id, rails was still ignoring it and treating it as a standard joins table (why wouldn’t it?).
To fix this I had to explicitly set it in the model.
And finally everything worked, including all the fancy rails enum methods too.
I’m not sure if this was the best solution to the problem or if this was the wrong way to structure things but it fixed my issue.
Feel free to reach out if you know more on this or have any feedback on this approach!