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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6ba358c0a8c21946a0c0c38cb4449b26cc9705c
4
- data.tar.gz: f8cad2beee638c900f6418fa06a9e2b8336acc3b
3
+ metadata.gz: 21b840689c7c1696a1d03a4e94780db8d29f6e4b
4
+ data.tar.gz: 0e55089540444e6f7d37dad011a6a52847d533c2
5
5
  SHA512:
6
- metadata.gz: 972712b50dd7ccdd03be8d5e557271e577dda9d4de3aa8dff47cab82313fbc9b2d8b74a03160f51f35d0fe0743ee59252229f35246b2d2bfb290c6abdc1aa12e
7
- data.tar.gz: b945a9e7168001e830bed9cb08bedb23812127950e5fe55e56ff18ab908db287f9679f4a1b568056afb6ec9b7f4947683753ea0f36539bb393f9fda42396363e
6
+ metadata.gz: ab14005088a2fae2c1219b18224517e141e0402bc266a4653818d20b5201feaee2930b889438603367ab666499b9a59274cb40523f8accae25b1610bbd50574c
7
+ data.tar.gz: 1e2bcbdcd38a22b70eba990ef9571659ccf26aeac6ca135e7fc53cbc6cf24fa344b991e2bdc657d8235d36c545890f0ed31c672eac69419840355530184a8148
data/Gemfile CHANGED
@@ -11,4 +11,5 @@ group :development, :test do
11
11
  gem 'pry-byebug'
12
12
  gem 'shoulda-matchers', '~> 3.1.1'
13
13
  gem 'faker'
14
+ gem 'rspec-retry'
14
15
  end
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
@@ -6,3 +6,6 @@ require 'gdatastore_mapper/version'
6
6
  require 'gdatastore_mapper/session'
7
7
  require 'gdatastore_mapper/base'
8
8
 
9
+ ActiveSupport.on_load(:i18n) do
10
+ I18n.load_path << File.dirname(__FILE__) + "/gdatastore_mapper/locale/en.yml"
11
+ end
@@ -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,5 @@
1
+ en:
2
+ errors:
3
+ messages:
4
+ required: "must exist"
5
+ taken: "has already been taken"
@@ -0,0 +1,9 @@
1
+ require 'gdatastore_mapper/validations/uniqueness_validator'
2
+
3
+ module GdatastoreMapper
4
+ module Validations
5
+ def validates_uniqueness_of(*args)
6
+ validates_with(UniquenessValidator, _merge_attributes(args))
7
+ end
8
+ end
9
+ end
@@ -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
+
@@ -1,3 +1,3 @@
1
1
  module GdatastoreMapper
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
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.6
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-22 00:00:00.000000000 Z
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