belongs_to_polymorphic 0.1.1 → 0.1.2
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 +4 -4
- data/README.md +20 -8
- data/lib/belongs_to_polymorphic/associations.rb +60 -0
- data/lib/belongs_to_polymorphic/version.rb +3 -1
- data/lib/belongs_to_polymorphic.rb +8 -40
- metadata +44 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72a7fc1cfa599890817ed887d3026bfe38a379e04011086704e9c011d493cacb
|
4
|
+
data.tar.gz: 2d4f9da5474e4c6832f5bfd8c3414392f979018b3474c817ca65ab57a708c1fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 281b3a89834676d4e7b70d8349be4a235b79de2933f5dd4e930fda96f84f7d3c3ed442ba089077afa56786bc8b1c21374fea0e0fcadcea5f2eac52fbefd560bc
|
7
|
+
data.tar.gz: a97f89bc4f284cb7cb0eeacc339461ac5b329a937bfd919156da702fd1507234567154488faf42ef41edcaa0bb8f5e48c909baeee10f5b309752e7c301c72efc
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
An ActiveRecord extension defining the concept *belongs to polymorphic*, which allows us to use polymorphic associations (belongs_to) and restrict which classes are allowed to be related to.
|
4
4
|
|
5
5
|
|
6
|
-
The base idea
|
6
|
+
The base idea was taken from this blogpost: [Improve ActiveRecord Polymorphic Associations - Head of engineering at Product Hunt](https://blog.rstankov.com/allowed-class-names-in-activerecord-polymorphic-associations/).
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
@@ -27,16 +27,16 @@ In your model you can do the following:
|
|
27
27
|
|
28
28
|
```ruby
|
29
29
|
class Book < ActiveRecord::Base
|
30
|
-
belongs_to_polymorphic :owner, allowed_classes: [
|
30
|
+
belongs_to_polymorphic :owner, allowed_classes: [User, Publisher]
|
31
31
|
end
|
32
32
|
```
|
33
33
|
|
34
34
|
You can also add any options that a regular `belongs_to` with `polymorphic: true` could use.
|
35
35
|
|
36
|
-
By using this you create a polymorphic relationship in `Book` called `
|
36
|
+
By using this you create a polymorphic relationship in `Book` called `owner` which can be a `User` or a `Publisher`.
|
37
37
|
If you try to set an `owner` from a class rather than the aforementioend ones, it will return the following error:
|
38
38
|
```ruby
|
39
|
-
|
39
|
+
#ActiveRecord::RecordInvalid: Validation failed: Owner type OtherThing class is not an allowed class.
|
40
40
|
```
|
41
41
|
|
42
42
|
It also automatically adds some helpers
|
@@ -53,14 +53,26 @@ Instance:
|
|
53
53
|
|
54
54
|
```ruby
|
55
55
|
class Book < ActiveRecord::Base
|
56
|
-
belongs_to_polymorphic :owner, allowed_classes: [Publisher::
|
56
|
+
belongs_to_polymorphic :owner, allowed_classes: [Publisher::User, Publisher]
|
57
57
|
end
|
58
58
|
```
|
59
59
|
|
60
60
|
It will allow you to use:
|
61
|
-
- `Book.with_owner(Publisher::
|
62
|
-
- `Book.
|
63
|
-
- `book.
|
61
|
+
- `Book.with_owner(Publisher::User)`
|
62
|
+
- `Book.with_owner_publisher_user`
|
63
|
+
- `book.owner_type_publisher_user?`
|
64
|
+
|
65
|
+
## I18n
|
66
|
+
|
67
|
+
Belongs to Polymoprhic uses I18n to define the not allowed class error. To customize it, you can set up your locale file:
|
68
|
+
|
69
|
+
```yaml
|
70
|
+
en:
|
71
|
+
belongs_to_polymoprhic:
|
72
|
+
errors:
|
73
|
+
messages:
|
74
|
+
class_not_allowed: "%{class} is not an allowed class"
|
75
|
+
```
|
64
76
|
|
65
77
|
## License
|
66
78
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BelongsToPolymorphic
|
4
|
+
module Associations
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def belongs_to_polymorphic(name, allowed_classes:, **options)
|
11
|
+
allowed_classes = Array.new(allowed_classes)
|
12
|
+
belongs_to name, polymorphic: true, **options
|
13
|
+
validates "#{name}_type", inclusion: {
|
14
|
+
in: classes(allowed_classes, options),
|
15
|
+
message: I18n.t('belongs_to_polymorphic.errors.messages.class_not_allowed',
|
16
|
+
class: '%<value>s')
|
17
|
+
}
|
18
|
+
|
19
|
+
define_singleton_method("#{name}_types") { allowed_classes }
|
20
|
+
define_generic_finder_method(name)
|
21
|
+
define_scopes_and_instance_methods(name, allowed_classes)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def classes(allowed_classes, options)
|
27
|
+
classes = allowed_classes.map(&:name)
|
28
|
+
classes << nil if options[:optional]
|
29
|
+
classes
|
30
|
+
end
|
31
|
+
|
32
|
+
# Generates a generic finder method
|
33
|
+
def define_generic_finder_method(name)
|
34
|
+
define_singleton_method("with_#{name}") do |type|
|
35
|
+
type = case type
|
36
|
+
when Class then type.name
|
37
|
+
when String then type
|
38
|
+
else type.class.name
|
39
|
+
end
|
40
|
+
where("#{name}_type" => type)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def define_scopes_and_instance_methods(name, allowed_classes)
|
45
|
+
allowed_classes.each do |model|
|
46
|
+
model_name = model.name
|
47
|
+
model_name_sanitized = model_name.underscore.tr('/', '_')
|
48
|
+
# generates scope for each allowed class
|
49
|
+
scope "with_#{name}_#{model_name_sanitized}",
|
50
|
+
-> { where("#{name}_type" => model_name) }
|
51
|
+
|
52
|
+
# generates instance method for each allowed class to check if type is that class
|
53
|
+
define_method("#{name}_type_#{model_name_sanitized}?") do
|
54
|
+
public_send("#{name}_type") == model_name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,44 +1,12 @@
|
|
1
|
-
|
2
|
-
require 'active_support/concern'
|
3
|
-
|
4
|
-
module BelongsToPolymorphic
|
5
|
-
extend ActiveSupport::Concern
|
1
|
+
# frozen_string_literal: true
|
6
2
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
allowed_classes = Array.new(allowed_classes)
|
11
|
-
belongs_to name, polymorphic: true, **options
|
12
|
-
classes = allowed_classes.map(&:name)
|
13
|
-
classes << nil if options[:optional]
|
14
|
-
validates "#{name}_type", inclusion: { in: classes }
|
15
|
-
define_singleton_method("#{name}_types") { allowed_classes }
|
16
|
-
|
17
|
-
# generates a generic finder method
|
18
|
-
define_singleton_method("with_#{name}") do |type|
|
19
|
-
type = case type
|
20
|
-
when Class then type.name
|
21
|
-
when String then type
|
22
|
-
else type.class.name
|
23
|
-
end
|
24
|
-
where("#{name}_type" => type)
|
25
|
-
end
|
3
|
+
require 'active_record'
|
4
|
+
require 'belongs_to_polymorphic/version'
|
5
|
+
require 'belongs_to_polymorphic/associations'
|
26
6
|
|
27
|
-
|
28
|
-
model_name = model.name
|
29
|
-
model_name_sanitized = model_name.underscore.tr('/', '_')
|
30
|
-
# generates scope for each allowed class
|
31
|
-
scope "with_#{name}_#{model_name_sanitized}",
|
32
|
-
-> { where("#{name}_type" => model_name) }
|
7
|
+
I18n.load_path << Dir["#{File.expand_path('config/locales')}/*.yml"]
|
33
8
|
|
34
|
-
|
35
|
-
define_method("#{name}_type_#{model_name_sanitized}?") do
|
36
|
-
public_send("#{name}_type") == model_name
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
# rubocop:enable Metrics/AbcSize
|
41
|
-
end
|
42
|
-
end
|
9
|
+
module BelongsToPolymorphic; end
|
43
10
|
|
44
|
-
ActiveRecord::Base
|
11
|
+
# Extend ActiveRecord::Base with belongs to polymorphic associations
|
12
|
+
ActiveRecord::Base.include BelongsToPolymorphic::Associations
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: belongs_to_polymorphic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolas Erlichman
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,42 +16,62 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.
|
20
|
-
|
19
|
+
version: '5.2'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '8.0'
|
23
|
+
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.
|
29
|
+
version: '5.2'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '8.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: database_cleaner-active_record
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 1.8.0
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.8.0
|
27
47
|
- !ruby/object:Gem::Dependency
|
28
48
|
name: rake
|
29
49
|
requirement: !ruby/object:Gem::Requirement
|
30
50
|
requirements:
|
31
|
-
- - "
|
51
|
+
- - "~>"
|
32
52
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
53
|
+
version: 13.0.6
|
34
54
|
type: :development
|
35
55
|
prerelease: false
|
36
56
|
version_requirements: !ruby/object:Gem::Requirement
|
37
57
|
requirements:
|
38
|
-
- - "
|
58
|
+
- - "~>"
|
39
59
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
60
|
+
version: 13.0.6
|
41
61
|
- !ruby/object:Gem::Dependency
|
42
62
|
name: rspec
|
43
63
|
requirement: !ruby/object:Gem::Requirement
|
44
64
|
requirements:
|
45
|
-
- - "
|
65
|
+
- - "~>"
|
46
66
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
67
|
+
version: 3.11.0
|
48
68
|
type: :development
|
49
69
|
prerelease: false
|
50
70
|
version_requirements: !ruby/object:Gem::Requirement
|
51
71
|
requirements:
|
52
|
-
- - "
|
72
|
+
- - "~>"
|
53
73
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
74
|
+
version: 3.11.0
|
55
75
|
- !ruby/object:Gem::Dependency
|
56
76
|
name: simplecov
|
57
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,25 +87,19 @@ dependencies:
|
|
67
87
|
- !ruby/object:Gem::Version
|
68
88
|
version: 0.17.1
|
69
89
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
90
|
+
name: sqlite3
|
71
91
|
requirement: !ruby/object:Gem::Requirement
|
72
92
|
requirements:
|
73
|
-
- - "
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '5.2'
|
76
|
-
- - "<"
|
93
|
+
- - "~>"
|
77
94
|
- !ruby/object:Gem::Version
|
78
|
-
version:
|
79
|
-
type: :
|
95
|
+
version: 1.4.2
|
96
|
+
type: :development
|
80
97
|
prerelease: false
|
81
98
|
version_requirements: !ruby/object:Gem::Requirement
|
82
99
|
requirements:
|
83
|
-
- - "
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '5.2'
|
86
|
-
- - "<"
|
100
|
+
- - "~>"
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
102
|
+
version: 1.4.2
|
89
103
|
description: ActiveRecord extension - Polymorphic associations with restricted allowed
|
90
104
|
classes.
|
91
105
|
email:
|
@@ -97,6 +111,7 @@ files:
|
|
97
111
|
- LICENSE.txt
|
98
112
|
- README.md
|
99
113
|
- lib/belongs_to_polymorphic.rb
|
114
|
+
- lib/belongs_to_polymorphic/associations.rb
|
100
115
|
- lib/belongs_to_polymorphic/version.rb
|
101
116
|
homepage: https://github.com/gogrow-dev/belongs_to_polymorphic
|
102
117
|
licenses:
|
@@ -104,7 +119,7 @@ licenses:
|
|
104
119
|
metadata:
|
105
120
|
source_code_uri: https://github.com/gogrow-dev/belongs_to_polymorphic
|
106
121
|
rubygems_mfa_required: 'true'
|
107
|
-
post_install_message:
|
122
|
+
post_install_message:
|
108
123
|
rdoc_options: []
|
109
124
|
require_paths:
|
110
125
|
- lib
|
@@ -119,8 +134,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
134
|
- !ruby/object:Gem::Version
|
120
135
|
version: '0'
|
121
136
|
requirements: []
|
122
|
-
rubygems_version: 3.
|
123
|
-
signing_key:
|
137
|
+
rubygems_version: 3.3.7
|
138
|
+
signing_key:
|
124
139
|
specification_version: 4
|
125
140
|
summary: ActiveRecord extension - Polymorphic associations with restricted allowed
|
126
141
|
classes.
|