column_namespace 0.0.1
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 +11 -0
- data/.rspec +3 -0
- data/.travis.yml +33 -0
- data/Appraisals +24 -0
- data/Gemfile +6 -0
- data/README.md +118 -0
- data/Rakefile +6 -0
- data/column_namespace.gemspec +36 -0
- data/gemfiles/4.2.gemfile +8 -0
- data/gemfiles/5.0.gemfile +8 -0
- data/gemfiles/5.1.gemfile +8 -0
- data/gemfiles/5.2.gemfile +8 -0
- data/gemfiles/6.0.gemfile +8 -0
- data/lib/column_namespace.rb +70 -0
- data/lib/column_namespace/version.rb +5 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 851cc54004fb49af7ab29acf1b0adb5d887e54246397058aed37de7f3761b5f7
|
4
|
+
data.tar.gz: 18f116ac4a131c58a27aeea0baf575bc7e5c392ac1e4b667bc614b955d538bcb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 19e4d8ef5552f60155fe65ec73f0a704aa3e2d18b9311c06ecddce80fca924f6ae2c1a8e58f06d2b169d804264a759893e5ed80c03213d2adf3bac4f93258782
|
7
|
+
data.tar.gz: a6e06fd4d6a22db02df72eb27c5e6596888d0cfdf46b95011200bc5f34b91628177e59b147c3778671b537937a52d6fe87448248a6fe9ee8d4273d182c0252b2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
---
|
2
|
+
sudo: false
|
3
|
+
language: ruby
|
4
|
+
cache: bundler
|
5
|
+
rvm:
|
6
|
+
- 2.3
|
7
|
+
- 2.4
|
8
|
+
- 2.5
|
9
|
+
- 2.6
|
10
|
+
- 2.7
|
11
|
+
|
12
|
+
before_install:
|
13
|
+
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
14
|
+
- gem install bundler -v '< 2'
|
15
|
+
|
16
|
+
gemfile:
|
17
|
+
- gemfiles/4.2.gemfile
|
18
|
+
- gemfiles/5.0.gemfile
|
19
|
+
- gemfiles/5.1.gemfile
|
20
|
+
- gemfiles/5.2.gemfile
|
21
|
+
- gemfiles/6.0.gemfile
|
22
|
+
|
23
|
+
matrix:
|
24
|
+
exclude:
|
25
|
+
- rvm: 2.3
|
26
|
+
gemfile: gemfiles/6.0.gemfile
|
27
|
+
- rvm: 2.4
|
28
|
+
gemfile: gemfiles/6.0.gemfile
|
29
|
+
- rvm: 2.7
|
30
|
+
gemfile: gemfiles/4.2.gemfile
|
31
|
+
|
32
|
+
notifications:
|
33
|
+
email: false
|
data/Appraisals
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
appraise "4.2" do
|
2
|
+
gem "activerecord", "~> 4.2.11"
|
3
|
+
gem "sqlite3", "~> 1.3.6"
|
4
|
+
end
|
5
|
+
|
6
|
+
appraise "5.0" do
|
7
|
+
gem "activerecord", "~> 5.0.7"
|
8
|
+
gem "sqlite3", "~> 1.3.6"
|
9
|
+
end
|
10
|
+
|
11
|
+
appraise "5.1" do
|
12
|
+
gem "activerecord", "~> 5.1.7"
|
13
|
+
gem "sqlite3"
|
14
|
+
end
|
15
|
+
|
16
|
+
appraise "5.2" do
|
17
|
+
gem "activerecord", "~> 5.2.4"
|
18
|
+
gem "sqlite3"
|
19
|
+
end
|
20
|
+
|
21
|
+
appraise "6.0" do
|
22
|
+
gem "activerecord", "~> 6.0.2"
|
23
|
+
gem "sqlite3"
|
24
|
+
end
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# Column Namespace
|
2
|
+
|
3
|
+
[](https://travis-ci.org/sshaw/column_namespace)
|
4
|
+
|
5
|
+
Group columns on your Active Record model under a "namespace method".
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
Given the following database table (note the columns beginning with `"external_"`):
|
10
|
+
```sql
|
11
|
+
create table products (
|
12
|
+
id int unsigned,
|
13
|
+
name varchar(255),
|
14
|
+
external_product_id bigint unsigned,
|
15
|
+
external_variant_id bigint unsigned,
|
16
|
+
external_metafield_id bigint unsigned
|
17
|
+
)
|
18
|
+
```
|
19
|
+
|
20
|
+
Add the following to its model:
|
21
|
+
```ruby
|
22
|
+
class Product < ApplicationRecord
|
23
|
+
extend ColumnNamespace
|
24
|
+
column_namespace "external_"
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
Now you can do:
|
29
|
+
```ruby
|
30
|
+
product = Product.new(:external => { :product_id => 123, :variant_id => 999 })
|
31
|
+
|
32
|
+
p product.external.product_id # 123
|
33
|
+
p product.external.variant_id # 999
|
34
|
+
|
35
|
+
product.save!
|
36
|
+
|
37
|
+
p product[:external_variant_id] # 999
|
38
|
+
|
39
|
+
product.external.variant_id = 21341510
|
40
|
+
product.save!
|
41
|
+
|
42
|
+
product[:external_variant_id] # 21341510
|
43
|
+
|
44
|
+
product = Product.last
|
45
|
+
p product.external.to_h # { :product_id => 1, :metafield_id => nil, ... }
|
46
|
+
```
|
47
|
+
|
48
|
+
Alternatively you can specify the namespace method and its columns:
|
49
|
+
```ruby
|
50
|
+
class Product < ApplicationRecord
|
51
|
+
extend ColumnNamespace
|
52
|
+
column_namespace :some_method => %w[name external_product_id]
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
This gives you:
|
57
|
+
```ruby
|
58
|
+
product = Product.new(:some_method => { :name => "sshaw", :external_product_id => 99 })
|
59
|
+
product.some_method.name = nil
|
60
|
+
product.some_method.external_product_id = 1_000_00
|
61
|
+
|
62
|
+
# etc... same stuff as before
|
63
|
+
```
|
64
|
+
|
65
|
+
|
66
|
+
### But Isn't This What `composed_of` Does‽
|
67
|
+
|
68
|
+
Yes, but, no!
|
69
|
+
|
70
|
+
`composed_of` forces you to create and explicitly use a "value object". In some cases (like in the above examples)
|
71
|
+
this class is artificial. It doesn't exist in your domain –nor should it!
|
72
|
+
|
73
|
+
Using the above examples with `composed_of` do not work. Instead of:
|
74
|
+
```ruby
|
75
|
+
product = Product.last
|
76
|
+
product.external.product_id = 510
|
77
|
+
product.save! # does not save 510
|
78
|
+
```
|
79
|
+
|
80
|
+
You'd have to write:
|
81
|
+
```ruby
|
82
|
+
product = Product.last
|
83
|
+
product.external = External.new(:product_id => 510)
|
84
|
+
product.save!
|
85
|
+
```
|
86
|
+
|
87
|
+
The same applies for validation:
|
88
|
+
```ruby
|
89
|
+
# In Product:
|
90
|
+
# validates :external_product_id, :numericality => { :greater_than => -1 }
|
91
|
+
product = Product.last
|
92
|
+
product.external.product_id = -1
|
93
|
+
product.valid? # true
|
94
|
+
```
|
95
|
+
|
96
|
+
You'd have to assign an instance of `External` to `product.external` for this to work.
|
97
|
+
|
98
|
+
## Installation
|
99
|
+
|
100
|
+
Add this line to your application's Gemfile:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
gem "column_namespace"
|
104
|
+
```
|
105
|
+
|
106
|
+
Or:
|
107
|
+
|
108
|
+
```
|
109
|
+
gem install column_namespace
|
110
|
+
```
|
111
|
+
|
112
|
+
## Author
|
113
|
+
|
114
|
+
Skye Shaw [skye.shaw AT gmail.com]
|
115
|
+
|
116
|
+
## License
|
117
|
+
|
118
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "column_namespace/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "column_namespace"
|
8
|
+
spec.version = ColumnNamespace::VERSION
|
9
|
+
spec.authors = ["Skye Shaw"]
|
10
|
+
spec.email = ["skye.shaw@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Group columns on your Active Record model under a "namespace method".}
|
13
|
+
spec.homepage = "https://github.com/sshaw/column_namespace"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/sshaw/column_namespace/issues"
|
18
|
+
spec.metadata["changelog_uri"] = "https://github.com/sshaw/column_namespace/blob/master/Changes"
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_dependency "class2", "~> 0.5.2"
|
30
|
+
spec.add_dependency "activerecord", ">= 4.2", "< 7"
|
31
|
+
|
32
|
+
spec.add_development_dependency "appraisal"
|
33
|
+
spec.add_development_dependency "bundler"
|
34
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
35
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
36
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "column_namespace/version"
|
4
|
+
require "class2"
|
5
|
+
|
6
|
+
module ColumnNamespace
|
7
|
+
def column_namespace(options)
|
8
|
+
if options.is_a?(Hash)
|
9
|
+
namespace_via_list(options)
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
Array.wrap(options).each { |prefix| namespace_via_prefix(prefix) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def namespace_via_list(config)
|
19
|
+
config.each do |namespace, columns|
|
20
|
+
unknown = columns.map(&:to_s) - column_names
|
21
|
+
raise "unknown column(s): #{unknown.to_sentence}" unless unknown.empty?
|
22
|
+
|
23
|
+
klass = namespace.to_s.classify
|
24
|
+
class2 self, klass => columns
|
25
|
+
|
26
|
+
class_eval(<<-CODE)
|
27
|
+
def #{namespace}
|
28
|
+
@__#{namespace} ||= #{klass}.new(attributes.slice(*#{columns}))
|
29
|
+
end
|
30
|
+
|
31
|
+
def #{namespace}=(instance_or_attributes)
|
32
|
+
@__#{namespace} = instance_or_attributes.is_a?(Hash) ? #{klass}.new(instance_or_attributes) : instance_or_attributes
|
33
|
+
end
|
34
|
+
|
35
|
+
before_validation do
|
36
|
+
#{namespace}.to_h.each do |key, value|
|
37
|
+
self[key] = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
CODE
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def namespace_via_prefix(prefix)
|
45
|
+
columns = column_names.select { |name| name.starts_with?(prefix) }
|
46
|
+
raise "No attributes found with prefix #{prefix}" unless columns.any?
|
47
|
+
|
48
|
+
method = prefix.sub(/[^[:alnum]]*\z/i, "")
|
49
|
+
klass = method.classify
|
50
|
+
prefix_regex = /\A#{Regexp.quote(prefix)}[^[:alnum:]]*/
|
51
|
+
|
52
|
+
class2 self, klass => columns.map { |name| name.sub(prefix_regex, "") }
|
53
|
+
|
54
|
+
class_eval(<<-CODE)
|
55
|
+
def #{method}
|
56
|
+
@__#{method} ||= #{klass}.new(attributes.slice(*#{columns}).transform_keys! { |k| k.sub(/#{prefix_regex}/, "") })
|
57
|
+
end
|
58
|
+
|
59
|
+
def #{method}=(instance_or_attributes)
|
60
|
+
@__#{method} = instance_or_attributes.is_a?(Hash) ? #{klass}.new(instance_or_attributes) : instance_or_attributes
|
61
|
+
end
|
62
|
+
|
63
|
+
before_validation do
|
64
|
+
#{method}.to_h.each do |key, value|
|
65
|
+
self["#{prefix}\#{key}"] = value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
CODE
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: column_namespace
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Skye Shaw
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: class2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.2'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '7'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '4.2'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '7'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: appraisal
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: bundler
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rake
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 12.3.3
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 12.3.3
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rspec
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '3.0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '3.0'
|
103
|
+
description:
|
104
|
+
email:
|
105
|
+
- skye.shaw@gmail.com
|
106
|
+
executables: []
|
107
|
+
extensions: []
|
108
|
+
extra_rdoc_files: []
|
109
|
+
files:
|
110
|
+
- ".gitignore"
|
111
|
+
- ".rspec"
|
112
|
+
- ".travis.yml"
|
113
|
+
- Appraisals
|
114
|
+
- Gemfile
|
115
|
+
- README.md
|
116
|
+
- Rakefile
|
117
|
+
- column_namespace.gemspec
|
118
|
+
- gemfiles/4.2.gemfile
|
119
|
+
- gemfiles/5.0.gemfile
|
120
|
+
- gemfiles/5.1.gemfile
|
121
|
+
- gemfiles/5.2.gemfile
|
122
|
+
- gemfiles/6.0.gemfile
|
123
|
+
- lib/column_namespace.rb
|
124
|
+
- lib/column_namespace/version.rb
|
125
|
+
homepage: https://github.com/sshaw/column_namespace
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata:
|
129
|
+
homepage_uri: https://github.com/sshaw/column_namespace
|
130
|
+
bug_tracker_uri: https://github.com/sshaw/column_namespace/issues
|
131
|
+
changelog_uri: https://github.com/sshaw/column_namespace/blob/master/Changes
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
require_paths:
|
135
|
+
- lib
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 2.7.6
|
149
|
+
signing_key:
|
150
|
+
specification_version: 4
|
151
|
+
summary: Group columns on your Active Record model under a "namespace method".
|
152
|
+
test_files: []
|