datamappify 0.60.0 → 0.70.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
![](http://i.imgur.com/
|
30
|
+
![](http://i.imgur.com/BvtEO1u.png)
|
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
|