activerecord-traits 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|