gdatastore_mapper 0.1.6 → 0.1.7
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/Gemfile +1 -0
- data/README.md +16 -0
- data/lib/gdatastore_mapper.rb +3 -0
- data/lib/gdatastore_mapper/base.rb +2 -0
- data/lib/gdatastore_mapper/locale/en.yml +5 -0
- data/lib/gdatastore_mapper/validations.rb +9 -0
- data/lib/gdatastore_mapper/validations/uniqueness_validator.rb +87 -0
- data/lib/gdatastore_mapper/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21b840689c7c1696a1d03a4e94780db8d29f6e4b
|
4
|
+
data.tar.gz: 0e55089540444e6f7d37dad011a6a52847d533c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab14005088a2fae2c1219b18224517e141e0402bc266a4653818d20b5201feaee2930b889438603367ab666499b9a59274cb40523f8accae25b1610bbd50574c
|
7
|
+
data.tar.gz: 1e2bcbdcd38a22b70eba990ef9571659ccf26aeac6ca135e7fc53cbc6cf24fa344b991e2bdc657d8235d36c545890f0ed31c672eac69419840355530184a8148
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -16,6 +16,7 @@ Once you install GdatastoreMapper you can use Google Cloud Datastore like Active
|
|
16
16
|
- [Associations](#associations)
|
17
17
|
- [One to Many](#one-to-many)
|
18
18
|
- [Callbacks](#callbacks)
|
19
|
+
- [Validations](#validations)
|
19
20
|
- [Contact](#contact)
|
20
21
|
- [Development](#development)
|
21
22
|
|
@@ -228,6 +229,21 @@ class Book
|
|
228
229
|
end
|
229
230
|
```
|
230
231
|
|
232
|
+
## Validations
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
class Author
|
236
|
+
include GdatastoreMapper::Base
|
237
|
+
|
238
|
+
attr_accessor :email
|
239
|
+
|
240
|
+
validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
|
241
|
+
validates :email, length: { in: 3..20 }
|
242
|
+
validates_uniqueness_of :email
|
243
|
+
end
|
244
|
+
```
|
245
|
+
|
246
|
+
|
231
247
|
## Contact
|
232
248
|
|
233
249
|
Please shoot me an e-mail if you find any issues, ideas and comments. shinya.kitamura.14@gmail.com
|
data/lib/gdatastore_mapper.rb
CHANGED
@@ -3,6 +3,7 @@ require 'gdatastore_mapper/scoping'
|
|
3
3
|
require 'gdatastore_mapper/associations'
|
4
4
|
require 'gdatastore_mapper/persistence'
|
5
5
|
require 'gdatastore_mapper/persistence/class_methods'
|
6
|
+
require 'gdatastore_mapper/validations'
|
6
7
|
|
7
8
|
module GdatastoreMapper
|
8
9
|
module Base
|
@@ -20,6 +21,7 @@ module GdatastoreMapper
|
|
20
21
|
extend Associations
|
21
22
|
include Persistence
|
22
23
|
extend Persistence::ClassMethods
|
24
|
+
extend Validations
|
23
25
|
end
|
24
26
|
|
25
27
|
module ClassMethods
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module GdatastoreMapper
|
2
|
+
module Validations
|
3
|
+
class UniquenessValidator < ActiveModel::EachValidator # :nodoc:
|
4
|
+
def initialize(options)
|
5
|
+
if options[:conditions] && !options[:conditions].respond_to?(:call)
|
6
|
+
raise ArgumentError, "#{options[:conditions]} was passed as :conditions but is not callable. " \
|
7
|
+
"Pass a callable instead: `conditions: -> { where(approved: true) }`"
|
8
|
+
end
|
9
|
+
super({ case_sensitive: true }.merge!(options))
|
10
|
+
@klass = options[:class]
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate_each(record, attribute, value)
|
14
|
+
finder_class = find_finder_class_for(record).first
|
15
|
+
# value = map_enum_attribute(finder_class, attribute, value)
|
16
|
+
|
17
|
+
relation = build_relation(finder_class, attribute, value)
|
18
|
+
if record.persisted?
|
19
|
+
relation = detect_relation(relation, record.id)
|
20
|
+
# if finder_class.primary_key
|
21
|
+
# relation = relation.where.not(finder_class.primary_key => record.id_in_database || record.id)
|
22
|
+
# else
|
23
|
+
# raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
|
24
|
+
# end
|
25
|
+
end
|
26
|
+
relation = scope_relation(record, relation)
|
27
|
+
relation = relation.merge(options[:conditions]) if options[:conditions]
|
28
|
+
|
29
|
+
if relation.present?
|
30
|
+
error_options = options.except(:case_sensitive, :scope, :conditions)
|
31
|
+
error_options[:value] = value
|
32
|
+
|
33
|
+
record.errors.add(attribute, :taken, error_options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def find_finder_class_for(record)
|
39
|
+
class_hierarchy = [record.class]
|
40
|
+
|
41
|
+
while class_hierarchy.first != @klass
|
42
|
+
class_hierarchy.unshift(class_hierarchy.first.superclass)
|
43
|
+
end
|
44
|
+
|
45
|
+
# class_hierarchy.detect { |klass| !klass.abstract_class? }
|
46
|
+
class_hierarchy
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_relation(klass, attribute, value)
|
50
|
+
# klass.unscoped.where!({ attribute => value }, options)
|
51
|
+
klass.where({ attribute => value })
|
52
|
+
end
|
53
|
+
|
54
|
+
def scope_relation(record, relation)
|
55
|
+
Array(options[:scope]).each do |scope_item|
|
56
|
+
scope_value = if record.class._reflect_on_association(scope_item)
|
57
|
+
record.association(scope_item).reader
|
58
|
+
else
|
59
|
+
record._read_attribute(scope_item)
|
60
|
+
end
|
61
|
+
relation = relation.where(scope_item => scope_value)
|
62
|
+
end
|
63
|
+
|
64
|
+
relation
|
65
|
+
end
|
66
|
+
|
67
|
+
def map_enum_attribute(klass, attribute, value)
|
68
|
+
mapping = klass.defined_enums[attribute.to_s]
|
69
|
+
value = mapping[value] if value && mapping
|
70
|
+
value
|
71
|
+
end
|
72
|
+
|
73
|
+
def detect_relation(records, id)
|
74
|
+
records.select do |record|
|
75
|
+
record.id != id
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module ClassMethods
|
81
|
+
def validates_uniqueness_of(*attr_names)
|
82
|
+
validates_with UniquenessValidator, _merge_attributes(attr_names)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gdatastore_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shinya Kitamura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-cloud-datastore
|
@@ -116,11 +116,14 @@ files:
|
|
116
116
|
- lib/gdatastore_mapper/associations.rb
|
117
117
|
- lib/gdatastore_mapper/associations/has_many.rb
|
118
118
|
- lib/gdatastore_mapper/base.rb
|
119
|
+
- lib/gdatastore_mapper/locale/en.yml
|
119
120
|
- lib/gdatastore_mapper/persistence.rb
|
120
121
|
- lib/gdatastore_mapper/persistence/class_methods.rb
|
121
122
|
- lib/gdatastore_mapper/relation.rb
|
122
123
|
- lib/gdatastore_mapper/scoping.rb
|
123
124
|
- lib/gdatastore_mapper/session.rb
|
125
|
+
- lib/gdatastore_mapper/validations.rb
|
126
|
+
- lib/gdatastore_mapper/validations/uniqueness_validator.rb
|
124
127
|
- lib/gdatastore_mapper/version.rb
|
125
128
|
- rails_example/.gitignore
|
126
129
|
- rails_example/Gemfile
|