Search code examples
ruby-on-railsactiverecordruby-on-rails-5acts-as-taggable-onacts-as-taggable

Rails model #attributes method shows gem inserted association as model attribute


I am upgrading a Rails 4.2 application to Rails Version 5.2. We are using the acts_as_taggable_on gem (version changed from 4 to 6) for tagging functionality.

Let's say I have a model called Task. If I do Task.new, I get the below initialized object.

=> #<Task:0x00003fh7398rcg3
 id: nil,
 title: nil,
 description: nil,
 creator_id: nil,
 due_date: nil
 status: "active",
 created_at: nil, 
 updated_at: nil>

If I do Task.new.attributes, I get

 {"id"=>"nil,
 "title"=>"nil,
 "description"=>"nil,
 "creator_id"=>"nil,
 "due_date"=>"nil
 "status"=>""active",
 "created_at"=>"nil, 
 "updated_at"=>"nil,
 "tag_list"=>nil}

This tag_list is coming from the gem and is expected to be used to set and update the associated tags.

On Rails 4.2, the behavior is as expected. On Rails 5.2, since this add-on attribute shows up as a model attribute, it causes unexpected problems at multiple places.

I went looking and saw that there are changes to ActiveRecord::ModelSchema that may be the cause.

While I was doing that, I did a force-load schema on the Task model.

Task.send(:load_schema!)

Output:

{
"id"=>#<ActiveRecord::Type::UnsignedInteger:0x00007fc89f01d780 @limit=4, @precision=nil, @range=0...4294967296, @scale=nil>,
"title"=>#<ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlString:0x00007fc89f0245f8 @limit=610, @precision=nil, @scale=nil>,
"description"=>#<ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlString:0x00007fc8ab906d40 @limit=1000, @precision=nil, @scale=nil>,
"creator_id"=>#<ActiveRecord::Type::UnsignedInteger:0x00007fc89f01d780 @limit=4, @precision=nil, @range=0...4294967296, @scale=nil>,
"due_date"=>#<ActiveRecord::Type::DateTime:0x00007fc8ab90a5d0 @limit=nil, @precision=0, @scale=nil>,
"status"=>#<ActiveRecord::Enum::EnumType:0x00007fc8a0341870 @mapping={"active"=>0, 
"complete"=>1}, @name="status", ,@scale=nil>,@subtype=#<ActiveModel::Type::Integer:0x00007fc8ab908370 @limit=1, @precision=nil, @range=-128...128, @scale=nil>>,
"created_at"=>#<ActiveRecord::Type::DateTime:0x00007fc8ab90a5d0 @limit=nil, @precision=0, @scale=nil>,
"updated_at"=>#<ActiveRecord::Type::DateTime:0x00007fc8ab90a5d0 @limit=nil, @precision=0, @scale=nil>
"tag_list"=>#<ActsAsTaggableOn::Taggable::TagListType:0x00007fc89fe9e840 @limit=nil, @precision=nil, @scale=nil>
}

When I try to see the default attributes by doing Task._default_attributes, I still see the tag_list attribute.

   "tag_list"=>
    #<ActiveModel::Attribute::WithCastValue:0x00007fc8a03409c0
     @name="tag_list",
     @original_attribute=nil,
     @type=#<ActsAsTaggableOn::Taggable::TagListType:0x00007fc89fe9e840 @limit=nil, @precision=nil, @scale=nil>,
     @value_before_type_cast=nil>}>

tag_list is definitely not on the model schema, but it is shown as such anyways.

I am stumped how to address this. Appreciate any help!


Solution

  • The gem is causing this, since you upgraded 2 major versions a lot of changes were made. Possibly this line is causing it https://github.com/mbleigh/acts-as-taggable-on/blob/950c01072b7ab6227d74dc0d0b112f0135281fc2/lib/acts_as_taggable_on/taggable/core.rb#L42. Your options are to either change your code to support this change or try running the older gem version if it supports Rails 5.