virtus-relations 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 +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +75 -0
- data/Rakefile +2 -0
- data/lib/virtus/relations.rb +186 -0
- data/lib/virtus/relations/version.rb +5 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/virtus/relations_spec.rb +120 -0
- data/virtus-relations.gemspec +27 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8d2c028409e9b6f8e746c754c9bf30b527e4d36
|
4
|
+
data.tar.gz: 28a863c25d519a3bd1f17026b3ffc85063b2c43d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9fb675108952c9f28a78aa09b44807cb5b43dc4b461534fd3dfeb232cedecccf59cb59b90034154a2de0d5ff69148daf856f5fa33ad48426cf440a2573f845ef
|
7
|
+
data.tar.gz: 66b4929df4ab1176919fbe0c43c6fd8921299c8a40331c985376b02bb8df168deeca3b981b18c799a62e2b7d7ab05ae694f7f723463040ae6b57387ebee15c1d
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Simeon Manolov
|
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,75 @@
|
|
1
|
+
# Virtus::Relations
|
2
|
+
|
3
|
+
Adds relations to Virtus objects.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
In your Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'virtus-relations'
|
11
|
+
```
|
12
|
+
|
13
|
+
In your source code:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'virtus/relations'
|
17
|
+
```
|
18
|
+
|
19
|
+
## Usage examples
|
20
|
+
Given the following classes:
|
21
|
+
```ruby
|
22
|
+
require 'virtus/relations'
|
23
|
+
|
24
|
+
class Kid
|
25
|
+
include Virtus.model
|
26
|
+
|
27
|
+
attribute :name, String
|
28
|
+
end
|
29
|
+
|
30
|
+
class Mother
|
31
|
+
include Virtus.model
|
32
|
+
include Virtus.relations(as: :mom)
|
33
|
+
|
34
|
+
attribute :name, String
|
35
|
+
attribute :kid, Kid, relation: true, lazy: true, default: :load_kid
|
36
|
+
|
37
|
+
def load_kid
|
38
|
+
{ name: 'Billy' }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
You can do the following:
|
44
|
+
```ruby
|
45
|
+
### Explicit assignment
|
46
|
+
alice = Mother.new(name: 'Alice')
|
47
|
+
alice.kid = { name: 'Danny' }
|
48
|
+
alice.kid.mom
|
49
|
+
# => <Mother:0x007fa43415fda8 @name="Alice", ...>
|
50
|
+
|
51
|
+
### Mass-assignment
|
52
|
+
emma = Mother.new(name: 'Emma', kid: { name: 'Johnny' })
|
53
|
+
emma.kid.mom
|
54
|
+
# => #<Mother:0x007fc40dbbdbf8 @name="Emma", ...>
|
55
|
+
|
56
|
+
### Lazy assignment
|
57
|
+
mia = Mother.new(name: 'Mia')
|
58
|
+
mia.kid.mom
|
59
|
+
# => #<Mother:0x007fa435d27130 @name="Mia", ...>
|
60
|
+
|
61
|
+
### Objects can still be created without a parent
|
62
|
+
orphan = Kid.new(name: 'Deirdre')
|
63
|
+
orphan.parent
|
64
|
+
# => NoMethodError: undefined method `parent' for #<Kid:0x007...
|
65
|
+
```
|
66
|
+
|
67
|
+
The `:as` option defaults to `parent` when omitted
|
68
|
+
|
69
|
+
## Contributing
|
70
|
+
|
71
|
+
1. Fork it
|
72
|
+
2. Create your feature branch
|
73
|
+
3. Comply with the [ruby style guide](https://github.com/bbatsov/ruby-style-guide)
|
74
|
+
4. Add tests for your new feature/bugfix. This is important so I don't break it in a future version unintentionally.
|
75
|
+
5. Submit a pull request
|
data/Rakefile
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
require 'virtus/relations/version'
|
3
|
+
|
4
|
+
module Virtus
|
5
|
+
def self.relations(params = {})
|
6
|
+
rel_name = params.fetch(:as, :parent)
|
7
|
+
fail TypeError, 'Symbol expected' unless rel_name.is_a?(Symbol)
|
8
|
+
|
9
|
+
mod = Module.new
|
10
|
+
mod.instance_variable_set(:@rel_name, rel_name)
|
11
|
+
|
12
|
+
mod.module_eval do
|
13
|
+
def self.class_methods
|
14
|
+
Module.new do
|
15
|
+
# During instantiation, .relation_attributes is called
|
16
|
+
# If class was instantiated before, just return the list of related
|
17
|
+
# attributes
|
18
|
+
#
|
19
|
+
# If instantiated for the first time, then monkey-patch some instance
|
20
|
+
# methods to allow relation attributes to work with accessor methods.
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# patch Model#attribute=
|
24
|
+
#
|
25
|
+
# 1. create {list}
|
26
|
+
# 2. for each {attribute} in {list}
|
27
|
+
# 2.1. patch the accessor method
|
28
|
+
# 2.2. patch the lazy initializer method (if any)
|
29
|
+
#
|
30
|
+
def relation_attributes
|
31
|
+
@relation_attributes ||= attribute_set.select do |attribute|
|
32
|
+
next unless attribute.options[:relation] == true
|
33
|
+
|
34
|
+
patch_accessor_method(attribute)
|
35
|
+
patch_lazy_initializer(attribute)
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# When the original method returns something, we need to
|
42
|
+
# actually set ourselves as its parent
|
43
|
+
# If that something is a collection, do it for each element
|
44
|
+
#
|
45
|
+
def relate(object, method_return)
|
46
|
+
if object.kind_of?(Array)
|
47
|
+
object.each { |o| relate(o, method_return) }
|
48
|
+
else
|
49
|
+
object.define_singleton_method(relation_name) { method_return }
|
50
|
+
object
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
protected
|
56
|
+
# 1. rename method "{attribute}=" to "{attribute}_not_related="
|
57
|
+
# 2. define method "{attribute}=", which:
|
58
|
+
# 2.1. calls "{attribute}_not_related=", takes the {return_object}
|
59
|
+
# 2.2. defines {return_object}.parent which returns self
|
60
|
+
# 2.3. returns {return_object}
|
61
|
+
# 3. return the list
|
62
|
+
def patch_accessor_method(attribute)
|
63
|
+
if [Numeric, Symbol].any? { |c| attribute.primitive.ancestors.include?(c) }
|
64
|
+
fail "Relations don't work with Numeric and Symbol types"
|
65
|
+
end
|
66
|
+
|
67
|
+
old_method = "#{attribute.name}_not_related="
|
68
|
+
new_method = "#{attribute.name}="
|
69
|
+
|
70
|
+
# Suffix the original method with '_not_related'
|
71
|
+
define_method(old_method, instance_method(new_method))
|
72
|
+
define_method(new_method) do |value|
|
73
|
+
return_value = send(old_method, value)
|
74
|
+
self.class.relate(return_value, self)
|
75
|
+
end
|
76
|
+
|
77
|
+
private old_method
|
78
|
+
visibility = attribute.options[:writer]
|
79
|
+
send(visibility, new_method)
|
80
|
+
end
|
81
|
+
|
82
|
+
# (see above for the explanation of step 2.)
|
83
|
+
# Wrap the original method/proc into a new one, which:
|
84
|
+
# 1. calls the original one, takes the {return_object}
|
85
|
+
# 2. coerces {return_object}
|
86
|
+
# 3. defines {return_object}.parent which returns self
|
87
|
+
# 4. returns {return_object}
|
88
|
+
#
|
89
|
+
def patch_lazy_initializer(attribute)
|
90
|
+
return unless attribute.lazy?
|
91
|
+
|
92
|
+
case attribute.default_value.value
|
93
|
+
when Proc
|
94
|
+
old_proc = attribute.default_value.value
|
95
|
+
new_proc = proc do |object, *args|
|
96
|
+
return_value = attribute.coerce(old_proc.call(*[object, *args]))
|
97
|
+
object.class.relate(return_value, object)
|
98
|
+
end
|
99
|
+
|
100
|
+
attribute.default_value.instance_variable_set(:@value, new_proc)
|
101
|
+
else
|
102
|
+
old_method = "#{attribute.default_value.value}_not_related"
|
103
|
+
new_method = attribute.default_value.value
|
104
|
+
visibility = if private_method_defined?(new_method)
|
105
|
+
:private
|
106
|
+
elsif protected_method_defined?(new_method)
|
107
|
+
:protected
|
108
|
+
else
|
109
|
+
:public
|
110
|
+
end
|
111
|
+
|
112
|
+
define_method(old_method, instance_method(new_method))
|
113
|
+
define_method(new_method) do
|
114
|
+
return_value = attribute.coerce(send(old_method))
|
115
|
+
self.class.relate(return_value, self)
|
116
|
+
return_value
|
117
|
+
end
|
118
|
+
|
119
|
+
private old_method
|
120
|
+
send(visibility, new_method)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end # Module.new
|
124
|
+
end # def
|
125
|
+
|
126
|
+
def self.instance_methods
|
127
|
+
Module.new do
|
128
|
+
#
|
129
|
+
# Enhance the initialize process to allow
|
130
|
+
# related attributes to work with mass-assignment
|
131
|
+
#
|
132
|
+
def initialize(mass_assignment_attributes = {})
|
133
|
+
super
|
134
|
+
|
135
|
+
self.class.relation_attributes.each do |ra|
|
136
|
+
# set self as the child's parent only if child was mass-
|
137
|
+
# assigned during self.initialize (e.g. hash has child's key)
|
138
|
+
# This prevents children from doing this against the parents
|
139
|
+
# when they also have relation: true on their attributes
|
140
|
+
# (since their initializers will not receive the parent as
|
141
|
+
# a part of the mass-assignment)
|
142
|
+
|
143
|
+
if mass_assignment_attributes.key?(ra.name)
|
144
|
+
self.class.relate(ra.get(self), self)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
alias_method :dup_not_related, :dup
|
150
|
+
|
151
|
+
# Add #parent to duped objects, when available
|
152
|
+
def dup
|
153
|
+
rel = self.class.relation_name
|
154
|
+
if respond_to?(rel)
|
155
|
+
self.class.relate(dup_not_related, rel)
|
156
|
+
else
|
157
|
+
dup_not_related
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end # Module.new
|
161
|
+
end # def
|
162
|
+
|
163
|
+
def self.included(base)
|
164
|
+
required = [
|
165
|
+
Virtus::InstanceMethods::MassAssignment,
|
166
|
+
Virtus::InstanceMethods::Constructor
|
167
|
+
]
|
168
|
+
|
169
|
+
unless required.all? { |mod| base.included_modules.include?(mod) }
|
170
|
+
fail 'Virtus.model must be included prior to Virtus.relations'
|
171
|
+
end
|
172
|
+
|
173
|
+
# Using a local variable in the parent scope
|
174
|
+
# with the same name as the singleton method
|
175
|
+
# prevents recursion
|
176
|
+
relation_name = @rel_name
|
177
|
+
base.define_singleton_method(:relation_name) { relation_name }
|
178
|
+
|
179
|
+
base.send(:include, instance_methods)
|
180
|
+
base.extend(class_methods)
|
181
|
+
end
|
182
|
+
|
183
|
+
mod
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/core_ext/object/instance_variables'
|
3
|
+
|
4
|
+
describe Virtus::Relations do
|
5
|
+
# The child
|
6
|
+
class C
|
7
|
+
include Virtus.model
|
8
|
+
end
|
9
|
+
|
10
|
+
# The parent, referenced by Child#parent
|
11
|
+
class P
|
12
|
+
include Virtus.model
|
13
|
+
include Virtus.relations
|
14
|
+
|
15
|
+
attribute :c_1, C, relation: true
|
16
|
+
attribute :c_2, C, relation: true, lazy: true, default: :load_c_2
|
17
|
+
attribute :c_3, C, relation: true, lazy: true, default: proc { {} }
|
18
|
+
attribute :c_4, Array[C], relation: true
|
19
|
+
attribute :c_5, Array[C], relation: true, lazy: true, default: :load_c_5
|
20
|
+
attribute :c_6, Array[C], relation: true, lazy: true, default: proc { [{}] }
|
21
|
+
|
22
|
+
def load_c_2
|
23
|
+
{}
|
24
|
+
end
|
25
|
+
|
26
|
+
def load_c_5
|
27
|
+
[{}]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Another parent, but referenced by Child#father
|
32
|
+
class F
|
33
|
+
include Virtus.model
|
34
|
+
include Virtus.relations(as: :father)
|
35
|
+
|
36
|
+
attribute :c, C, relation: true
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'allow to specify a relation name' do
|
40
|
+
f = F.new
|
41
|
+
f.c = {}
|
42
|
+
|
43
|
+
expect(f.c.father).to be(f)
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'Object#parent' do
|
47
|
+
context 'when initialized via a related attribute' do
|
48
|
+
context 'of non-array type' do
|
49
|
+
context 'and is mass-assigned' do
|
50
|
+
let(:p) { P.new(c_1: {}) }
|
51
|
+
|
52
|
+
it 'returns the attribute owner' do
|
53
|
+
expect(p.c_1.parent).to be(p)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'does not store its return value in an instance variable' do
|
57
|
+
expect(p.c_1.instance_values.values).not_to include(p)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'and is strictly initialized' do
|
62
|
+
it 'returns the attribute owner' do
|
63
|
+
p = P.new
|
64
|
+
p.c_1 = {}
|
65
|
+
expect(p.c_1.parent).to be(p)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'and is lazily initialized via a method' do
|
70
|
+
it 'returns the attribute owner' do
|
71
|
+
p = P.new
|
72
|
+
expect(p.c_2.parent).to be(p)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'and is lazily initialized via a proc' do
|
77
|
+
it 'returns the attribute owner' do
|
78
|
+
p = P.new
|
79
|
+
p.c_3
|
80
|
+
expect(p.c_3.parent).to be(p)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'of an array type' do
|
86
|
+
context 'and is mass-assigned' do
|
87
|
+
it 'returns the attribute owner' do
|
88
|
+
p = P.new(c_4: [{}])
|
89
|
+
expect(p.c_4.first.parent).to be(p)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'and is strictly initialized' do
|
94
|
+
it 'returns the attribute owner' do
|
95
|
+
p = P.new
|
96
|
+
p.c_4 = [{}]
|
97
|
+
expect(p.c_4.first.parent).to be(p)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'and is lazily initialized via a method' do
|
102
|
+
it 'returns the attribute owner' do
|
103
|
+
p = P.new
|
104
|
+
expect(p.c_5.first.parent).to be(p)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'and is lazily initialized via a proc' do
|
109
|
+
it 'returns the attribute owner' do
|
110
|
+
p = P.new
|
111
|
+
expect(p.c_6.first.parent).to be(p)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe ''
|
119
|
+
|
120
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'virtus/relations/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'virtus-relations'
|
8
|
+
spec.version = Virtus::Relations::VERSION
|
9
|
+
spec.authors = ['Simeon Manolov']
|
10
|
+
spec.email = ['s.manolloff@gmail.com']
|
11
|
+
spec.summary = %q{Relations for Virtus models}
|
12
|
+
spec.homepage = 'https://github.com/smanolloff/virtus-relations'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_runtime_dependency 'virtus', '~> 1'
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.2'
|
25
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.1'
|
26
|
+
spec.add_development_dependency 'activesupport', '~> 4.2'
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: virtus-relations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Simeon Manolov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: virtus
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
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.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
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.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.2'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '4.2'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- s.manolloff@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- lib/virtus/relations.rb
|
110
|
+
- lib/virtus/relations/version.rb
|
111
|
+
- spec/spec_helper.rb
|
112
|
+
- spec/virtus/relations_spec.rb
|
113
|
+
- virtus-relations.gemspec
|
114
|
+
homepage: https://github.com/smanolloff/virtus-relations
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.4.3
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: Relations for Virtus models
|
138
|
+
test_files:
|
139
|
+
- spec/spec_helper.rb
|
140
|
+
- spec/virtus/relations_spec.rb
|