active_record-json_associations 0.13.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d0210b855faca7f7e383b01be2e5e7fb6f78a24770fc5456f6fe6661e3862d2
4
- data.tar.gz: 95abf57fc202bb226e8c3dd01c018c489c21ed47c3e00fbd1fc920b0df8f7856
3
+ metadata.gz: 0425a5d0c7935d72007daa4961178471c58a88dac30522a9137e89923f158dbd
4
+ data.tar.gz: cfbc21cae4d8655ad0c62c2a73c95715d6207f882e3de6433dc079abc3eff9d9
5
5
  SHA512:
6
- metadata.gz: d396317afb6cb24bccf06d8f7d9a773f8b76ca65e117d9194230c9378804eeb26f9eb608b26e7240fa0de45e5292f03b6170e544473bfb77621d695a7a0cc887
7
- data.tar.gz: 72cc81817ebb6f46f4d82a446f1a17235d60ca701f43300aa23425d2bbd298d5119587ad407eaaf441c74dca0a68aa0d58483b42ef315e064eacb4fe869f8784
6
+ metadata.gz: 15b8f1ea8aebceea06a143635cfb8242fec793f319196d1af11e90a5dbc77bbc68e43d08ff6e9c893d94f79180bb9d1f11db2bf8c4a6f3048e2c870a9f70cffc
7
+ data.tar.gz: 2862a70dfb5c0db59dbf30facb73f0c5d810e7c4c00404c5c5eb74daf7aa6c1cacdca86560db5727b1c7e6537f3d0d3bdea2515837c4af0ee3a18b4a5b680fb4
@@ -1,21 +1,57 @@
1
1
  name: CI
2
+
2
3
  on: [push, pull_request]
4
+
3
5
  jobs:
4
6
  test:
7
+ runs-on: ubuntu-latest
5
8
  strategy:
6
9
  fail-fast: false
7
10
  matrix:
8
- gemfile: [ rails_7.0, rails_7.1, rails_7.2 ]
9
- ruby: [ 3.1, 3.2, 3.3 ]
10
-
11
- runs-on: ubuntu-latest
12
- env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
13
- BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
11
+ ruby: ["3.2", "3.3", "3.4", "4.0"]
12
+ gemfile:
13
+ - gemfiles/rails_7.2.gemfile
14
+ - gemfiles/rails_8.0.gemfile
15
+ - gemfiles/rails_8.1.gemfile
16
+ database: [sqlite, postgres, mysql]
17
+ services:
18
+ postgres:
19
+ image: postgres:16
20
+ env:
21
+ POSTGRES_PASSWORD: postgres
22
+ options: >-
23
+ --health-cmd pg_isready
24
+ --health-interval 10s
25
+ --health-timeout 5s
26
+ --health-retries 5
27
+ ports:
28
+ - 5432:5432
29
+ mysql:
30
+ image: mysql:8
31
+ env:
32
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
33
+ options: >-
34
+ --health-cmd "mysqladmin ping"
35
+ --health-interval 10s
36
+ --health-timeout 5s
37
+ --health-retries 5
38
+ ports:
39
+ - 3306:3306
40
+ env:
41
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
14
42
  steps:
15
- - uses: actions/checkout@v2
43
+ - uses: actions/checkout@v4
16
44
  - uses: ruby/setup-ruby@v1
17
45
  with:
18
46
  ruby-version: ${{ matrix.ruby }}
19
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
20
- - run: bundle exec rake
21
-
47
+ bundler-cache: true
48
+ - name: Create test database
49
+ if: matrix.database == 'postgres'
50
+ run: PGPASSWORD=postgres createdb -h localhost -U postgres test
51
+ - name: Create test database
52
+ if: matrix.database == 'mysql'
53
+ run: mysql -h 127.0.0.1 -u root -e "CREATE DATABASE test"
54
+ - name: Run tests
55
+ run: bundle exec rake
56
+ env:
57
+ DATABASE_URL: ${{ matrix.database == 'postgres' && 'postgres://postgres:postgres@localhost:5432/test' || matrix.database == 'mysql' && 'trilogy://root@127.0.0.1:3306/test' || 'sqlite3::memory:' }}
data/Appraisals CHANGED
@@ -1,13 +1,11 @@
1
- appraise "rails-7.0" do
2
- gem "rails", "~>7.0.0"
3
- gem "sqlite3", "~>1.0"
1
+ appraise "rails-7.2" do
2
+ gem "rails", "~>7.2.0"
4
3
  end
5
4
 
6
- appraise "rails-7.1" do
7
- gem "rails", "~>7.1.0"
5
+ appraise "rails-8.0" do
6
+ gem "rails", "~>8.0.0"
8
7
  end
9
8
 
10
- appraise "rails-7.2" do
11
- gem "rails", "~>7.2.0"
9
+ appraise "rails-8.1" do
10
+ gem "rails", "~>8.1.0"
12
11
  end
13
-
data/CLAUDE.md ADDED
@@ -0,0 +1,38 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## About
6
+
7
+ ActiveRecord::JsonAssociations is a Ruby gem that provides an alternative to traditional many-to-many join tables by storing foreign keys in a JSON array on the parent record.
8
+
9
+ ## Development Commands
10
+
11
+ ```bash
12
+ # Run all tests
13
+ bundle exec rake
14
+
15
+ # Run a single spec file
16
+ bundle exec rspec spec/belongs_to_many_spec.rb
17
+
18
+ # Run a specific test by line number
19
+ bundle exec rspec spec/belongs_to_many_spec.rb:42
20
+
21
+ # Test against specific Rails versions using Appraisal
22
+ BUNDLE_GEMFILE=gemfiles/rails_7.1.gemfile bundle exec rake
23
+ BUNDLE_GEMFILE=gemfiles/rails_8.0.gemfile bundle exec rake
24
+ ```
25
+
26
+ ## Architecture
27
+
28
+ The gem extends `ActiveRecord::Base` with a single module (`ActiveRecord::JsonAssociations`) that provides two main class methods:
29
+
30
+ - **`belongs_to_many`** - Stores foreign keys as a JSON array in a text/json column on the parent model. Provides `children`, `children=`, `child_ids`, `child_ids=`, `children?` methods plus a `child_ids_including` scope for querying.
31
+
32
+ - **`has_many :json_foreign_key`** - The inverse relationship. When a child model uses this option, it can find parents that reference it via their JSON arrays. Also provides `build_parent`, `create_parent`, `create_parent!` builder methods.
33
+
34
+ Both methods support native JSON columns (using `JSON_CONTAINS`) or text columns (using `LIKE` queries with serialized JSON).
35
+
36
+ ## Testing
37
+
38
+ Tests use RSpec with an in-memory SQLite database. Each spec file sets up its own schema and model classes. Use `focus: true` on individual specs during development.
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # ActiveRecord::JsonAssociations
2
2
 
3
3
  [![CI Status](https://github.com/botandrose/active_record-json_associations/actions/workflows/ci.yml/badge.svg)](https://github.com/botandrose/active_record-json_associations/actions/workflows/ci.yml)
4
- [![Code Climate](https://codeclimate.com/github/botandrose/active_record-json_associations/badges/gpa.svg)](https://codeclimate.com/github/botandrose/active_record-json_associations)
5
4
 
6
5
  Instead of keeping the foreign keys on the children, or in a many-to-many join table, let's keep them in a JSON array on the parent.
7
6
 
@@ -12,7 +11,7 @@ require "active_record/json_associations"
12
11
 
13
12
  ActiveRecord::Schema.define do
14
13
  create_table :parents do |t|
15
- t.text :child_ids
14
+ t.json :child_ids, default: []
16
15
  end
17
16
 
18
17
  create_table :children
@@ -23,6 +22,8 @@ class Parent < ActiveRecord::Base
23
22
  end
24
23
  ```
25
24
 
25
+ **Note:** The `child_ids` column must be a native JSON type. Text columns are not supported.
26
+
26
27
  This will add some familiar `has_many`-style methods:
27
28
 
28
29
  ```ruby
@@ -37,16 +38,16 @@ parent.child_ids #=> [1,2]
37
38
  parent.children? #=> true
38
39
  ```
39
40
 
40
- And a scope method for finding records assocatied with an id:
41
+ And a scope method for finding records associated with an id:
41
42
 
42
43
  ```ruby
43
44
  Parent.child_ids_including(2) # => [<Parent child_ids: [1,2,3]>]
44
45
  ```
45
46
 
46
- Or any of specified array of ids:
47
+ Or any of a specified array of ids:
47
48
 
48
49
  ```ruby
49
- Parent.child_ids_including([2,4,5]) # => [<Parent child_ids: [1,2,3]>]
50
+ Parent.child_ids_including(any: [2,4,5]) # => [<Parent child_ids: [1,2,3]>]
50
51
  ```
51
52
 
52
53
  `touch: true` can be specified on belongs_to_many to touch the associated records' timestamps when the record is modified.
@@ -77,7 +78,9 @@ child.build_parent(name: "Momma")
77
78
 
78
79
  ## Requirements
79
80
 
80
- * ActiveRecord 5.0+
81
+ * Ruby 3.2+
82
+ * ActiveRecord 7.2+
83
+ * Database with JSON column support (MySQL, PostgreSQL, SQLite 3.9+)
81
84
 
82
85
  ## Contributing
83
86
 
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = %q{Instead of a many-to-many join table, serialize the ids into a JSON array.}
13
13
  spec.homepage = "https://github.com/botandrose/active_record-json_associations"
14
14
  spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.2"
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0")
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -25,6 +26,8 @@ Gem::Specification.new do |spec|
25
26
  spec.add_development_dependency "rake"
26
27
  spec.add_development_dependency "rspec"
27
28
  spec.add_development_dependency "sqlite3"
29
+ spec.add_development_dependency "pg"
30
+ spec.add_development_dependency "trilogy"
28
31
  spec.add_development_dependency "byebug"
29
32
  spec.add_development_dependency "timecop"
30
33
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~>7.1.0"
5
+ gem "rails", "~>8.0.0"
6
6
 
7
7
  gemspec path: "../"
@@ -2,7 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~>7.0.0"
6
- gem "sqlite3", "~>1.0"
5
+ gem "rails", "~>8.1.0"
7
6
 
8
7
  gemspec path: "../"
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module JsonAssociations
3
- VERSION = "0.13.1"
3
+ VERSION = "1.0.0"
4
4
  end
5
5
  end
@@ -1,18 +1,44 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record"
2
4
  require "json"
3
5
 
4
6
  module ActiveRecord
5
7
  module JsonAssociations
8
+ ORDER_BY_IDS_PROC = proc do |scope, ids|
9
+ if ids.empty?
10
+ scope
11
+ else
12
+ pk = scope.klass.primary_key
13
+ quoted_ids = ids.map { |id| scope.connection.quote(id) }
14
+ order_sql = case scope.connection.adapter_name
15
+ when "Mysql2", "Trilogy"
16
+ "FIELD(#{pk}, #{quoted_ids.join(",")})"
17
+ when "PostgreSQL"
18
+ "array_position(ARRAY[#{quoted_ids.join(",")}], #{pk})"
19
+ else
20
+ fragments = ids.each_with_index.map { |id, i| "WHEN #{quoted_ids[i]} THEN #{i}" }
21
+ "CASE #{pk} #{fragments.join(" ")} END"
22
+ end
23
+ scope.order!(Arel.sql(order_sql))
24
+ end
25
+ end
26
+ private_constant :ORDER_BY_IDS_PROC
27
+
6
28
  FIELD_INCLUDE_SCOPE_BUILDER_PROC = proc do |context, field, id|
7
- using_json = context.columns_hash[field.to_s].type == :json
29
+ unless context.columns_hash[field.to_s].type == :json
30
+ raise ArgumentError, "#{field} column must be of type :json"
31
+ end
32
+
33
+ sanitized_id = id.to_i
8
34
 
9
- if using_json
10
- context.where("JSON_CONTAINS(#{field}, ?, '$')", id.to_json)
35
+ case context.connection.adapter_name
36
+ when "Mysql2", "Trilogy"
37
+ context.where("JSON_CONTAINS(#{field}, ?, '$')", sanitized_id.to_json)
38
+ when "PostgreSQL"
39
+ context.where("#{field}::jsonb @> ?::jsonb", [sanitized_id].to_json)
11
40
  else
12
- context.where("#{field}='[#{id}]'").or(
13
- context.where("#{field} LIKE '[#{id},%'")).or(
14
- context.where("#{field} LIKE '%,#{id},%'")).or(
15
- context.where("#{field} LIKE '%,#{id}]'"))
41
+ context.where("EXISTS (SELECT 1 FROM json_each(#{field}) WHERE value = ?)", sanitized_id)
16
42
  end
17
43
  end
18
44
  private_constant :FIELD_INCLUDE_SCOPE_BUILDER_PROC
@@ -26,34 +52,16 @@ module ActiveRecord
26
52
 
27
53
  class_name ||= one.classify
28
54
 
29
- using_json = columns_hash[one_ids.to_s].type == :json
30
-
31
- if !using_json
32
- if ActiveRecord.version >= Gem::Version.new("7.1")
33
- serialize one_ids, coder: JSON
34
- else
35
- serialize one_ids, JSON
36
- end
55
+ unless columns_hash[one_ids.to_s].type == :json
56
+ raise ArgumentError, "#{one_ids} column must be of type :json"
37
57
  end
38
58
 
39
59
  if touch
40
60
  after_commit do
41
61
  unless no_touching?
42
- method = respond_to?(:saved_changes) ? :saved_changes : :previous_changes
43
- old_ids, new_ids = send(method)[one_ids.to_s]
62
+ old_ids, new_ids = saved_changes[one_ids.to_s]
44
63
  ids = Array(send(one_ids)) | Array(old_ids) | Array(new_ids)
45
- scope = class_name.constantize.where(self.class.primary_key => ids)
46
-
47
- if scope.respond_to?(:touch) # AR 6.0+
48
- scope.touch_all
49
- elsif self.class.respond_to?(:touch_attributes_with_time) # AR 5.1+
50
- scope.update_all self.class.touch_attributes_with_time
51
- else # AR 5.0
52
- attributes = timestamp_attributes_for_update_in_model.inject({}) do |attributes, key|
53
- attributes.merge(key => current_time_from_proper_timezone)
54
- end
55
- scope.update_all attributes
56
- end
64
+ class_name.constantize.where(self.class.primary_key => ids).touch_all
57
65
  end
58
66
  end
59
67
  end
@@ -84,16 +92,9 @@ module ActiveRecord
84
92
 
85
93
  define_method many do
86
94
  klass = class_name.constantize
87
- scope = klass.all
88
-
89
- ids = send(one_ids)
90
- scope.where!(klass.primary_key => ids)
91
-
92
- fragments = []
93
- fragments += ["#{klass.primary_key} NOT IN (#{ids.map(&:to_s).join(",")})"] if ids.any?
94
- fragments += ids.reverse.map { |id| "#{klass.primary_key}=#{id}" }
95
- order_by_ids = fragments.join(", ")
96
- scope.order!(Arel.sql(order_by_ids))
95
+ ids = send(one_ids).map(&:to_i)
96
+ scope = klass.where(klass.primary_key => ids)
97
+ ORDER_BY_IDS_PROC.call(scope, ids)
97
98
  end
98
99
 
99
100
  define_method many_equals do |collection|
@@ -126,30 +127,43 @@ module ActiveRecord
126
127
  create_one_bang = :"create_#{one}!"
127
128
 
128
129
  class_name = options[:class_name] || one.classify
129
- klass = class_name.constantize
130
130
 
131
131
  foreign_key = options[:json_foreign_key]
132
132
  foreign_key = :"#{model_name.singular}_ids" if foreign_key == true
133
133
 
134
+ pending_associations_var = :"@pending_#{many}"
135
+
136
+ after_create do
137
+ if (pending = instance_variable_get(pending_associations_var))
138
+ instance_variable_set(pending_associations_var, nil)
139
+ send(many_equals, pending)
140
+ end
141
+ end
142
+
134
143
  include Module.new {
135
144
  define_method one_ids do
136
145
  send(many).pluck(:id)
137
146
  end
138
147
 
139
148
  define_method one_ids_equals do |ids|
149
+ klass = class_name.constantize
140
150
  normalized_ids = Array(ids).select(&:present?).map(&:to_i).uniq
141
151
  send many_equals, klass.find(normalized_ids)
142
152
  end
143
153
 
144
154
  define_method many do
155
+ klass = class_name.constantize
145
156
  FIELD_INCLUDE_SCOPE_BUILDER_PROC.call(klass, foreign_key, id)
146
157
  end
147
158
 
148
159
  define_method many_equals do |collection|
149
- collection.each do |record|
150
- new_id_array = Array(record.send(foreign_key)) | [id]
151
- raise "FIXME: Cannot assign during creation, because no id has yet been reified." if new_id_array.any?(&:nil?)
152
- record.update foreign_key => new_id_array
160
+ if new_record?
161
+ instance_variable_set(pending_associations_var, collection)
162
+ else
163
+ collection.each do |record|
164
+ new_id_array = Array(record.send(foreign_key)) | [id]
165
+ record.update foreign_key => new_id_array
166
+ end
153
167
  end
154
168
  end
155
169
 
@@ -158,14 +172,17 @@ module ActiveRecord
158
172
  end
159
173
 
160
174
  define_method build_one do |attributes={}|
175
+ klass = class_name.constantize
161
176
  klass.new attributes.merge!(foreign_key => [id])
162
177
  end
163
178
 
164
179
  define_method create_one do |attributes={}|
180
+ klass = class_name.constantize
165
181
  klass.create attributes.merge!(foreign_key => [id])
166
182
  end
167
183
 
168
184
  define_method create_one_bang do |attributes={}|
185
+ klass = class_name.constantize
169
186
  klass.create! attributes.merge!(foreign_key => [id])
170
187
  end
171
188
  }
@@ -2,23 +2,22 @@ require "active_record/json_associations"
2
2
 
3
3
  describe ActiveRecord::JsonAssociations do
4
4
  before do
5
- ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
5
+ ActiveRecord::Base.establish_connection database_config
6
6
 
7
7
  silence_stream(STDOUT) do
8
8
  ActiveRecord::Schema.define do
9
- create_table :parents do |t|
9
+ create_table :parents, force: true do |t|
10
10
  t.string :name
11
- t.text :child_ids
12
- t.text :fuzzy_ids
13
- t.json :dependent_types_and_ids
11
+ t.json :child_ids
12
+ t.json :fuzzy_ids
14
13
  t.timestamps
15
14
  end
16
15
 
17
- create_table :children do |t|
16
+ create_table :children, force: true do |t|
18
17
  t.timestamps
19
18
  end
20
19
 
21
- create_table :pets do |t|
20
+ create_table :pets, force: true do |t|
22
21
  t.timestamps
23
22
  end
24
23
  end
@@ -2,22 +2,22 @@ require "active_record/json_associations"
2
2
 
3
3
  describe ActiveRecord::JsonAssociations do
4
4
  before do
5
- ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
5
+ ActiveRecord::Base.establish_connection database_config
6
6
 
7
7
  silence_stream(STDOUT) do
8
8
  ActiveRecord::Schema.define do
9
- create_table :parents do |t|
9
+ create_table :parents, force: true do |t|
10
10
  t.string :name
11
- t.text :child_ids
12
- t.text :fuzzy_ids
11
+ t.json :child_ids
12
+ t.json :fuzzy_ids
13
13
  t.timestamps
14
14
  end
15
15
 
16
- create_table :children do |t|
16
+ create_table :children, force: true do |t|
17
17
  t.timestamps
18
18
  end
19
19
 
20
- create_table :pets do |t|
20
+ create_table :pets, force: true do |t|
21
21
  t.timestamps
22
22
  end
23
23
  end
@@ -87,6 +87,14 @@ describe ActiveRecord::JsonAssociations do
87
87
  expect(subject.parents).to eq parents
88
88
  end
89
89
 
90
+ it "defers assignment until after create for new records" do
91
+ child = Child.new
92
+ child.parents = parents
93
+ expect(parents.map { |p| p.reload.child_ids }).to eq [[], [], []]
94
+ child.save!
95
+ expect(parents.map { |p| p.reload.child_ids }).to eq [[child.id], [child.id], [child.id]]
96
+ end
97
+
90
98
  context "finds records with the specified id" do
91
99
  let(:child) { Child.create! }
92
100
 
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  require "byebug"
2
2
  require "timecop"
3
3
 
4
+ def database_config
5
+ if ENV["DATABASE_URL"]
6
+ { url: ENV["DATABASE_URL"] }
7
+ else
8
+ { adapter: "sqlite3", database: ":memory:" }
9
+ end
10
+ end
11
+
4
12
  RSpec.configure do |config|
5
13
  config.filter_run focus: true
6
14
  config.run_all_when_everything_filtered = true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record-json_associations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micah Geisel
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-15 00:00:00.000000000 Z
11
+ date: 2026-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pg
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: trilogy
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: byebug
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -134,15 +162,16 @@ files:
134
162
  - ".gitignore"
135
163
  - ".rspec"
136
164
  - Appraisals
165
+ - CLAUDE.md
137
166
  - Gemfile
138
167
  - LICENSE.txt
139
168
  - README.md
140
169
  - Rakefile
141
170
  - active_record-json_associations.gemspec
142
171
  - bin/setup
143
- - gemfiles/rails_7.0.gemfile
144
- - gemfiles/rails_7.1.gemfile
145
172
  - gemfiles/rails_7.2.gemfile
173
+ - gemfiles/rails_8.0.gemfile
174
+ - gemfiles/rails_8.1.gemfile
146
175
  - lib/active_record/json_associations.rb
147
176
  - lib/active_record/json_associations/version.rb
148
177
  - spec/belongs_to_many_spec.rb
@@ -152,7 +181,7 @@ homepage: https://github.com/botandrose/active_record-json_associations
152
181
  licenses:
153
182
  - MIT
154
183
  metadata: {}
155
- post_install_message:
184
+ post_install_message:
156
185
  rdoc_options: []
157
186
  require_paths:
158
187
  - lib
@@ -160,7 +189,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
189
  requirements:
161
190
  - - ">="
162
191
  - !ruby/object:Gem::Version
163
- version: '0'
192
+ version: '3.2'
164
193
  required_rubygems_version: !ruby/object:Gem::Requirement
165
194
  requirements:
166
195
  - - ">="
@@ -168,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
197
  version: '0'
169
198
  requirements: []
170
199
  rubygems_version: 3.5.11
171
- signing_key:
200
+ signing_key:
172
201
  specification_version: 4
173
202
  summary: Instead of a many-to-many join table, serialize the ids into a JSON array.
174
203
  test_files: