datamappify 0.60.0 → 0.70.0.beta1
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/.travis.yml +0 -1
- data/CHANGELOG.md +20 -0
- data/README.md +120 -3
- data/datamappify.gemspec +3 -3
- data/lib/datamappify/data/criteria/active_record/count.rb +0 -2
- data/lib/datamappify/data/criteria/active_record/criteria.rb +10 -0
- data/lib/datamappify/data/criteria/active_record/criteria_method.rb +65 -0
- data/lib/datamappify/data/criteria/active_record/find.rb +10 -2
- data/lib/datamappify/data/criteria/active_record/find_by_key.rb +4 -2
- data/lib/datamappify/data/criteria/active_record/limit.rb +10 -0
- data/lib/datamappify/data/criteria/active_record/match.rb +40 -0
- data/lib/datamappify/data/criteria/active_record/order.rb +41 -0
- data/lib/datamappify/data/criteria/active_record/rollback.rb +13 -0
- data/lib/datamappify/data/criteria/active_record/save.rb +1 -4
- data/lib/datamappify/data/criteria/active_record/save_by_key.rb +0 -1
- data/lib/datamappify/data/criteria/active_record/where.rb +18 -0
- data/lib/datamappify/data/criteria/common.rb +5 -2
- data/lib/datamappify/data/criteria/concerns/update_primary_record.rb +2 -0
- data/lib/datamappify/data/criteria/relational/concerns/find.rb +35 -0
- data/lib/datamappify/data/criteria/relational/concerns/find_by_key.rb +19 -0
- data/lib/datamappify/data/criteria/relational/criteria.rb +29 -0
- data/lib/datamappify/data/criteria/relational/{find_multiple.rb → criteria_base_method.rb} +2 -28
- data/lib/datamappify/data/criteria/relational/criteria_method.rb +44 -0
- data/lib/datamappify/data/criteria/relational/limit.rb +13 -0
- data/lib/datamappify/data/criteria/relational/save.rb +12 -0
- data/lib/datamappify/data/criteria/sequel/count.rb +0 -2
- data/lib/datamappify/data/criteria/sequel/criteria.rb +10 -0
- data/lib/datamappify/data/criteria/sequel/criteria_method.rb +51 -0
- data/lib/datamappify/data/criteria/sequel/find.rb +10 -2
- data/lib/datamappify/data/criteria/sequel/find_by_key.rb +4 -2
- data/lib/datamappify/data/criteria/sequel/limit.rb +10 -0
- data/lib/datamappify/data/criteria/sequel/match.rb +22 -0
- data/lib/datamappify/data/criteria/sequel/order.rb +22 -0
- data/lib/datamappify/data/criteria/sequel/rollback.rb +13 -0
- data/lib/datamappify/data/criteria/sequel/save.rb +1 -4
- data/lib/datamappify/data/criteria/sequel/save_by_key.rb +0 -1
- data/lib/datamappify/data/criteria/sequel/where.rb +18 -0
- data/lib/datamappify/data/errors.rb +8 -9
- data/lib/datamappify/data/mapper/attribute.rb +13 -33
- data/lib/datamappify/data/mapper.rb +13 -2
- data/lib/datamappify/data/provider/active_record.rb +8 -6
- data/lib/datamappify/data/provider/common_provider.rb +2 -2
- data/lib/datamappify/data/provider/sequel.rb +9 -6
- data/lib/datamappify/entity/association/reference.rb +63 -0
- data/lib/datamappify/entity/association/validation.rb +59 -0
- data/lib/datamappify/entity/association.rb +44 -0
- data/lib/datamappify/entity/{active_model/compatibility.rb → compatibility/active_model.rb} +2 -2
- data/lib/datamappify/entity/compatibility/active_record.rb +22 -0
- data/lib/datamappify/entity/compatibility/association/active_record.rb +43 -0
- data/lib/datamappify/entity/composable/attributes.rb +8 -16
- data/lib/datamappify/entity.rb +8 -6
- data/lib/datamappify/lazy/attributes_handler.rb +1 -1
- data/lib/datamappify/lazy.rb +0 -1
- data/lib/datamappify/repository/mapping_dsl.rb +9 -0
- data/lib/datamappify/repository/query_method/criteria.rb +21 -0
- data/lib/datamappify/repository/query_method/destroy.rb +1 -1
- data/lib/datamappify/repository/query_method/exists.rb +1 -1
- data/lib/datamappify/repository/query_method/find.rb +1 -9
- data/lib/datamappify/repository/query_method/method/multi_result_blender.rb +24 -0
- data/lib/datamappify/repository/query_method/method/reference_handler.rb +60 -0
- data/lib/datamappify/repository/query_method/method/source_attributes_walker.rb +19 -4
- data/lib/datamappify/repository/query_method/method.rb +58 -17
- data/lib/datamappify/repository/query_method/save.rb +4 -4
- data/lib/datamappify/repository/query_method/where_or_match.rb +24 -0
- data/lib/datamappify/repository/query_methods.rb +21 -5
- data/lib/datamappify/repository/unit_of_work/persistent_states/object.rb +2 -2
- data/lib/datamappify/version.rb +1 -1
- data/spec/entity/{relation_spec.rb → association/reference_spec.rb} +2 -2
- data/spec/repository/associations/has_many_spec.rb +259 -0
- data/spec/repository/dirty_tracking_spec.rb +68 -57
- data/spec/repository/finders/all_spec.rb +29 -0
- data/spec/repository/finders/criteria_spec.rb +61 -0
- data/spec/repository/finders/different_providers_spec.rb +81 -0
- data/spec/repository/finders/find_spec.rb +21 -0
- data/spec/repository/finders/match_spec.rb +28 -0
- data/spec/repository/finders/where_spec.rb +18 -0
- data/spec/repository/reverse_mapped_spec.rb +20 -4
- data/spec/support/entities/group.rb +4 -0
- data/spec/support/entities/super_user.rb +9 -0
- data/spec/support/entities/user.rb +5 -0
- data/spec/support/entities/user_info.rb +5 -0
- data/spec/support/repositories/active_record/group_repository.rb +4 -0
- data/spec/support/repositories/active_record/super_user_repository.rb +23 -0
- data/spec/support/repositories/active_record/user_repository.rb +6 -4
- data/spec/support/repositories/sequel/group_repository.rb +4 -0
- data/spec/support/repositories/sequel/super_user_repository.rb +23 -0
- data/spec/support/repositories/sequel/user_repository.rb +6 -4
- data/spec/support/shared/contexts.rb +8 -1
- data/spec/support/shared/examples/repository/finders/where_or_match.rb +130 -0
- data/spec/support/tables/active_record.rb +20 -10
- data/spec/support/tables/sequel.rb +20 -7
- data/spec/unit/entity/{relation_spec.rb → association/reference_spec.rb} +5 -5
- data/spec/unit/repository/query_method_spec.rb +9 -2
- metadata +74 -42
- data/lib/datamappify/data/criteria/active_record/find_multiple.rb +0 -40
- data/lib/datamappify/data/criteria/relational/find.rb +0 -25
- data/lib/datamappify/data/criteria/relational/find_by_key.rb +0 -18
- data/lib/datamappify/data/criteria/sequel/find_multiple.rb +0 -43
- data/lib/datamappify/entity/relation.rb +0 -61
- data/lib/datamappify/repository/query_method/find_multiple.rb +0 -28
- data/spec/repository/finders_spec.rb +0 -211
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 42a1f0451b17ea3e731eab36334ca301d2f82c54
|
|
4
|
+
data.tar.gz: fe1e60e36f3c5885829e0b3e109e1c6ae799572d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 32641a2d06c6f2eb8281422edee1e292bb414c932266fcf04b0fd4fa7b59ddb75ae370c4d30295fd08d4b84f5f555c8208efe0a43bdfe1847d3b7051976f9b81
|
|
7
|
+
data.tar.gz: 12f10eda25ac22872ca671ef411531709448d547822bad740ca822ac306c2958cebf788cd6749c64ec28300c7919356abddf70a6d86b424b518646c0c649c1c1
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
## master
|
|
2
2
|
|
|
3
|
+
## 0.70.0.beta1 [2013-09-26]
|
|
4
|
+
|
|
5
|
+
- Fixed dirty tracking for entities returned from `where` and `all`.
|
|
6
|
+
- Fixed a bug where in certain situations duplicated data records are created upon updating an entity.
|
|
7
|
+
- Fixed a bug where reversed mapping option `:via` generates wrong join queries.
|
|
8
|
+
- New API: Added `match` for repository.
|
|
9
|
+
- Added preliminary support for composed search criteria.
|
|
10
|
+
- Added `where` as a composable criteria.
|
|
11
|
+
- Added `match` as a composable criteria.
|
|
12
|
+
- Added `limit` as a composable criteria.
|
|
13
|
+
- Added `order` as a composable criteria.
|
|
14
|
+
- Added experimental support for associations.
|
|
15
|
+
- Added `reference_key` option to `map_attribute`.
|
|
16
|
+
- Added support for ActiveRecord-style attribute-nesting, e.g. `form.fields_for`.
|
|
17
|
+
- Added validation aggregation for associated entities.
|
|
18
|
+
- Added the ability to destroy associated items.
|
|
19
|
+
- Performance optimisations.
|
|
20
|
+
- Refactored the way Datamappify walks attributes to allow query optimisations.
|
|
21
|
+
- Optimised ActiveRecord queries for entities.
|
|
22
|
+
|
|
3
23
|
## 0.60.0 [2013-07-23]
|
|
4
24
|
|
|
5
25
|
- New API: Introduced `Datamappify.config` for configuring default behaviours.
|
data/README.md
CHANGED
|
@@ -27,17 +27,22 @@ Datamappify consists of three components:
|
|
|
27
27
|
|
|
28
28
|
Below is a high level and somewhat simplified overview of Datamappify's architecture.
|
|
29
29
|
|
|
30
|
-

|
|
31
31
|
|
|
32
32
|
Note: Datamappify is NOT affiliated with the [Datamapper](https://github.com/datamapper/) project.
|
|
33
33
|
|
|
34
34
|
### Built-in ORMs for Persistence
|
|
35
35
|
|
|
36
|
-
You may implement your own [data provider and
|
|
36
|
+
You may implement your own [data provider and criteria](lib/datamappify/data), but Datamappify comes with build-in support for the following ORMS:
|
|
37
37
|
|
|
38
38
|
- ActiveRecord
|
|
39
39
|
- Sequel
|
|
40
40
|
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- ruby 2.0+
|
|
44
|
+
- ActiveModel 4.0+
|
|
45
|
+
|
|
41
46
|
## Installation
|
|
42
47
|
|
|
43
48
|
Add this line to your application's Gemfile:
|
|
@@ -205,6 +210,12 @@ class UserRepository
|
|
|
205
210
|
#
|
|
206
211
|
# this is useful for mapping form fields (similar to ActiveRecord's nested attributes)
|
|
207
212
|
map_attribute :hobby_name, :to => 'Hobby#name', :via => :hobby_id
|
|
213
|
+
|
|
214
|
+
# by default, Datamappify maps attributes using an inferred reference (foreign) key,
|
|
215
|
+
# for example, the first mapping below will look for the `user_id` key in `Bio`,
|
|
216
|
+
# the second mapping below will look for the `person_id` key in `Bio` instead
|
|
217
|
+
map_attribute :bio, :to => 'Bio#body'
|
|
218
|
+
map_attribute :bio, :to => 'Bio#body', :reference_key => :person_id
|
|
208
219
|
end
|
|
209
220
|
```
|
|
210
221
|
|
|
@@ -284,10 +295,41 @@ users = UserRepository.all
|
|
|
284
295
|
|
|
285
296
|
Returns an array of entities.
|
|
286
297
|
|
|
298
|
+
##### Simple
|
|
299
|
+
|
|
287
300
|
```ruby
|
|
288
301
|
users = UserRepository.where(:first_name => 'Fred', :driver_license => 'AABBCCDD')
|
|
289
302
|
```
|
|
290
303
|
|
|
304
|
+
##### Match
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
users = UserRepository.match(:first_name => 'Fre%', :driver_license => '%bbcc%')
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
##### Advanced
|
|
311
|
+
|
|
312
|
+
You may compose search criteria via the `criteria` method.
|
|
313
|
+
|
|
314
|
+
```ruby
|
|
315
|
+
users = UserRepository.criteria(
|
|
316
|
+
:where => {
|
|
317
|
+
:first_name => 'Fred'
|
|
318
|
+
},
|
|
319
|
+
:order => {
|
|
320
|
+
:last_name => :asc
|
|
321
|
+
},
|
|
322
|
+
:limit => 10
|
|
323
|
+
)
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Currently implemented criteria options:
|
|
327
|
+
|
|
328
|
+
- where(Hash)
|
|
329
|
+
- match(Hash)
|
|
330
|
+
- order(Hash)
|
|
331
|
+
- limit(Integer)
|
|
332
|
+
|
|
291
333
|
_Note: it does not currently support searching attributes from different data providers._
|
|
292
334
|
|
|
293
335
|
#### Saving/updating entities
|
|
@@ -381,6 +423,76 @@ end
|
|
|
381
423
|
|
|
382
424
|
Note: Returning either `nil` or `false` from the callback will cancel all subsequent callbacks (and the action itself, if it's a `before_` callback).
|
|
383
425
|
|
|
426
|
+
### Association
|
|
427
|
+
|
|
428
|
+
Datamappify also supports entity association. It is experimental and it currently supports the following association types:
|
|
429
|
+
|
|
430
|
+
- belongs_to
|
|
431
|
+
- has_many
|
|
432
|
+
|
|
433
|
+
Set up your entities and repositories:
|
|
434
|
+
|
|
435
|
+
```ruby
|
|
436
|
+
# entities
|
|
437
|
+
|
|
438
|
+
class User
|
|
439
|
+
include Datamappify::Entity
|
|
440
|
+
|
|
441
|
+
has_many :posts, :via => Post
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
class Post
|
|
445
|
+
include Datamappify::Entity
|
|
446
|
+
|
|
447
|
+
belongs_to :user
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
# repositories
|
|
451
|
+
|
|
452
|
+
class UserRepository
|
|
453
|
+
include Datamappify::Repository
|
|
454
|
+
|
|
455
|
+
for_entity User
|
|
456
|
+
|
|
457
|
+
references :posts, :via => PostRepository
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
class PostRepository
|
|
461
|
+
include Datamappify::Repository
|
|
462
|
+
|
|
463
|
+
for_entity Post
|
|
464
|
+
end
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Usage examples:
|
|
468
|
+
|
|
469
|
+
```ruby
|
|
470
|
+
new_post = Post.new(post_attributes)
|
|
471
|
+
another_new_post = Post.new(post_attributes)
|
|
472
|
+
user = UserRepository.find(1)
|
|
473
|
+
user.posts = [new_post, another_new_post]
|
|
474
|
+
|
|
475
|
+
persisted_user = UserRepository.save!(user)
|
|
476
|
+
|
|
477
|
+
persisted_user.posts #=> an array of associated posts
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Nested attributes in forms
|
|
481
|
+
|
|
482
|
+
Like ActiveRecord and ActionView, Datamappify also supports nested attributes via `fields_for` or `simple_fields_for`.
|
|
483
|
+
|
|
484
|
+
```ruby
|
|
485
|
+
# slim template
|
|
486
|
+
|
|
487
|
+
= simple_form_for @post do |f|
|
|
488
|
+
= f.input :title
|
|
489
|
+
= f.input :body
|
|
490
|
+
|
|
491
|
+
= f.simple_fields_for :comment do |fp|
|
|
492
|
+
= fp.input :author_name
|
|
493
|
+
= fp.input :comment_body
|
|
494
|
+
```
|
|
495
|
+
|
|
384
496
|
### Default configuration
|
|
385
497
|
|
|
386
498
|
You may configure Datamappify's default behaviour. In Rails you would put it in an initializer file.
|
|
@@ -391,6 +503,11 @@ Datamappify.config do |c|
|
|
|
391
503
|
end
|
|
392
504
|
```
|
|
393
505
|
|
|
506
|
+
## API Documentation
|
|
507
|
+
|
|
508
|
+
- [Rubygem release version](http://rubydoc.info/gems/datamappify/frames)
|
|
509
|
+
- [Github master version](http://rubydoc.info/github/fredwu/datamappify/master/frames)
|
|
510
|
+
|
|
394
511
|
## More Reading
|
|
395
512
|
|
|
396
513
|
You may check out this [article](http://fredwu.me/post/54009567748/) for more examples.
|
|
@@ -415,7 +532,7 @@ Refer to [CHANGELOG](CHANGELOG.md).
|
|
|
415
532
|
|
|
416
533
|
- [Fred Wu](http://fredwu.me/) - author.
|
|
417
534
|
- [James Ladd](http://jamesladdcode.com/) for reviewing the code and giving advice on architectural decisions.
|
|
418
|
-
- [Locomote](http://www.locomote.com.au/) - where Datamappify is built and
|
|
535
|
+
- [Locomote](http://www.locomote.com.au/) - where Datamappify is built and used in our products.
|
|
419
536
|
- And with these [awesome contributors](https://github.com/fredwu/datamappify/contributors)!
|
|
420
537
|
|
|
421
538
|
## License
|
data/datamappify.gemspec
CHANGED
|
@@ -18,8 +18,8 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
-
spec.add_dependency "virtus", ">= 1.0.0.
|
|
22
|
-
spec.add_dependency "activemodel", "
|
|
21
|
+
spec.add_dependency "virtus", ">= 1.0.0.beta6", "< 2.0"
|
|
22
|
+
spec.add_dependency "activemodel", "~> 4.0.0"
|
|
23
23
|
spec.add_dependency "hooks", "~> 0.3.0"
|
|
24
24
|
|
|
25
25
|
spec.add_development_dependency "bundler", "~> 1.3"
|
|
@@ -33,6 +33,6 @@ Gem::Specification.new do |spec|
|
|
|
33
33
|
spec.add_development_dependency "coveralls"
|
|
34
34
|
spec.add_development_dependency "sqlite3"
|
|
35
35
|
spec.add_development_dependency "sequel"
|
|
36
|
-
spec.add_development_dependency "activerecord", "
|
|
36
|
+
spec.add_development_dependency "activerecord", "~> 4.0.0"
|
|
37
37
|
spec.add_development_dependency "database_cleaner", "~> 1.0.1"
|
|
38
38
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'datamappify/data/criteria/relational/criteria_method'
|
|
2
|
+
|
|
3
|
+
module Datamappify
|
|
4
|
+
module Data
|
|
5
|
+
module Criteria
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
class CriteriaMethod < Relational::CriteriaMethod
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# @param scope [ActiveRecord::Relation]
|
|
11
|
+
#
|
|
12
|
+
# @return [ActiveRecord::Relation]
|
|
13
|
+
def records_scope(scope = nil)
|
|
14
|
+
(scope || source_class).includes(associated.map(&:association_key))
|
|
15
|
+
.references(associated.map(&:association_key))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [Array<Attribute>]
|
|
19
|
+
def associated
|
|
20
|
+
attributes.select(&:secondary_attribute?)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @param primaries [Array<Attribute>]
|
|
24
|
+
#
|
|
25
|
+
# @param secondaries [Array<Attribute>]
|
|
26
|
+
#
|
|
27
|
+
# @return [Hash]
|
|
28
|
+
def structured_criteria
|
|
29
|
+
_criteria = {}
|
|
30
|
+
|
|
31
|
+
primaries.each do |primary|
|
|
32
|
+
_criteria[primary.source_attribute_key] = primary.value
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
secondaries.each do |secondary|
|
|
36
|
+
table_alias = detect_table_alias(secondary)
|
|
37
|
+
|
|
38
|
+
_criteria[table_alias] ||= {}
|
|
39
|
+
_criteria[table_alias][secondary.source_attribute_key] = secondary.value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
_criteria
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @see https://github.com/rails/rails/issues/12224
|
|
46
|
+
#
|
|
47
|
+
# @param [Attribute]
|
|
48
|
+
#
|
|
49
|
+
# @return [Symbol]
|
|
50
|
+
def detect_table_alias(attribute)
|
|
51
|
+
reflection = records_scope.send(:construct_join_dependency_for_association_find).join_parts.detect do |join|
|
|
52
|
+
join.try(:reflection).try(:name) == attribute.association_key
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if reflection
|
|
56
|
+
reflection.tables[0].try(:right) || attribute.source_table
|
|
57
|
+
else
|
|
58
|
+
attribute.source_table
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
require 'datamappify/data/criteria/relational/find'
|
|
1
|
+
require 'datamappify/data/criteria/relational/concerns/find'
|
|
2
|
+
require 'datamappify/data/criteria/active_record/criteria_method'
|
|
2
3
|
|
|
3
4
|
module Datamappify
|
|
4
5
|
module Data
|
|
5
6
|
module Criteria
|
|
6
7
|
module ActiveRecord
|
|
7
|
-
class Find <
|
|
8
|
+
class Find < CriteriaMethod
|
|
9
|
+
include Relational::Concerns::Find
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def record
|
|
14
|
+
records_scope.where(criteria).first
|
|
15
|
+
end
|
|
8
16
|
end
|
|
9
17
|
end
|
|
10
18
|
end
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
require 'datamappify/data/criteria/relational/find_by_key'
|
|
1
|
+
require 'datamappify/data/criteria/relational/concerns/find_by_key'
|
|
2
|
+
require 'datamappify/data/criteria/active_record/find'
|
|
2
3
|
|
|
3
4
|
module Datamappify
|
|
4
5
|
module Data
|
|
5
6
|
module Criteria
|
|
6
7
|
module ActiveRecord
|
|
7
|
-
class FindByKey <
|
|
8
|
+
class FindByKey < Find
|
|
9
|
+
include Relational::Concerns::FindByKey
|
|
8
10
|
end
|
|
9
11
|
end
|
|
10
12
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'datamappify/data/criteria/active_record/criteria_method'
|
|
2
|
+
|
|
3
|
+
module Datamappify
|
|
4
|
+
module Data
|
|
5
|
+
module Criteria
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
class Match < CriteriaMethod
|
|
8
|
+
# @param scope [ActiveRecord::Relation]
|
|
9
|
+
#
|
|
10
|
+
# @return [ActiveRecord::Relation]
|
|
11
|
+
def records(scope = nil)
|
|
12
|
+
records_scope(scope).where(string_criteria, *criteria.values)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# @return [String]
|
|
18
|
+
def string_criteria
|
|
19
|
+
structured_criteria.map do |column, value|
|
|
20
|
+
"lower(#{column}) LIKE lower(?)"
|
|
21
|
+
end.join(' AND ')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Hash]
|
|
25
|
+
def structured_criteria
|
|
26
|
+
Hash[*super.flat_map do |table, values|
|
|
27
|
+
if values.is_a?(Hash)
|
|
28
|
+
values.flat_map do |column, value|
|
|
29
|
+
["#{table}.#{column}", value]
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
["#{records_scope.table.name}.#{table}", values]
|
|
33
|
+
end
|
|
34
|
+
end]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'datamappify/data/criteria/active_record/criteria_method'
|
|
2
|
+
|
|
3
|
+
module Datamappify
|
|
4
|
+
module Data
|
|
5
|
+
module Criteria
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
class Order < CriteriaMethod
|
|
8
|
+
def initialize(*args)
|
|
9
|
+
super
|
|
10
|
+
|
|
11
|
+
validate_order_args
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param scope [ActiveRecord::Relation]
|
|
15
|
+
#
|
|
16
|
+
# @return [ActiveRecord::Relation]
|
|
17
|
+
def records(scope = nil)
|
|
18
|
+
structured_criteria.inject(records_scope(scope)) do |scope, (table, values)|
|
|
19
|
+
if values.is_a?(Hash)
|
|
20
|
+
values.inject(scope) do |s, (column, value)|
|
|
21
|
+
s.order("#{table}.#{column} #{value}")
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
scope.order(table => values)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
# @return [void]
|
|
32
|
+
def validate_order_args
|
|
33
|
+
unless (criteria.values - [:asc, :desc]).empty?
|
|
34
|
+
raise ArgumentError.new('Order direction should be :asc or :desc')
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require 'datamappify/data/criteria/relational/save'
|
|
2
1
|
require 'datamappify/data/criteria/concerns/update_primary_record'
|
|
3
2
|
|
|
4
3
|
module Datamappify
|
|
@@ -6,7 +5,7 @@ module Datamappify
|
|
|
6
5
|
module Criteria
|
|
7
6
|
module ActiveRecord
|
|
8
7
|
class Save < Relational::Save
|
|
9
|
-
|
|
8
|
+
prepend Concerns::UpdatePrimaryRecord
|
|
10
9
|
|
|
11
10
|
private
|
|
12
11
|
|
|
@@ -17,8 +16,6 @@ module Datamappify
|
|
|
17
16
|
|
|
18
17
|
def save(record)
|
|
19
18
|
record.update_attributes attributes_and_values
|
|
20
|
-
|
|
21
|
-
super
|
|
22
19
|
end
|
|
23
20
|
end
|
|
24
21
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'datamappify/data/criteria/active_record/criteria_method'
|
|
2
|
+
|
|
3
|
+
module Datamappify
|
|
4
|
+
module Data
|
|
5
|
+
module Criteria
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
class Where < CriteriaMethod
|
|
8
|
+
# @param scope [ActiveRecord::Relation]
|
|
9
|
+
#
|
|
10
|
+
# @return [ActiveRecord::Relation]
|
|
11
|
+
def records(scope = nil)
|
|
12
|
+
records_scope(scope).where(structured_criteria)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -32,6 +32,9 @@ module Datamappify
|
|
|
32
32
|
@source_class = source_class
|
|
33
33
|
@entity, @criteria, @attributes, @options = *args
|
|
34
34
|
@block = block
|
|
35
|
+
|
|
36
|
+
@criteria ||= {}
|
|
37
|
+
@options ||= {}
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
# Performs the action (defined by child method classes) with callbacks
|
|
@@ -76,7 +79,7 @@ module Datamappify
|
|
|
76
79
|
#
|
|
77
80
|
# @return [Symbol]
|
|
78
81
|
def key_name
|
|
79
|
-
primary_record? ? :id : any_attribute.
|
|
82
|
+
primary_record? || options[:via] ? :id : any_attribute.reference_key
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
# The value of {#key_name}
|
|
@@ -111,7 +114,7 @@ module Datamappify
|
|
|
111
114
|
#
|
|
112
115
|
# @return [Boolean]
|
|
113
116
|
def ignore?
|
|
114
|
-
attributes_and_values.empty?
|
|
117
|
+
attributes_and_values.empty? && !primary_record?
|
|
115
118
|
end
|
|
116
119
|
|
|
117
120
|
# Stores the attribute value in {Mapper::Attribute} for later use
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Datamappify
|
|
2
|
+
module Data
|
|
3
|
+
module Criteria
|
|
4
|
+
module Relational
|
|
5
|
+
module Concerns
|
|
6
|
+
module Find
|
|
7
|
+
def perform
|
|
8
|
+
record = records_scope.where(criteria).first
|
|
9
|
+
|
|
10
|
+
update_entity_with(record) if record
|
|
11
|
+
|
|
12
|
+
record
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def update_entity_with(record)
|
|
18
|
+
attributes.each do |attribute|
|
|
19
|
+
if attribute.secondary_attribute? || attribute.reverse_mapped?
|
|
20
|
+
update_entity_attribute_with(attribute, record.send(attribute.association_key))
|
|
21
|
+
else
|
|
22
|
+
update_entity_attribute_with(attribute, record)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def update_entity_attribute_with(attribute, record)
|
|
28
|
+
entity.send("#{attribute.name}=", record.send(attribute.source_attribute_name)) if record
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'datamappify/data/criteria/relational/concerns/set_criteria'
|
|
2
|
+
|
|
3
|
+
module Datamappify
|
|
4
|
+
module Data
|
|
5
|
+
module Criteria
|
|
6
|
+
module Relational
|
|
7
|
+
module Concerns
|
|
8
|
+
module FindByKey
|
|
9
|
+
include SetCriteria
|
|
10
|
+
|
|
11
|
+
def initialize(source_class, entity, attributes, options = {}, &block)
|
|
12
|
+
super(source_class, entity, nil, attributes, options, &block)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'datamappify/data/criteria/relational/criteria_base_method'
|
|
2
|
+
|
|
3
|
+
module Datamappify
|
|
4
|
+
module Data
|
|
5
|
+
module Criteria
|
|
6
|
+
module Relational
|
|
7
|
+
class Criteria < CriteriaBaseMethod
|
|
8
|
+
# @return
|
|
9
|
+
# a collection represents the records, e.g. `ActiveRecord::Relation` or `Sequel::DataSet`
|
|
10
|
+
def records
|
|
11
|
+
criteria.inject(nil) do |scope, (name, method_criteria)|
|
|
12
|
+
criteria_class(name).new(
|
|
13
|
+
source_class, entity, method_criteria, attributes, options
|
|
14
|
+
).records(scope)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# @return [Class]
|
|
21
|
+
# the criteria class, e.g. `Where` or `Limit`
|
|
22
|
+
def criteria_class(name)
|
|
23
|
+
self.class.name.deconstantize.constantize.const_get(name.to_s.classify)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|