active_record-any_links 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5d991efbc26c4de04ea6203b73356fdb35806afd
4
+ data.tar.gz: cb1a9f0466c18907fd4ff35fb5a3264310279ea4
5
+ SHA512:
6
+ metadata.gz: bf656d93c9a5cda2cc9e8996df81a93fa41e7193c6427a739b32f2c9a7db1b13f22fb92bb60b4fdf7021877c9ef069f684594af76fb673f344d90bf44ba45c83
7
+ data.tar.gz: f47fcedc79318c8700c5952bc3fa0b1d78306a2f2184e35a2d947ba37b1af78e2685e19c3a6a67fe194bb3d62df8deb72e806e802cd5477f50415058cbcc1d3d
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.14.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in active_record-any_links.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017, Samanage
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,209 @@
1
+ # AnyLinks
2
+
3
+ AnyLinks is an ActiveRecord extension which enables simple linking any model to any other model.
4
+
5
+ It requires a single table holding the connection of all types, and a single statement for each linked model.
6
+ No pass-through model required.
7
+
8
+ The links can be many-to-many or one-to-many, and can link
9
+ also any model to itself, with bidirectional connection.
10
+
11
+ It is a simple-to-use extension to the polymorphic schema, but without the complexity and with much more capabilities.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'active_record-any_links'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install active_record-any_links
28
+
29
+ ## Getting Started
30
+
31
+ ### 1. Create any_links table
32
+
33
+ AnyLinks requires an any_links table to store the links.
34
+ You can create the table by adding the following migration, and running:
35
+
36
+ ```ruby
37
+ rake db:migrate
38
+ ```
39
+
40
+ ```ruby
41
+ class CreateAnyLinks < ActiveRecord::Migration
42
+ def up
43
+ create_table :any_links do |t|
44
+ t.integer :id1, null: false
45
+ t.string :type1, null: false
46
+ t.integer :id2, null: false
47
+ t.string :type2, null: false
48
+
49
+ t.timestamps
50
+ end
51
+
52
+ change_table :any_links do |t|
53
+ t.index [:id1, :type1, :id2, :type2], unique: true
54
+ t.index [:id1, :type1, :type2]
55
+ t.index [:id2, :type2, :type1]
56
+ end
57
+ end
58
+
59
+ def down
60
+ drop_table :any_links
61
+ end
62
+ end
63
+ ```
64
+
65
+ ### 2. Linking models
66
+
67
+ In the following example we link the User model to Group model, using many to many relationship.
68
+
69
+ ```ruby
70
+ class User < ActiveRecord::Base
71
+ has_many_to_many :groups
72
+ end
73
+
74
+ class Group < ActiveRecord::Base
75
+ has_many_to_many :users
76
+ end
77
+ ```
78
+ ### 3. Using the linked models
79
+
80
+ Use the linked models the same way you use any has_many relationship.
81
+ examples:
82
+
83
+ ```ruby
84
+ @user.groups = [group, group]
85
+ @group.user_ids # => [4,7,9]
86
+ @group.users.exists?
87
+ @group.users.where(first_name: "James")
88
+ ```
89
+
90
+ ## AnyLinks statements
91
+
92
+ There are three statements added to ActiveRecord:
93
+
94
+ ```ruby
95
+ has_many_to_many
96
+ has_many_to_one
97
+ has_one_to_many
98
+ ```
99
+
100
+ Each one of them creates a bundle of helper methods.
101
+
102
+ ## has_many_to_many
103
+
104
+ has_many_to_many Specifies a many-to-many bi-directional association.
105
+ Regularly, has_many_to_many is declared in each side of the association models.
106
+ It will also work if declared only on one side of the association. However, doing so will
107
+ not generate the dynamic methods on the other side, making the connections seen from
108
+ one side only
109
+
110
+ has_many_to_many can be used even on the same model:
111
+
112
+ ```ruby
113
+ class User < ActiveRecord::Base
114
+ has_many_to_many :friends, class_name: User
115
+ end
116
+ ```
117
+
118
+ The previous link is also bidirectional!
119
+ The associations, for all types and collections, are stored together in a single table called 'any_links'.
120
+ The table contain all links between all instances of any type.
121
+ Every record represent a link, which contains id and type for each side of the connection,
122
+ which are called id1, type1, and id2, type2 respectively.
123
+ Since the links are bi-directional, theoretically, any object can be represented as the left
124
+ side link (#1) or right side (#2).
125
+ For simplicity and performance, the links are stored thus the "smallest" type is in the left.
126
+ Any link betwwen 'Incident' and 'Change' is stored as the Change object in the left, since
127
+ the string types are 'Change' < 'Incident'.
128
+ This technique is 'Hidden' and transparent for the has_many_to_many consumer.
129
+
130
+ For association of the same type - (e.g. `Incident has_many incidents`):
131
+ do standard declaration in the Class (i.e. has_many_to_many <collection>).
132
+ In that case, a callbacks of after create and after destroy shall be called in the relevant any_link class.
133
+ To overcome association methods that skip callbacks (as clear method) we override the delete_all
134
+ association method of has many by passing a block with the new function.
135
+ Notice that calling with 'dependent' param in this case shall raise an error since it doesn't have a meaning
136
+ for once and secondly this param cannot be passed to destroy_all which is the callback that we call.
137
+
138
+ A set dynamic methods are generated for altering the set of linked objects.
139
+ They are the same methods as added by has_many decleration.
140
+ The following methods for retrieval and query of
141
+ collections of associated objects will be added:
142
+
143
+ #### Auto-generated methods
144
+
145
+ ```ruby
146
+ others
147
+ others=(other,other,...)
148
+ other_ids
149
+ other_ids=(id,id,...)
150
+ others<<
151
+ others.push
152
+ others.concat
153
+ others.build(attributes={})
154
+ others.create(attributes={})
155
+ others.create!(attributes={})
156
+ others.size
157
+ others.length
158
+ others.count
159
+ others.sum(args*,&block)
160
+ others.empty?
161
+ others.clear
162
+ others.delete(other,other,...)
163
+ others.delete_all
164
+ others.destroy_all
165
+ others.find(*args)
166
+ others.exists?
167
+ others.uniq
168
+ others.reset
169
+ ```
170
+ #### Options
171
+
172
+ [:class_name]
173
+ Specify the class name of the association. Use it only if that name can't be inferred
174
+ from the association name. So <tt>has_many_to_many :products</tt> will by default be linked
175
+ to the Product class, but if the real class name is SpecialProduct, you'll have to
176
+ specify it with this option.
177
+
178
+ #### Examples
179
+
180
+ ```ruby
181
+ has_many_to_many :authors # linked class is Author
182
+ has_many_to_many :authors, class_name: "Person" # specify that linked class is Person
183
+ ```
184
+
185
+ ## has_one_to_many, has_many_to_one
186
+
187
+ has_one_to_many Specifies a one-to-many bi-directional association.
188
+ The has_one_to_many is declared in one side of the association models. The other side must declare the opposite direction with has_many_to_one decleration.
189
+ Notice: It differ from has_many_to_many, which will work also if only one side of the association is
190
+ declared.
191
+
192
+ The has_one_to_many and has_many_to_one use the has_many_to_many to create the relatioships, in the same
193
+ table, but with restriction to a single connection from the has_one side.
194
+ It means that the decleration creates plural helper functions as above in additition to the following
195
+ singular helper functions.
196
+
197
+ #### Singular Auto-generated methods
198
+
199
+ ```ruby
200
+ other
201
+ other=other
202
+ other_id
203
+ other_id=id
204
+ ```
205
+
206
+ ## Contributing
207
+
208
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Hagai-Arzi/active_record-any_links.
209
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'active_record/any_links/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "active_record-any_links"
8
+ spec.version = ActiveRecord::AnyLinks::VERSION
9
+ spec.authors = ["Hagai Arzi"]
10
+ spec.email = ["Hagai.Arzi@Gmail.com"]
11
+
12
+ spec.summary = %q{Enable link objects of different models in a single table using only a single statement.}
13
+ spec.description = %q{Enable link objects of different models in a single table using has_many_to_many, has_one_to_many or has_many_to_one methods.}
14
+ spec.homepage = "https://github.com/Hagai-Arzi/active_record-any_links/tree/master/lib/active_record"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "sqlite3", "~> 1.3"
24
+ spec.add_development_dependency "bundler", "~> 1.14"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+
28
+ # spec.add_development_dependency 'byebug'
29
+ # spec.add_development_dependency 'pry-byebug'
30
+ # spec.add_development_dependency 'pry-rails'
31
+ # spec.add_development_dependency 'pry-stack_explorer'
32
+
33
+ spec.add_dependency "activerecord", ">= 4.2"
34
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "active_record/any_links"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,224 @@
1
+ module ActiveRecord
2
+ module AnyLinks
3
+ module ClassMethods
4
+
5
+ # has_many_to_many Specifies a many-to-many bi-directional association.
6
+ # Regularly, the has_many_to_many is declared in each side of the association models.
7
+ # It will also work if declared only on one side of the association. However, doing so will
8
+ # not generate the dynamic methods on the other side, making the connections seen from
9
+ # one side only
10
+ #
11
+ # The associations, for all types and collections, are stored together in a single table called 'any_links'.
12
+ # The table contain all links between all instances of any type.
13
+ # Every record represent a link, which contains id and type for each side of the connection,
14
+ # which are called id1, type1, and id2, type2 respectively.
15
+ # Since the links are bi-directional, theoretically, any object can be represented as the left
16
+ # side link (#1) or right side (#2).
17
+ # For simplicity and performance, the links are stored thus the "smallest" type is in the left.
18
+ # Any link betwwen 'Incident' and 'Change' is stored as the Change object in the left, since
19
+ # the string types are 'Change' < 'Incident'.
20
+ # This technique is 'Hidden' and transparent for the has_many_to_many consumer.
21
+ #
22
+ # For association of the same type - (e.g. Incident has_many incidents):
23
+ # do standard declaration in the Class (i.e. has_many_to_many <collection>).
24
+ # In that case, a callbacks of after create and after destroy shall be called in the relevant any_link class.
25
+ # To overcome association methods that skip callbacks (as clear method) we override the delete_all
26
+ # association method of has many by passing a block with the new function.
27
+ # Notice that calling with 'dependent' param in this case shall raise an error since it doesn't have a meaning
28
+ # for once and secondly this param cannot be passed to destroy_all which is the callback that we call.
29
+ #
30
+ # The table should manually generated with a migration such as this:
31
+ #
32
+ # class CreateAnyLinks < ActiveRecord::Migration
33
+ # def up
34
+ # create_table :any_links do |t|
35
+ # t.integer :id1, null: false
36
+ # t.string :type1, null: false
37
+ # t.integer :id2, null: false
38
+ # t.string :type2, null: false
39
+ #
40
+ # t.timestamps
41
+ # end
42
+ #
43
+ # change_table :any_links do |t|
44
+ # t.index [:id1, :type1, :id2, :type2], unique: true
45
+ # t.index [:id1, :type1, :type2]
46
+ # t.index [:id2, :type2, :type1]
47
+ # end
48
+ # end
49
+ #
50
+ # def down
51
+ # drop_table :any_links
52
+ # end
53
+ # end
54
+
55
+ # A set dynamic methods are generated for altering the set of linked objects.
56
+ # They are the same methods as added by has_many decleration.
57
+ # The following methods for retrieval and query of
58
+ # collections of associated objects will be added:
59
+ #
60
+ # Auto-generated methods
61
+ # --------------------------------------
62
+ # others
63
+ # others=(other,other,...)
64
+ # other_ids
65
+ # other_ids=(id,id,...)
66
+ # others<<
67
+ # others.push
68
+ # others.concat
69
+ # others.build(attributes={})
70
+ # others.create(attributes={})
71
+ # others.create!(attributes={})
72
+ # others.size
73
+ # others.length
74
+ # others.count
75
+ # others.sum(args*,&block)
76
+ # others.empty?
77
+ # others.clear
78
+ # others.delete(other,other,...)
79
+ # others.delete_all
80
+ # others.destroy_all
81
+ # others.find(*args)
82
+ # others.exists?
83
+ # others.uniq
84
+ # others.reset
85
+ #
86
+ # === Options
87
+ #
88
+ # [:class_name]
89
+ # Specify the class name of the association. Use it only if that name can't be inferred
90
+ # from the association name. So <tt>has_many_to_many :products</tt> will by default be linked
91
+ # to the Product class, but if the real class name is SpecialProduct, you'll have to
92
+ # specify it with this option.
93
+ #
94
+ # === Examples
95
+ #
96
+ # has_many_to_many :authors # linked class is Author
97
+ # has_many_to_many :authors, class_name: "Person" # specify that linked class is Person
98
+ def has_many_to_many(collection, options = {})
99
+ class_name = options[:class_name]
100
+ link_items, foreign_key, source = define_link_class(class_name || collection)
101
+ has_many link_items, foreign_key: foreign_key
102
+ if !identical_source_collection_class(class_name || collection)
103
+ has_many collection, { through: link_items, source: source, dependent: :destroy }.merge(options)
104
+ else
105
+ has_many collection, through: link_items, source: source, dependent: :destroy do
106
+ def delete_all(dependent = nil)
107
+ if dependent.present?
108
+ raise "The dependency is not supported nor relevant to the case of has_many_to_many since the relation is through association table any_links!"
109
+ end
110
+ destroy_all
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ # has_one_to_many Specifies a one-to-many bi-directional association.
117
+ # The has_one_to_many is declared in one side of the association models. The other side
118
+ # must declare the opposite direction with has_many_to_one decleration.
119
+ # Notice: It differ from has_many_to_many, which will work also if only one side of the association is
120
+ # declared.
121
+ #
122
+ # The has_one_to_many and has_many_to_one use the has_many_to_many to create the relatioships, in the same
123
+ # table, but with restriction to a single connection from the has_one side.
124
+ # It means that the decleration creates plural helper functions as above in additition to the following
125
+ # singular helper functions.
126
+ #
127
+ # Singular Auto-generated methods
128
+ # --------------------------------------
129
+ # other
130
+ # other=other
131
+ # other_id
132
+ # other_id=id
133
+ #
134
+ def has_one_to_many(collection, options = {})
135
+ item = collection.to_s.singularize.to_sym
136
+ has_many_to_many(
137
+ item.to_s.pluralize.to_sym,
138
+ options.merge(before_add: -> (owner, obj) { raise ActiveRecord::RecordNotUnique.new("#{name} can have only one #{obj.class} associated") if owner.send(item).present? })
139
+ )
140
+ AnyLinks.define_singular_accessors(self, item, collection)
141
+ end
142
+
143
+ def has_many_to_one(collection, options = {})
144
+ has_many_to_many(collection, options.merge(before_add: -> (_owner, obj) { obj.send(name.demodulize.underscore.pluralize).clear }))
145
+ end
146
+
147
+ private
148
+
149
+ def identical_source_collection_class(collection_or_class)
150
+ name == collection_or_class.to_s.singularize.classify
151
+ end
152
+
153
+ def define_link_class(collection)
154
+ klass1 = name
155
+ klass2 = collection.to_s.singularize.classify
156
+ model1 = name.demodulize.underscore
157
+ model2 = collection.to_s.demodulize.singularize.underscore
158
+ foreign_key = :id1
159
+ source = (klass1 == klass2 ? model2 + "_ghost" : model2).to_sym
160
+ model1, model2, klass1, klass2, foreign_key = model2, model1, klass2, klass1, :id2 if model1 > model2
161
+ klass_name = "#{model1}_#{model2}_link".classify
162
+ model2 = source if klass1 == klass2
163
+
164
+ define_class(klass_name, ActiveRecord::Base) do
165
+ if klass1 == klass2
166
+ attr_accessor :duplicated_relation
167
+ after_create :create_opposite_relation
168
+ after_destroy :destroy_opposite_relation
169
+ end
170
+
171
+ self.table_name = 'any_links'
172
+
173
+ belongs_to model1.to_sym, foreign_key: :id1, class_name: klass1
174
+ belongs_to model2.to_sym, foreign_key: :id2, class_name: klass2
175
+
176
+ default_scope { where(type1: klass1, type2: klass2) }
177
+
178
+ def create_opposite_relation
179
+ if !duplicated_relation && id2 != id1
180
+ self.class.create!(type1: type1, id1: id2, type2: type1, id2: id1, duplicated_relation: true)
181
+ end
182
+ end
183
+
184
+ def destroy_opposite_relation
185
+ self.class.find_by(type1: type1, type2: type2, id1: id2, id2: id1).try(:destroy)
186
+ end
187
+ end
188
+
189
+ [klass_name.underscore.pluralize.to_sym, foreign_key, source]
190
+ end
191
+
192
+ def define_class(klass_name, ancestor, &block)
193
+ if !const_defined?(klass_name)
194
+ klass = Class.new(ancestor, &block)
195
+ Object.const_set(klass_name, klass)
196
+ end
197
+ end
198
+ end
199
+
200
+ def self.define_singular_accessors(model, item, plural_name)
201
+ mixin = model.generated_association_methods
202
+ define_readers(mixin, item, plural_name)
203
+ define_writers(mixin, item, plural_name)
204
+ define_readers(mixin, "#{item}_id", "#{item}_ids")
205
+ define_writers(mixin, "#{item}_id", "#{item}_ids")
206
+ end
207
+
208
+ def self.define_readers(mixin, name, plural_name)
209
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
210
+ def #{name}(*args)
211
+ send("#{plural_name}")[0]
212
+ end
213
+ CODE
214
+ end
215
+
216
+ def self.define_writers(mixin, name, plural_name)
217
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
218
+ def #{name}=(value)
219
+ value.nil? ? send("#{plural_name}=", []) : send("#{plural_name}=", [value])
220
+ end
221
+ CODE
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveRecord
2
+ module AnyLinks
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_record'
2
+ require 'active_record/any_links/version'
3
+ require 'active_record/any_links/class_methods'
4
+
5
+ module ActiveRecord
6
+ class Base
7
+ extend AnyLinks::ClassMethods
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_record-any_links
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Hagai Arzi
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-02-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sqlite3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activerecord
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '4.2'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '4.2'
83
+ description: Enable link objects of different models in a single table using has_many_to_many,
84
+ has_one_to_many or has_many_to_one methods.
85
+ email:
86
+ - Hagai.Arzi@Gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - active_record-any_links.gemspec
99
+ - bin/console
100
+ - bin/setup
101
+ - lib/active_record/any_links.rb
102
+ - lib/active_record/any_links/class_methods.rb
103
+ - lib/active_record/any_links/version.rb
104
+ homepage: https://github.com/Hagai-Arzi/active_record-any_links/tree/master/lib/active_record
105
+ licenses: []
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.6.8
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Enable link objects of different models in a single table using only a single
127
+ statement.
128
+ test_files: []