AttrJson::Associations

A simple association extension for attr_json.

Dependencies

  • ruby 2.7+
  • attr_json 1.3
  • activerecord 6.0+
  • activesupport 6.0+

Installation

Add this line to your application's Gemfile:

gem 'attr_json-associations'

Then execute:

$ bundle

Usage

Include AttrJson::Associations, and define associations using attr_json_belongs_to and attr_json_has_many. You may specify attributes defined with attr_json as a primary key or a foreign key. For example:

class Group < ActiveRecord::Base
  include AttrJson::Record
  include AttrJson::Record::QueryScopes
  include AttrJson::Associations

  attr_json_has_many :users
end

class User < ActiveRecord::Base
  include AttrJson::Record
  include AttrJson::Record::QueryScopes
  include AttrJson::Associations

  attr_json_config(default_container_attribute: :data)

  attr_json :group_id, :integer
  attr_json_belongs_to :group
end

These associations generates queries as follows:

Group.new(id: 1).users
#=> SELECT "users".* FROM "users" WHERE ("users"."data"->'group_id' = '1')

User.new(group_id: 1).group
#=> SELECT "groups".* FROM "groups" WHERE "groups"."id" = 1

Options

You can speficy the following options for association definitions:

  • class_name
  • primary_key
  • foreign_key

These options are same as ActiveRecord. For example:

class Group < ActiveRecord::Base
  include AttrJson::Record
  include AttrJson::Record::QueryScopes
  include AttrJson::Associations

  attr_json_has_many :users, class_name: 'User', primary_key: :id, foreign_key: :group_id
end

You can also specify an additional scope for each association:

class Group < ActiveRecord::Base
  include AttrJson::Record
  include AttrJson::Record::QueryScopes
  include AttrJson::Associations

  attr_json_has_many :users, -> { order(:id) }
end

Group.new(id: 1).users
#=> SELECT "users".* FROM "users" WHERE ("users"."data"->'group_id' = '1') ORDER BY "users"."id" ASC

Array type

You can define attr_json_belongs_to for an array attribute. For example:

class Array::User < ActiveRecord::Base
  include AttrJson::Record
  include AttrJson::Record::QueryScopes
  include AttrJson::Associations

  attr_json_config(default_container_attribute: :data)

  attr_json :group_ids, :integer, array: true
  attr_json_belongs_to :groups
end

Array::User.new(group_ids: [1, 2]).groups
#=> SELECT "groups".* FROM "groups" WHERE "groups"."id" IN (1, 2) ORDER BY CASE "groups"."id" WHEN 1 THEN 0 WHEN 2 THEN 1 ELSE 2 END

Array::User.new(group_ids: [2, 1]).groups
#=> SELECT "groups".* FROM "groups" WHERE "groups"."id" IN (2, 1) ORDER BY CASE "groups"."id" WHEN 2 THEN 0 WHEN 1 THEN 1 ELSE 2 END

Note that the returned records are ordered by the index of the array, so the order of records in first example is different from the one in second example.

Limitations

This gem is experimental so the various options like ActiveRecord's things are not supported.

Contributing

Bug reports and pull requests are welcome at https://github.com/kanety/attr_json-associations.

License

The gem is available as open source under the terms of the MIT License.