activerecord-traits 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 +15 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +62 -0
- data/Rakefile +1 -0
- data/activerecord-traits.gemspec +24 -0
- data/lib/activerecord-traits.rb +44 -0
- data/lib/traits/association.rb +39 -0
- data/lib/traits/attribute.rb +52 -0
- data/lib/traits/base.rb +7 -0
- data/lib/traits/concerns/association/essay_shortcuts.rb +9 -0
- data/lib/traits/concerns/association/intermediate.rb +55 -0
- data/lib/traits/concerns/association/join.rb +89 -0
- data/lib/traits/concerns/association/macro.rb +43 -0
- data/lib/traits/concerns/association/members.rb +35 -0
- data/lib/traits/concerns/association/naming.rb +15 -0
- data/lib/traits/concerns/association/polymorphism.rb +118 -0
- data/lib/traits/concerns/association/read_only.rb +17 -0
- data/lib/traits/concerns/association/through.rb +72 -0
- data/lib/traits/concerns/attribute/essay_shortcuts.rb +9 -0
- data/lib/traits/concerns/attribute/key.rb +38 -0
- data/lib/traits/concerns/attribute/naming.rb +20 -0
- data/lib/traits/concerns/attribute/polymorphism.rb +28 -0
- data/lib/traits/concerns/attribute/querying.rb +14 -0
- data/lib/traits/concerns/attribute/sti.rb +15 -0
- data/lib/traits/concerns/attribute/type.rb +59 -0
- data/lib/traits/concerns/model/essay_shortcuts.rb +9 -0
- data/lib/traits/concerns/model/naming.rb +83 -0
- data/lib/traits/concerns/model/polymorphism.rb +15 -0
- data/lib/traits/concerns/model/querying.rb +34 -0
- data/lib/traits/concerns/model/sti.rb +41 -0
- data/lib/traits/descendants_listing.rb +51 -0
- data/lib/traits/engine.rb +13 -0
- data/lib/traits/list.rb +52 -0
- data/lib/traits/model.rb +78 -0
- data/lib/traits/utilities.rb +37 -0
- data/lib/traits/version.rb +3 -0
- metadata +151 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
module Traits
|
2
|
+
class Model
|
3
|
+
module Naming
|
4
|
+
# class User
|
5
|
+
# name => user
|
6
|
+
#
|
7
|
+
# class Assets::Photo
|
8
|
+
# name => assets/photo
|
9
|
+
#
|
10
|
+
def name
|
11
|
+
# Rails 4.1 doesn't support nested acronyms
|
12
|
+
#
|
13
|
+
# Rails 4.1 behaviour:
|
14
|
+
# 'Helpers::ViewHelper'.underscore => 'helpers/view_helper' - good
|
15
|
+
# 'CIHelper'.underscore => 'ci_helper' - good
|
16
|
+
# 'Helpers::CIHelper' => 'helpers/ci_helper' - good
|
17
|
+
#
|
18
|
+
# 'Helpers::ViewHelper' => 'helpers/view_helper' - good
|
19
|
+
# 'CIHelper' => 'cihelper' - good
|
20
|
+
# 'Helpers::CIHelper' => 'helpers/ci_helper' - bad!
|
21
|
+
#
|
22
|
+
# Newer Rails behaviour:
|
23
|
+
# 'Helpers::ViewHelper' => 'helpers/view_helper' - good
|
24
|
+
# 'CIHelper' => 'cihelper' - good
|
25
|
+
# 'Helpers::CIHelper' => 'helpers/cihelper' - good
|
26
|
+
#
|
27
|
+
@name ||= model_class.name.split('::').map(&:underscore).join('/')
|
28
|
+
end
|
29
|
+
|
30
|
+
# class User
|
31
|
+
# plural_name => users
|
32
|
+
#
|
33
|
+
# class Assets::Photo
|
34
|
+
# plural_name => assets/photos
|
35
|
+
#
|
36
|
+
def plural_name
|
37
|
+
@plural_name ||= name.pluralize
|
38
|
+
end
|
39
|
+
|
40
|
+
# class User
|
41
|
+
# resource_name => users
|
42
|
+
#
|
43
|
+
# class Assets::Photo
|
44
|
+
# resource_name => assets/photos
|
45
|
+
#
|
46
|
+
def resource_name
|
47
|
+
@resource_name ||= plural_name
|
48
|
+
end
|
49
|
+
|
50
|
+
# class User
|
51
|
+
# class_name => User
|
52
|
+
#
|
53
|
+
# class Assets::Photo
|
54
|
+
# class_name => Assets::Photo
|
55
|
+
#
|
56
|
+
def class_name
|
57
|
+
@class_name ||= model_class.name
|
58
|
+
end
|
59
|
+
|
60
|
+
# class User
|
61
|
+
# lookup_name => User
|
62
|
+
# lookup_name(:underscore) => user
|
63
|
+
#
|
64
|
+
# class Assets::Photo
|
65
|
+
# lookup_name => AssetsPhoto
|
66
|
+
# lookup_name(:underscore) => assets_photo
|
67
|
+
#
|
68
|
+
def lookup_name(namecase = :class)
|
69
|
+
namecase == :underscore ? name.gsub('/', '_') : class_name.gsub('::', '')
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_hash
|
73
|
+
super.merge!(
|
74
|
+
name: name,
|
75
|
+
plural_name: plural_name,
|
76
|
+
class_name: class_name,
|
77
|
+
lookup_name: lookup_name,
|
78
|
+
resource_name: resource_name
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Traits
|
2
|
+
class Model
|
3
|
+
module Querying
|
4
|
+
def primary_key_name
|
5
|
+
model_class.primary_key.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def arel
|
9
|
+
model_class.arel_table
|
10
|
+
end
|
11
|
+
|
12
|
+
def connection
|
13
|
+
model_class.connection
|
14
|
+
end
|
15
|
+
|
16
|
+
def table_name
|
17
|
+
model_class.table_name
|
18
|
+
end
|
19
|
+
|
20
|
+
def quoted_table_name
|
21
|
+
connection.quote_table_name(model_class.table_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_hash
|
25
|
+
super.merge!(
|
26
|
+
table_name: table_name,
|
27
|
+
quoted_table_name: quoted_table_name,
|
28
|
+
polymorphic_type: polymorphic_type,
|
29
|
+
primary_key_name: primary_key_name
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Traits
|
2
|
+
class Model
|
3
|
+
module STI
|
4
|
+
def uses_sti?
|
5
|
+
sti_base? || sti_derived?
|
6
|
+
end
|
7
|
+
|
8
|
+
def sti_base?
|
9
|
+
model_class.descends_from_active_record? && model_class.subclasses.any? do |subclass|
|
10
|
+
subclass.superclass == model_class
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def sti_derived?
|
15
|
+
!model_class.descends_from_active_record?
|
16
|
+
end
|
17
|
+
|
18
|
+
def sti_attribute_name
|
19
|
+
model_class.inheritance_column.to_sym
|
20
|
+
end
|
21
|
+
|
22
|
+
def sti_chain
|
23
|
+
model_class = self.model_class
|
24
|
+
chain = [model_class]
|
25
|
+
until model_class.superclass == ActiveRecord::Base do
|
26
|
+
model_class = model_class.superclass
|
27
|
+
chain.unshift(model_class)
|
28
|
+
end
|
29
|
+
chain
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_hash
|
33
|
+
super.merge!(
|
34
|
+
sti_base: sti_base?,
|
35
|
+
sti_derived: sti_derived?,
|
36
|
+
sti_attribute_name: sti_attribute_name
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Traits
|
2
|
+
module DescendantsListing
|
3
|
+
def active_record_descendants_loaded?
|
4
|
+
!!@ar_descendants
|
5
|
+
end
|
6
|
+
|
7
|
+
def load_active_record_descendants!
|
8
|
+
# Railties are not necessary here
|
9
|
+
# Source: http://stackoverflow.com/questions/6497834/differences-between-railties-and-engines-in-ruby-on-rails-3
|
10
|
+
Rails::Engine.subclasses.map(&:instance).each { |i| i.eager_load! }
|
11
|
+
Rails.application.eager_load!
|
12
|
+
end
|
13
|
+
|
14
|
+
def invalidate_loaded_active_record_descendants!
|
15
|
+
@ar_descendants = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def active_record_descendants
|
19
|
+
@ar_descendants ||= begin
|
20
|
+
load_active_record_descendants!
|
21
|
+
descendants = ActiveRecord::Base.descendants
|
22
|
+
|
23
|
+
descendants.reject! { |ar| excluded_active_record_descendant?(ar) }
|
24
|
+
descendants
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def excluded_active_record_descendant?(model_class)
|
29
|
+
rules_for_excluding_active_records.any? do |rule|
|
30
|
+
case rule
|
31
|
+
when Regexp then model_class.name =~ rule
|
32
|
+
when String then model_class.name == rule
|
33
|
+
when Class then model_class == rule
|
34
|
+
else false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
extend DescendantsListing
|
41
|
+
|
42
|
+
# TODO Give a better name
|
43
|
+
mattr_accessor :rules_for_excluding_active_records
|
44
|
+
|
45
|
+
self.rules_for_excluding_active_records = [
|
46
|
+
'Globalize::ActiveRecord::Translation',
|
47
|
+
'ActiveRecord::SchemaMigration',
|
48
|
+
/\AHABTM/,
|
49
|
+
/::Translation\Z/
|
50
|
+
]
|
51
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Traits
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
isolate_namespace Traits
|
4
|
+
|
5
|
+
config.before_initialize do |app|
|
6
|
+
unless app.config.cache_classes
|
7
|
+
ActionDispatch::Reloader.to_prepare do
|
8
|
+
Traits.invalidate_loaded_active_record_descendants!
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/traits/list.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Traits
|
2
|
+
class List
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(list = [])
|
6
|
+
@list = list
|
7
|
+
end
|
8
|
+
|
9
|
+
def filter(hash)
|
10
|
+
select do |attr|
|
11
|
+
hash.all? do |method, expected|
|
12
|
+
returned = attr.send(method)
|
13
|
+
if expected.is_a?(Array)
|
14
|
+
expected.include?(returned)
|
15
|
+
else
|
16
|
+
returned == expected
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def first_where(hash)
|
23
|
+
find do |attr|
|
24
|
+
hash.all? do |method, expected|
|
25
|
+
returned = attr.send(method)
|
26
|
+
if expected.is_a?(Array)
|
27
|
+
expected.include?(returned)
|
28
|
+
else
|
29
|
+
returned == expected
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](arg)
|
36
|
+
by_name(arg)
|
37
|
+
end
|
38
|
+
|
39
|
+
def each(&block)
|
40
|
+
@list.each(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def by_name(name)
|
44
|
+
name = name.to_s.to_sym
|
45
|
+
find { |attr| attr.name == name }
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_hash
|
49
|
+
each_with_object({}) { |item, memo| memo[item.name] = item.to_hash }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/traits/model.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
module Traits
|
2
|
+
class Model < Base
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'traits/concerns/model/naming'
|
7
|
+
require 'traits/concerns/model/polymorphism'
|
8
|
+
require 'traits/concerns/model/sti'
|
9
|
+
require 'traits/concerns/model/querying'
|
10
|
+
require 'traits/concerns/model/essay_shortcuts'
|
11
|
+
|
12
|
+
module Traits
|
13
|
+
class Model
|
14
|
+
include Naming
|
15
|
+
include STI
|
16
|
+
include Polymorphism
|
17
|
+
include Querying
|
18
|
+
include EssayShortcuts
|
19
|
+
|
20
|
+
attr_reader :model_class
|
21
|
+
|
22
|
+
alias active_record model_class
|
23
|
+
alias klass model_class
|
24
|
+
|
25
|
+
def initialize(model_class)
|
26
|
+
@model_class = model_class
|
27
|
+
end
|
28
|
+
|
29
|
+
def attributes
|
30
|
+
@attributes ||= inspect_attributes
|
31
|
+
end
|
32
|
+
|
33
|
+
def associations
|
34
|
+
@associations ||= inspect_associations
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
class_name
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_hash
|
42
|
+
super.merge!(
|
43
|
+
attributes: attributes.to_hash,
|
44
|
+
associations: associations.to_hash
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
# TODO Store, Storage, Virtual attributes
|
51
|
+
def inspect_attributes
|
52
|
+
columns = model_class.columns_hash.values
|
53
|
+
|
54
|
+
if features.translates_with_globalize?
|
55
|
+
globalize = features.globalize
|
56
|
+
tr_class = globalize.model_class_for_translations
|
57
|
+
tr_columns_hash = tr_class.columns_hash
|
58
|
+
|
59
|
+
columns += globalize.translated_attribute_names.map do |el|
|
60
|
+
tr_columns_hash[el.to_s]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
list = columns.map do |column|
|
65
|
+
Traits::Attribute.new(model_class, column)
|
66
|
+
end
|
67
|
+
|
68
|
+
Traits::List.new(list)
|
69
|
+
end
|
70
|
+
|
71
|
+
def inspect_associations
|
72
|
+
list = model_class.reflections.map do |pair|
|
73
|
+
Traits::Association.new(model_class, pair.last)
|
74
|
+
end
|
75
|
+
Traits::List.new(list)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Traits
|
2
|
+
class UnidentifiedModelReference < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
module Utilities
|
6
|
+
def retrieve_model_class(obj)
|
7
|
+
if active_record_descendant?(obj)
|
8
|
+
obj
|
9
|
+
|
10
|
+
elsif active_record_instance?(obj)
|
11
|
+
obj.class
|
12
|
+
|
13
|
+
else
|
14
|
+
case obj
|
15
|
+
when Symbol then obj.to_s.camelize.constantize
|
16
|
+
when String then obj.camelize.constantize
|
17
|
+
when Model then obj.model_class
|
18
|
+
else raise UnidentifiedModelReference, obj
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def active_record_descendant?(obj)
|
24
|
+
obj.kind_of?(Class) && obj < ActiveRecord::Base
|
25
|
+
end
|
26
|
+
|
27
|
+
def active_record_instance?(obj)
|
28
|
+
obj.kind_of?(ActiveRecord::Base)
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid_active_record_identifier?(id)
|
32
|
+
id.kind_of?(String) || id.kind_of?(Numeric)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
extend Utilities
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-traits
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yaroslav Konoplov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.0
|
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.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: essay
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: essay-globalize
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: essay-carrierwave
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.0
|
83
|
+
description: Type information of ActiveRecord models, attributes and associations
|
84
|
+
email:
|
85
|
+
- yaroslav@inbox.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- activerecord-traits.gemspec
|
96
|
+
- lib/activerecord-traits.rb
|
97
|
+
- lib/traits/association.rb
|
98
|
+
- lib/traits/attribute.rb
|
99
|
+
- lib/traits/base.rb
|
100
|
+
- lib/traits/concerns/association/essay_shortcuts.rb
|
101
|
+
- lib/traits/concerns/association/intermediate.rb
|
102
|
+
- lib/traits/concerns/association/join.rb
|
103
|
+
- lib/traits/concerns/association/macro.rb
|
104
|
+
- lib/traits/concerns/association/members.rb
|
105
|
+
- lib/traits/concerns/association/naming.rb
|
106
|
+
- lib/traits/concerns/association/polymorphism.rb
|
107
|
+
- lib/traits/concerns/association/read_only.rb
|
108
|
+
- lib/traits/concerns/association/through.rb
|
109
|
+
- lib/traits/concerns/attribute/essay_shortcuts.rb
|
110
|
+
- lib/traits/concerns/attribute/key.rb
|
111
|
+
- lib/traits/concerns/attribute/naming.rb
|
112
|
+
- lib/traits/concerns/attribute/polymorphism.rb
|
113
|
+
- lib/traits/concerns/attribute/querying.rb
|
114
|
+
- lib/traits/concerns/attribute/sti.rb
|
115
|
+
- lib/traits/concerns/attribute/type.rb
|
116
|
+
- lib/traits/concerns/model/essay_shortcuts.rb
|
117
|
+
- lib/traits/concerns/model/naming.rb
|
118
|
+
- lib/traits/concerns/model/polymorphism.rb
|
119
|
+
- lib/traits/concerns/model/querying.rb
|
120
|
+
- lib/traits/concerns/model/sti.rb
|
121
|
+
- lib/traits/descendants_listing.rb
|
122
|
+
- lib/traits/engine.rb
|
123
|
+
- lib/traits/list.rb
|
124
|
+
- lib/traits/model.rb
|
125
|
+
- lib/traits/utilities.rb
|
126
|
+
- lib/traits/version.rb
|
127
|
+
homepage: http://github.com/yivo/activerecord-traits
|
128
|
+
licenses:
|
129
|
+
- MIT
|
130
|
+
metadata: {}
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubyforge_project:
|
147
|
+
rubygems_version: 2.4.8
|
148
|
+
signing_key:
|
149
|
+
specification_version: 4
|
150
|
+
summary: Type information of ActiveRecord models, attributes and associations
|
151
|
+
test_files: []
|