rails_dynamic_associations 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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +93 -0
- data/Rakefile +25 -0
- data/app/models/relation.rb +78 -0
- data/app/models/role.rb +32 -0
- data/config/initializers/model_associations.rb +9 -0
- data/db/migrate/01_create_roles.rb +10 -0
- data/db/migrate/02_create_relations.rb +14 -0
- data/lib/core_ext/string.rb +8 -0
- data/lib/rails_dynamic_associations/active_record/associations.rb +101 -0
- data/lib/rails_dynamic_associations/active_record/relations.rb +62 -0
- data/lib/rails_dynamic_associations/active_record/roles.rb +24 -0
- data/lib/rails_dynamic_associations/active_record.rb +9 -0
- data/lib/rails_dynamic_associations/engine.rb +5 -0
- data/lib/rails_dynamic_associations/version.rb +3 -0
- data/lib/rails_dynamic_associations.rb +35 -0
- data/lib/tasks/rails_dynamic_associations_tasks.rake +4 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 02f1e9739f27b665443124374994afc6729e4e8f
|
4
|
+
data.tar.gz: f5d07be362c9b98969dfe4b5b0109f6b429f2c0f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5ee36ecaeee3642a97e3875c93c365e7323ac01ecc6fd7db0f2e67310eaf3a23aa61d9a0e351ee88b5c98f7de8d676f31fa456a1d992167dd8e37d4a9e9fd6ec
|
7
|
+
data.tar.gz: fc3ce8c1acbdebba32efd429e06eb5fc0b3390fc72163eb28905730f0a6293f5e0222fd67b2d89b8045a87aa138157f7b43b105bb070a7581efda2e0a0422802
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Alexander Senko, SoftPro Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# RailsDynamicAssociations
|
2
|
+
|
3
|
+
Define your model associations in the database without changing the schema or models.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
* Creates associations for your models when application starts.
|
8
|
+
* Provides `Relation` & `Role` models.
|
9
|
+
* No configuration code needed.
|
10
|
+
* No code generated or inserted to your app (except migrations).
|
11
|
+
* Adds some useful methods to `ActiveRecord` objects to handle their relations.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
1. Add the gem to your `Gemfile` and `bundle` it.
|
16
|
+
2. Copy migrations to your app (`rake rails_dynamic_associations:install:migrations`).
|
17
|
+
3. Migrate the DB (`rake db:migrate`).
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Add configuration records to the DB:
|
22
|
+
|
23
|
+
``` ruby
|
24
|
+
Relation.create({
|
25
|
+
source_type: Person,
|
26
|
+
target_type: Book,
|
27
|
+
})
|
28
|
+
```
|
29
|
+
|
30
|
+
Or use a helper method:
|
31
|
+
|
32
|
+
``` ruby
|
33
|
+
Relation.seed Person, Book
|
34
|
+
```
|
35
|
+
|
36
|
+
Now you have:
|
37
|
+
|
38
|
+
``` ruby
|
39
|
+
person.books
|
40
|
+
book.people
|
41
|
+
```
|
42
|
+
|
43
|
+
### Roles
|
44
|
+
|
45
|
+
You can create multiple role-based associations between two models.
|
46
|
+
|
47
|
+
``` ruby
|
48
|
+
Relation.seed Person, Book, %w[
|
49
|
+
author
|
50
|
+
editor
|
51
|
+
]
|
52
|
+
```
|
53
|
+
|
54
|
+
You will get:
|
55
|
+
|
56
|
+
``` ruby
|
57
|
+
person.books
|
58
|
+
person.authored_books
|
59
|
+
person.edited_books
|
60
|
+
|
61
|
+
book.people
|
62
|
+
book.author_people
|
63
|
+
book.editor_people
|
64
|
+
```
|
65
|
+
|
66
|
+
#### `User` special case
|
67
|
+
|
68
|
+
In case you have set up relations with a `User` model you'll get a slightly different naming:
|
69
|
+
|
70
|
+
``` ruby
|
71
|
+
Relation.seed User, Book, %w[
|
72
|
+
author
|
73
|
+
editor
|
74
|
+
]
|
75
|
+
```
|
76
|
+
|
77
|
+
``` ruby
|
78
|
+
book.users
|
79
|
+
book.authors
|
80
|
+
book.editors
|
81
|
+
```
|
82
|
+
|
83
|
+
###### TODO
|
84
|
+
|
85
|
+
* Describe self-referential associations.
|
86
|
+
|
87
|
+
## Contributing
|
88
|
+
|
89
|
+
1. Fork it
|
90
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
91
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
92
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
93
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'RailsDynamicAssociations'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.md')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
Bundler::GemHelper.install_tasks
|
25
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class Relation < ActiveRecord::Base
|
2
|
+
belongs_to :source, polymorphic: true
|
3
|
+
belongs_to :target, polymorphic: true
|
4
|
+
belongs_to :role
|
5
|
+
|
6
|
+
delegate :name, to: :role, allow_nil: true
|
7
|
+
|
8
|
+
RailsDynamicAssociations.directions.each &-> (attribute, direction) do
|
9
|
+
scope "#{direction}_abstract", -> (object = nil) {
|
10
|
+
if object then
|
11
|
+
send direction, object
|
12
|
+
else
|
13
|
+
all
|
14
|
+
end.
|
15
|
+
where "#{attribute}_id" => nil
|
16
|
+
}
|
17
|
+
|
18
|
+
scope "#{direction}_general", -> {
|
19
|
+
send("#{direction}_abstract").
|
20
|
+
where "#{attribute}_type" => nil
|
21
|
+
}
|
22
|
+
|
23
|
+
scope direction, -> (object) {
|
24
|
+
case object
|
25
|
+
when nil then
|
26
|
+
all
|
27
|
+
when Symbol then
|
28
|
+
send "#{direction}_#{object}"
|
29
|
+
when Class then
|
30
|
+
where "#{attribute}_type" => object.base_class
|
31
|
+
else
|
32
|
+
where "#{attribute}_type" => object.class.base_class,
|
33
|
+
"#{attribute}_id" => object.id
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
scope :abstract, -> {
|
39
|
+
of_abstract.to_abstract
|
40
|
+
}
|
41
|
+
|
42
|
+
scope :applied, -> {
|
43
|
+
where.not source_id: nil,
|
44
|
+
target_id: nil
|
45
|
+
}
|
46
|
+
|
47
|
+
scope :named, -> (*names) {
|
48
|
+
if names.present? then
|
49
|
+
where roles: { name: names.flatten.map(&:to_s) }
|
50
|
+
else
|
51
|
+
where.not roles: { name: nil }
|
52
|
+
end.
|
53
|
+
includes :role
|
54
|
+
}
|
55
|
+
|
56
|
+
def self.seed source, target, roles = nil
|
57
|
+
(roles.present? ? by_roles(roles) : [ self ]).map do |scope|
|
58
|
+
scope.create source_type: source,
|
59
|
+
target_type: target
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.by_roles *names
|
64
|
+
Role.find_or_create_named(*names).
|
65
|
+
map &:relations
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
# Using polymorphic associations in combination with single table inheritance (STI) is
|
70
|
+
# a little tricky. In order for the associations to work as expected, ensure that you
|
71
|
+
# store the base model for the STI models in the type column of the polymorphic
|
72
|
+
# association.
|
73
|
+
for reflection in reflections.values.select { |r| r.options[:polymorphic] } do
|
74
|
+
define_method "#{reflection.name}_type=" do |type|
|
75
|
+
super type && type.to_s.classify.constantize.base_class.to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/app/models/role.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
class Role < ActiveRecord::Base
|
2
|
+
has_many :relations
|
3
|
+
|
4
|
+
validates :name, presence: true, uniqueness: true
|
5
|
+
|
6
|
+
scope :named, -> (*names) {
|
7
|
+
where name: names.flatten.map(&:to_s)
|
8
|
+
}
|
9
|
+
|
10
|
+
scope :available, -> {
|
11
|
+
includes(:relations).
|
12
|
+
where relations: { id: Relation.of_abstract } # TODO: simplify
|
13
|
+
}
|
14
|
+
|
15
|
+
scope :in, -> (object) {
|
16
|
+
where relations: { id: object.source_relations } # TODO: simplify
|
17
|
+
}
|
18
|
+
|
19
|
+
scope :for, -> (subject) {
|
20
|
+
where relations: { id: subject.target_relations } # TODO: simplify
|
21
|
+
}
|
22
|
+
|
23
|
+
def self.find_or_create_named *names
|
24
|
+
names.flatten!
|
25
|
+
names.compact!
|
26
|
+
|
27
|
+
(existing = named(names)).all +
|
28
|
+
(names - existing.map(&:name)).map { |name|
|
29
|
+
create name: name
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
ActiveSupport.on_load :model_class do
|
2
|
+
for type in RailsDynamicAssociations.directions.keys do
|
3
|
+
for relation in send("#{type}_relations").abstract.select(&:"#{type}_type") do
|
4
|
+
setup_relation type, relation.send("#{type}_type").constantize, relation.role do |association|
|
5
|
+
attr_accessible "#{association.to_s.singularize}_ids"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end if self != Relation and Relation.table_exists? # needed for DB migrations & schema initializing
|
9
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateRelations < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :relations do |t|
|
4
|
+
t.references :source, polymorphic: { default: 'User' }
|
5
|
+
t.references :target, polymorphic: true
|
6
|
+
t.references :role
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :relations, [ :source_id, :source_type, :target_id, :target_type, :role_id ], unique: true,
|
12
|
+
name: 'index_relations_on_source_and_target_and_role'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module RailsDynamicAssociations::ActiveRecord
|
4
|
+
module Associations
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
protected
|
9
|
+
|
10
|
+
def setup_relation type, target = self, role = nil
|
11
|
+
define_association type, target
|
12
|
+
define_association type, target, role if role
|
13
|
+
|
14
|
+
for association, method in RailsDynamicAssociations.self_referential_recursive do
|
15
|
+
define_recursive_methods association, method if association.in? reflections and not method_defined? method
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def define_relations_association type, target = self, role = nil
|
22
|
+
:"#{role ? association_name(type, target, role).to_s.singularize : type}_relations".tap do |association|
|
23
|
+
unless association.in? reflections then
|
24
|
+
has_many association, conditions: role && { role_id: role.id },
|
25
|
+
as: (RailsDynamicAssociations.directions.keys - [ type ]).first, class_name: 'Relation'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def define_association type, target = self, role = nil
|
31
|
+
unless (association = association_name(type, target, role)).in? reflections then
|
32
|
+
has_many association,
|
33
|
+
through: define_relations_association(type, target, role),
|
34
|
+
source: type,
|
35
|
+
source_type: target.base_class.name,
|
36
|
+
class_name: target.name
|
37
|
+
|
38
|
+
define_association_with_roles association unless role
|
39
|
+
|
40
|
+
yield association if block_given?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def define_association_with_roles association
|
45
|
+
redefine_method "#{association}_with_roles" do |*roles|
|
46
|
+
send(association).where(
|
47
|
+
relations: {
|
48
|
+
role_id: Role.named(roles).pluck(:id)
|
49
|
+
}
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def define_recursive_methods association, method, tree_method = "#{method.to_s.singularize}_tree", distance_method = "#{method}_with_distance"
|
55
|
+
redefine_method tree_method do
|
56
|
+
send(association).inject([]) { |tree, node|
|
57
|
+
tree << node << node.send(tree_method)
|
58
|
+
}.reject &:blank?
|
59
|
+
end
|
60
|
+
|
61
|
+
redefine_method distance_method do
|
62
|
+
(with_distance = -> (level, distance) {
|
63
|
+
if level.is_a? Array then
|
64
|
+
level.inject(ActiveSupport::OrderedHash.new) { |hash, node|
|
65
|
+
hash.merge with_distance[node, distance.next]
|
66
|
+
}
|
67
|
+
else
|
68
|
+
{ level => distance }
|
69
|
+
end
|
70
|
+
})[send(tree_method), 0]
|
71
|
+
end
|
72
|
+
|
73
|
+
redefine_method method do
|
74
|
+
send(tree_method).flatten
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def association_name type, target = self, role = nil
|
79
|
+
if role then
|
80
|
+
if target == self || target <= User then
|
81
|
+
{
|
82
|
+
source: role.name,
|
83
|
+
target: "#{role.name.passivize}_#{target.name.split('::').reverse.join}",
|
84
|
+
}[type]
|
85
|
+
else
|
86
|
+
"#{{
|
87
|
+
source: role.name,
|
88
|
+
target: role.name.passivize,
|
89
|
+
}[type]}_#{association_name type, target}"
|
90
|
+
end
|
91
|
+
else
|
92
|
+
if target == self then
|
93
|
+
RailsDynamicAssociations.self_referential_recursive[type].to_s
|
94
|
+
else
|
95
|
+
target.name.split('::').reverse.join
|
96
|
+
end
|
97
|
+
end.tableize.to_sym
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module RailsDynamicAssociations::ActiveRecord
|
4
|
+
module Relations
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
extend ClassAndInstanceMethods
|
9
|
+
include ClassAndInstanceMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
RailsDynamicAssociations.opposite_directions.each &-> (association, method) do
|
14
|
+
define_method "#{association}_relations" do
|
15
|
+
Relation.send method, self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassAndInstanceMethods
|
21
|
+
# TODO: use keyword arguments
|
22
|
+
def find_relations args = {}
|
23
|
+
directions = RailsDynamicAssociations.directions
|
24
|
+
|
25
|
+
for association, method in directions do
|
26
|
+
args[association] = args.delete method
|
27
|
+
end
|
28
|
+
|
29
|
+
as = [ args[:as] ].flatten
|
30
|
+
|
31
|
+
if directions.keys.inject(nil) { |r, k| !r ^ !args[k] } then # direction specified
|
32
|
+
for association, method in directions do
|
33
|
+
next unless args[association]
|
34
|
+
|
35
|
+
return (as.present? ?
|
36
|
+
source_relations.named(as) :
|
37
|
+
source_relations
|
38
|
+
).send method, args[association]
|
39
|
+
end
|
40
|
+
else # both directions
|
41
|
+
directions.map do |association, method|
|
42
|
+
as.present? ?
|
43
|
+
send("#{association}_relations").named(as) :
|
44
|
+
send("#{association}_relations")
|
45
|
+
end.sum
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def relative? args = {}
|
50
|
+
find_relations(args).
|
51
|
+
present?
|
52
|
+
end
|
53
|
+
|
54
|
+
def relatives args = {}
|
55
|
+
find_relations(args).
|
56
|
+
map { |r|
|
57
|
+
([ r.source, r.target ] - [ self ]).first
|
58
|
+
}.uniq
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module RailsDynamicAssociations::ActiveRecord
|
4
|
+
module Roles
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
extend ClassAndInstanceMethods
|
9
|
+
include ClassAndInstanceMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassAndInstanceMethods
|
13
|
+
def roles to: nil, &block
|
14
|
+
if block_given? then
|
15
|
+
source_relations.instance_eval &block
|
16
|
+
else
|
17
|
+
source_relations
|
18
|
+
end.
|
19
|
+
to(to).
|
20
|
+
map(&:name).uniq
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'rails_dynamic_associations/active_record/associations'
|
2
|
+
require 'rails_dynamic_associations/active_record/relations'
|
3
|
+
require 'rails_dynamic_associations/active_record/roles'
|
4
|
+
|
5
|
+
ActiveSupport.on_load :active_record do
|
6
|
+
include RailsDynamicAssociations::ActiveRecord::Associations
|
7
|
+
include RailsDynamicAssociations::ActiveRecord::Relations
|
8
|
+
include RailsDynamicAssociations::ActiveRecord::Roles
|
9
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rails_model_load_hook'
|
2
|
+
|
3
|
+
require 'rails_dynamic_associations/engine'
|
4
|
+
require 'core_ext/string'
|
5
|
+
|
6
|
+
module RailsDynamicAssociations
|
7
|
+
mattr_accessor :directions,
|
8
|
+
:self_referential,
|
9
|
+
:self_referential_recursive
|
10
|
+
|
11
|
+
self.directions = {
|
12
|
+
source: :of,
|
13
|
+
target: :to,
|
14
|
+
}
|
15
|
+
|
16
|
+
self.self_referential = {
|
17
|
+
source: :child,
|
18
|
+
target: :parent,
|
19
|
+
}
|
20
|
+
|
21
|
+
self.self_referential_recursive = {
|
22
|
+
parents: :ancestors,
|
23
|
+
children: :descendants,
|
24
|
+
}
|
25
|
+
|
26
|
+
def self.opposite_directions
|
27
|
+
directions.each_with_object({}) do |(key, value), hash|
|
28
|
+
hash[key] = directions.values.find do |v|
|
29
|
+
v != value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rails_dynamic_associations/active_record'
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails_dynamic_associations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Senko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails_model_load_hook
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Define your model associations in the database without changing the schema
|
56
|
+
or models.
|
57
|
+
email:
|
58
|
+
- Alexander.Senko@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- MIT-LICENSE
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- app/models/relation.rb
|
67
|
+
- app/models/role.rb
|
68
|
+
- config/initializers/model_associations.rb
|
69
|
+
- db/migrate/01_create_roles.rb
|
70
|
+
- db/migrate/02_create_relations.rb
|
71
|
+
- lib/core_ext/string.rb
|
72
|
+
- lib/rails_dynamic_associations.rb
|
73
|
+
- lib/rails_dynamic_associations/active_record.rb
|
74
|
+
- lib/rails_dynamic_associations/active_record/associations.rb
|
75
|
+
- lib/rails_dynamic_associations/active_record/relations.rb
|
76
|
+
- lib/rails_dynamic_associations/active_record/roles.rb
|
77
|
+
- lib/rails_dynamic_associations/engine.rb
|
78
|
+
- lib/rails_dynamic_associations/version.rb
|
79
|
+
- lib/tasks/rails_dynamic_associations_tasks.rake
|
80
|
+
homepage: https://github.com/softpro/rails_dynamic_associations
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.2.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: DB-driven model associations for Rails.
|
104
|
+
test_files: []
|