active_repository 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +55 -31
- data/active_repository.gemspec +1 -1
- data/lib/active_repository/adapters/default_adapter.rb +11 -11
- data/lib/active_repository/adapters/mongoid_adapter.rb +2 -2
- data/lib/active_repository/adapters/persistence_adapter.rb +1 -5
- data/lib/active_repository/associations.rb +77 -23
- data/lib/active_repository/base.rb +35 -19
- data/lib/active_repository/finders.rb +1 -1
- data/lib/active_repository/result_set.rb +11 -3
- data/lib/active_repository/uniqueness.rb +3 -50
- data/lib/active_repository/version.rb +1 -1
- data/lib/active_repository/write_support.rb +1 -1
- data/lib/active_repository/writers.rb +4 -4
- data/spec/active_repository/associations_spec.rb +51 -8
- data/spec/active_repository/base_spec.rb +50 -6
- data/spec/active_repository/result_set_spec.rb +49 -8
- data/spec/support/shared_examples.rb +33 -10
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4e5ff5317491bb88742d8486544d1ed31a60181
|
4
|
+
data.tar.gz: 0acb8ac3cd7df689eb9c811b6b7c4b04683f46eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94c813e8ebae6c3837693041bd3780b557f9e52e759b0d81e7be118568202cae8962b1d70ea2173cc80f5f5ed34bd5f75b32682a523d455fce6c052ba7794328
|
7
|
+
data.tar.gz: cc1b12d0d86d3399318bc4f0b2dd673baedf1dfbcff94f96f98a290488daf677baf5722926de82200d7a675ce7b58db083b397fb119f40d3034f9ce984492b64
|
data/README.md
CHANGED
@@ -2,27 +2,27 @@
|
|
2
2
|
|
3
3
|
[[![Coverage Status](https://coveralls.io/repos/efreesen/active_repository/badge.png)](https://coveralls.io/r/efreesen/active_repository)![Build Status](https://secure.travis-ci.org/efreesen/active_repository.png)](http://travis-ci.org/efreesen/active_repository)[![Dependency Status](https://gemnasium.com/efreesen/active_repository.png)](https://gemnasium.com/efreesen/active_repository) [![Code Climate](https://codeclimate.com/github/efreesen/active_repository.png)](https://codeclimate.com/github/efreesen/active_repository)
|
4
4
|
|
5
|
-
ActiveRepository was designed so you can build your Business Models without
|
5
|
+
ActiveRepository was designed so you can build your Business Models without any dependence on persistence. It by default saves your data in memory using ActiveHash (https://github.com/zilkey/active_hash). Then when you decide which kind of persistence you want to use, all you have to do is connect ActiveRepository with it.
|
6
6
|
|
7
|
-
Currently it only works with ActiveRecord and/or Mongoid.
|
7
|
+
Currently it only works with ActiveRecord and/or Mongoid, but it is easy to add adaptors. If you need any adaptor, just open an issue!
|
8
8
|
|
9
|
-
|
9
|
+
With it you can always run your tests directly into memory, boosting your suite's speed. If you need to run all tests or a single spec using persistence you can do it too.
|
10
10
|
|
11
|
-
|
11
|
+
Check out our benchmark:
|
12
12
|
|
13
13
|
* **ActiveRepository:**
|
14
|
-
Finished in **
|
15
|
-
|
14
|
+
Finished in **2.96** seconds
|
15
|
+
90 examples, 0 failures
|
16
16
|
|
17
17
|
* **ActiveRecord:**
|
18
|
-
Finished in **
|
19
|
-
|
18
|
+
Finished in **6.29** seconds
|
19
|
+
90 examples, 0 failures
|
20
20
|
|
21
21
|
* **Mongoid:**
|
22
|
-
Finished in **
|
23
|
-
|
22
|
+
Finished in **7.01** seconds
|
23
|
+
90 examples, 0 failures
|
24
24
|
|
25
|
-
|
25
|
+
In ActiveRepository you will always work with ActiveRepository objects, so you can create relations between ActiveRecord and Mongoid seamlessly. You can even use Mongoid's Origin query format or keep with the SQL format no matter what kind of persistence you are using, we convert it for you!
|
26
26
|
|
27
27
|
## Requirements
|
28
28
|
|
@@ -46,45 +46,69 @@ Or install it yourself as:
|
|
46
46
|
|
47
47
|
## Usage
|
48
48
|
|
49
|
-
To use it
|
49
|
+
To use it your class should inherit ActiveRepository::Base:
|
50
50
|
|
51
|
-
class
|
51
|
+
class UserRepository < ActiveRepository::Base
|
52
|
+
persistence_class = User
|
53
|
+
save_in_memory = false
|
52
54
|
end
|
53
55
|
|
54
|
-
ActiveRepository::Base has two class attributes to help it identify where it is going to persist data
|
56
|
+
ActiveRepository::Base has two class attributes to help it identify where it is going to persist data.
|
55
57
|
|
56
|
-
###
|
58
|
+
###persistence_class
|
57
59
|
|
58
|
-
This attribute is used to identify the class responsible for persisting data, it should be the ActiveRecord model or the Mongoid Document.
|
60
|
+
This attribute is used to identify the class responsible for persisting data, it should be the ActiveRecord model or the Mongoid Document. Let's say your ActiveRecord Model is called User, using the example above, all database actions would be passed to User class, and you can extract all your business logic to the UserRepository class.
|
59
61
|
|
60
62
|
###save_in_memory
|
61
63
|
|
62
|
-
This attribute is used to persist data directly into memory. When set to true, it ignores the
|
64
|
+
This attribute is used to persist data directly into memory. When set to true, it ignores the persistence_class attribute and save in memory. If set to false it goes back to persistence_class. You can use it to keep your tests saving in memory, or set it to false manually if a test need to touch the database.
|
63
65
|
|
64
|
-
|
66
|
+
If using Rails you can even tie it to your environment, so in tests it is set to true and otherwise it is set to false, like this:
|
65
67
|
|
66
|
-
class
|
67
|
-
|
68
|
-
|
68
|
+
class UserRepository < ActiveRepository::Base
|
69
|
+
persistence_class = User
|
70
|
+
save_in_memory = Rails.env.test?
|
71
|
+
end
|
72
|
+
|
73
|
+
###postfix
|
74
|
+
|
75
|
+
ActiveRepository also has an attribute to help you keep your code clean, the postfix. It can be used to define a pattern for Persistence classes so you don't need to keep declaring it everywhere. When using it, your persistence_class name would be \<repository_class_name\> + \<postfix\>.
|
76
|
+
|
77
|
+
Here is an example, let's say you have a bunch of Mongoid Documents and you don't want to declare persistence_class for each repository. So you can create a Base Repository and declare the postfix:
|
69
78
|
|
70
|
-
|
71
|
-
|
79
|
+
class BaseRepository < ActiveRepository::Base
|
80
|
+
# Defines the postfix
|
81
|
+
postfix "Document"
|
82
|
+
|
83
|
+
save_in_memory = false
|
72
84
|
end
|
73
85
|
|
74
|
-
|
86
|
+
You have to rename your Mongoid Documents to the defined pattern, like this:
|
75
87
|
|
76
|
-
class
|
77
|
-
|
78
|
-
|
88
|
+
class UserDocument
|
89
|
+
include Mongoid::Document
|
90
|
+
end
|
79
91
|
|
80
|
-
|
92
|
+
And you can create your repositories inheriting from BaseRepository:
|
81
93
|
|
82
|
-
|
94
|
+
class User < BaseRepository
|
83
95
|
end
|
84
96
|
|
85
|
-
|
97
|
+
Then you are good to go!!!
|
98
|
+
|
99
|
+
###Setting fields
|
100
|
+
|
101
|
+
After defining the persistence options, you can set the fields it is going to use:
|
102
|
+
|
103
|
+
class UserRepository < ActiveRepository::Base
|
104
|
+
# Defines the fields of the class
|
105
|
+
fields :name, :email, :birthdate
|
106
|
+
|
107
|
+
persistence_class = User
|
108
|
+
save_in_memory = false
|
109
|
+
end
|
86
110
|
|
87
|
-
|
111
|
+
Now you are all set and ready to go. Your business logic is decoupled from the persistence tier!
|
88
112
|
|
89
113
|
## Contributing
|
90
114
|
|
data/active_repository.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |gem|
|
|
31
31
|
|
32
32
|
gem.add_runtime_dependency(%q<active_hash>, [">= 1.2.3"])
|
33
33
|
gem.add_runtime_dependency(%q<activemodel>, [">= 3.2"])
|
34
|
-
gem.add_runtime_dependency(%q<sql_query_executor>, [">= 0.3.
|
34
|
+
gem.add_runtime_dependency(%q<sql_query_executor>, [">= 0.3.4"])
|
35
35
|
gem.add_development_dependency(%q<pry>)
|
36
36
|
gem.add_development_dependency(%q<rspec>, [">= 2.2.0"])
|
37
37
|
gem.add_development_dependency(%q<activerecord>, [">= 3.2"])
|
@@ -1,42 +1,42 @@
|
|
1
1
|
class DefaultAdapter
|
2
2
|
class << self
|
3
3
|
def all(klass)
|
4
|
-
klass.
|
4
|
+
klass.persistence_class.all
|
5
5
|
end
|
6
6
|
|
7
7
|
def delete(klass, id)
|
8
|
-
object = klass.
|
8
|
+
object = klass.persistence_class.where(id: id).first
|
9
9
|
object.delete if object
|
10
10
|
end
|
11
11
|
|
12
12
|
def delete_all(klass)
|
13
|
-
klass.
|
13
|
+
klass.persistence_class.delete_all
|
14
14
|
end
|
15
15
|
|
16
16
|
def exists?(klass, id)
|
17
|
-
klass.
|
17
|
+
klass.persistence_class.exists?(id)
|
18
18
|
end
|
19
19
|
|
20
20
|
def find(klass, id)
|
21
21
|
id = normalize_id(id) if id
|
22
22
|
|
23
|
-
klass.
|
23
|
+
klass.persistence_class.find(id)
|
24
24
|
end
|
25
25
|
|
26
26
|
def first(klass)
|
27
|
-
klass.
|
27
|
+
klass.persistence_class.first
|
28
28
|
end
|
29
29
|
|
30
30
|
def last(klass)
|
31
|
-
klass.
|
31
|
+
klass.persistence_class.last
|
32
32
|
end
|
33
33
|
|
34
34
|
def create(klass, attributes)
|
35
|
-
object = klass.
|
35
|
+
object = klass.persistence_class.create(attributes)
|
36
36
|
end
|
37
37
|
|
38
38
|
def update_attribute(klass, id, key, value)
|
39
|
-
object = id.nil? ? klass.
|
39
|
+
object = id.nil? ? klass.persistence_class.new(key.to_sym => value) : klass.persistence_class.find(id)
|
40
40
|
|
41
41
|
ret = object.update_attribute(key, value)
|
42
42
|
|
@@ -44,7 +44,7 @@ class DefaultAdapter
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def update_attributes(klass, id, attributes)
|
47
|
-
object = id.nil? ? klass.
|
47
|
+
object = id.nil? ? klass.persistence_class.new : klass.persistence_class.find(id)
|
48
48
|
|
49
49
|
ret = object.update_attributes(attributes)
|
50
50
|
|
@@ -52,7 +52,7 @@ class DefaultAdapter
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def where(klass, query)
|
55
|
-
klass.
|
55
|
+
klass.persistence_class.where(query.to_sql)
|
56
56
|
end
|
57
57
|
|
58
58
|
private
|
@@ -11,7 +11,7 @@ class MongoidAdapter < DefaultAdapter
|
|
11
11
|
# end
|
12
12
|
|
13
13
|
def exists?(klass, id)
|
14
|
-
klass.
|
14
|
+
klass.persistence_class.where(:id => id).present?
|
15
15
|
end
|
16
16
|
|
17
17
|
# def find(klass, id)
|
@@ -47,7 +47,7 @@ class MongoidAdapter < DefaultAdapter
|
|
47
47
|
# end
|
48
48
|
|
49
49
|
def where(klass, query)
|
50
|
-
klass.
|
50
|
+
klass.persistence_class.where(query.selector)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -4,7 +4,7 @@ require 'active_repository/adapters/mongoid_adapter'
|
|
4
4
|
class PersistenceAdapter
|
5
5
|
class << self
|
6
6
|
def get_adapter(klass)
|
7
|
-
modules = klass.
|
7
|
+
modules = klass.persistence_class.included_modules.map(&:to_s)
|
8
8
|
if modules.include?("Mongoid::Document")
|
9
9
|
MongoidAdapter
|
10
10
|
else
|
@@ -56,8 +56,4 @@ class PersistenceAdapter
|
|
56
56
|
get_adapter(klass).where(klass, args)
|
57
57
|
end
|
58
58
|
end
|
59
|
-
|
60
|
-
def method_missing(sym, *args, &block)
|
61
|
-
get_adapter(args.first).send(sym, args)
|
62
|
-
end
|
63
59
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
# Author:: Caio Torres (mailto:efreesen@gmail.com)
|
4
4
|
# License:: GPL
|
5
5
|
|
6
|
+
|
6
7
|
module ActiveRepository
|
7
8
|
module Associations
|
8
9
|
def self.included(base)
|
@@ -14,33 +15,23 @@ module ActiveRepository
|
|
14
15
|
def has_many(association_id, options = {})
|
15
16
|
define_method(association_id) do
|
16
17
|
options = {
|
17
|
-
class_name: association_id.to_s.classify
|
18
|
-
foreign_key: self.class.to_s.foreign_key
|
18
|
+
class_name: association_id.to_s.classify
|
19
19
|
}.merge(options)
|
20
20
|
|
21
|
+
foreign_key = self.class.to_s.foreign_key
|
21
22
|
klass = options[:class_name].constantize
|
22
|
-
objects = []
|
23
23
|
|
24
|
-
klass.where(
|
24
|
+
klass.where(foreign_key => id)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
# Defines "has one" type relation between ActiveRepository objects
|
29
29
|
def has_one(association_id, options = {})
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
foreign_key: self.class.to_s.foreign_key
|
34
|
-
}.merge(options)
|
35
|
-
|
36
|
-
scope = options[:class_name].constantize
|
37
|
-
|
38
|
-
scope = scope.where(options[:conditions]) if options[:conditions]
|
39
|
-
|
40
|
-
send_params = scope.respond_to?(:find_by) ? ["find_by", id: id] : ["find_by_id", id]
|
30
|
+
options = {
|
31
|
+
class_name: association_id.to_s.classify
|
32
|
+
}.merge(options)
|
41
33
|
|
42
|
-
|
43
|
-
end
|
34
|
+
has_one_methods(association_id, options)
|
44
35
|
end
|
45
36
|
|
46
37
|
# Defines "belongs to" type relation between ActiveRepository objects
|
@@ -52,22 +43,85 @@ module ActiveRepository
|
|
52
43
|
|
53
44
|
field options[:foreign_key].to_sym
|
54
45
|
|
46
|
+
belongs_to_methods(association_id, options)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def has_one_methods(association_id, options)
|
51
|
+
define_has_one_method(association_id, options)
|
52
|
+
define_has_one_setter(association_id, options)
|
53
|
+
define_has_one_create(association_id, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
def belongs_to_methods(association_id, options)
|
57
|
+
define_belongs_to_method(association_id, options)
|
58
|
+
define_belongs_to_setter(association_id, options)
|
59
|
+
define_belongs_to_create(association_id, options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def define_has_one_method(association_id, options)
|
63
|
+
define_method(association_id) do
|
64
|
+
foreign_key = self.class.to_s.foreign_key
|
65
|
+
klass = options[:class_name].constantize
|
66
|
+
|
67
|
+
klass.where(foreign_key => self.id).first
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def define_has_one_setter(association_id, options)
|
72
|
+
define_method("#{association_id}=") do |object|
|
73
|
+
primary_key = self.send(self.class.primary_key)
|
74
|
+
foreign_key = self.class.to_s.foreign_key
|
75
|
+
association = self.send(association_id)
|
76
|
+
|
77
|
+
association.update_attribute(foreign_key, nil) if association
|
78
|
+
|
79
|
+
object.update_attribute(foreign_key, primary_key) if object
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def define_has_one_create(association_id, options)
|
84
|
+
define_method("create_#{association_id}") do |attributes|
|
85
|
+
primary_key = self.send(self.class.primary_key)
|
86
|
+
foreign_key = self.class.to_s.foreign_key
|
87
|
+
association = self.send(association_id)
|
88
|
+
klass = options[:class_name].constantize
|
89
|
+
|
90
|
+
association.update_attribute(foreign_key, nil) if
|
91
|
+
self.send("#{association_id}=", nil)
|
92
|
+
|
93
|
+
klass.create(attributes.merge(foreign_key => primary_key))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def define_belongs_to_method(association_id, options)
|
55
98
|
define_method(association_id) do
|
56
99
|
klass = options[:class_name].constantize
|
57
|
-
|
100
|
+
foreign_key = send(options[:foreign_key])
|
58
101
|
|
59
|
-
|
60
|
-
object = klass.respond_to?(:find_by) ? klass.find_by(id: id) : klass.find_by_id(id)
|
61
|
-
else
|
62
|
-
nil
|
63
|
-
end
|
102
|
+
klass.where(klass.primary_key => foreign_key).first
|
64
103
|
end
|
104
|
+
end
|
65
105
|
|
106
|
+
def define_belongs_to_setter(association_id, options)
|
66
107
|
define_method("#{association_id}=") do |new_value|
|
67
108
|
attributes.delete(association_id.to_sym)
|
68
109
|
send("#{options[:foreign_key]}=", (new_value.try(:id) ? new_value.id : new_value))
|
69
110
|
end
|
70
111
|
end
|
112
|
+
|
113
|
+
def define_belongs_to_create(association_id, options)
|
114
|
+
define_method("create_#{association_id}") do |attributes|
|
115
|
+
klass = options[:class_name].constantize
|
116
|
+
|
117
|
+
object = klass.create(attributes)
|
118
|
+
|
119
|
+
self.update_attribute(options[:foreign_key], object.id)
|
120
|
+
|
121
|
+
object
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
71
125
|
end
|
72
126
|
end
|
73
127
|
end
|
@@ -47,8 +47,8 @@ module ActiveRepository
|
|
47
47
|
# Using ActiveRecord/Mongoid to persist objects:
|
48
48
|
#
|
49
49
|
# class SaveInORMOrODMTest < ActiveRepository::Base
|
50
|
-
# SaveInORMOrODMTest.
|
51
|
-
# SaveInORMOrODMTest.
|
50
|
+
# SaveInORMOrODMTest.persistence_class = ORMOrODMModelClass
|
51
|
+
# SaveInORMOrODMTest.save_in_memory = false
|
52
52
|
# end
|
53
53
|
#
|
54
54
|
# Author:: Caio Torres (mailto:efreesen@gmail.com)
|
@@ -62,12 +62,11 @@ module ActiveRepository
|
|
62
62
|
include ActiveRepository::Associations
|
63
63
|
include ActiveRepository::Writers::InstanceMethods
|
64
64
|
|
65
|
-
class_attribute :model_class, :
|
65
|
+
class_attribute :model_class, :instance_writer => false
|
66
|
+
class_attribute :save_in_memory, :postfix, :instance_writer => true
|
66
67
|
|
67
68
|
after_validation :set_timestamps
|
68
69
|
|
69
|
-
self.save_in_memory = true if self.save_in_memory == nil
|
70
|
-
|
71
70
|
# Returns all persisted objects
|
72
71
|
def self.all
|
73
72
|
(repository? ? super : PersistenceAdapter.all(self).map { |object| serialize!(object.attributes) })
|
@@ -88,10 +87,16 @@ module ActiveRepository
|
|
88
87
|
repository? ? find_by(id: id).present? : PersistenceAdapter.exists?(self, id)
|
89
88
|
end
|
90
89
|
|
90
|
+
def self.persistence_class
|
91
|
+
return self if save_in_memory? || (postfix.nil? && self.model_class.nil?)
|
92
|
+
return "#{self}#{postfix.classify}".constantize if postfix.present?
|
93
|
+
self.model_class.to_s.constantize
|
94
|
+
end
|
95
|
+
|
91
96
|
# Returns the Class responsible for persisting the objects
|
92
97
|
def self.get_model_class
|
93
|
-
|
94
|
-
|
98
|
+
puts '[deprecation warning] This method is going to be deprecated, use "persistence_class" instead.'
|
99
|
+
persistence_class
|
95
100
|
end
|
96
101
|
|
97
102
|
# Searches all objects that matches #field_name field with the #args value(s)
|
@@ -121,21 +126,29 @@ module ActiveRepository
|
|
121
126
|
end
|
122
127
|
end
|
123
128
|
|
124
|
-
# Returns
|
129
|
+
# Returns an array with the field names of the Class
|
125
130
|
def self.serialized_attributes
|
126
131
|
field_names.map &:to_s
|
127
132
|
end
|
128
133
|
|
134
|
+
def self.persistence_class=(value)
|
135
|
+
self.model_class = value
|
136
|
+
end
|
137
|
+
|
129
138
|
# Sets the class attribute model_class, responsible to persist the ActiveRepository objects
|
130
139
|
def self.set_model_class(value)
|
131
|
-
|
140
|
+
puts '[deprecation warning] This method is going to be deprecated, use "persistence_class=" instead.'
|
141
|
+
persistence_class = value
|
142
|
+
end
|
132
143
|
|
133
|
-
|
144
|
+
def self.save_in_memory?
|
145
|
+
self.save_in_memory == nil ? true : self.save_in_memory
|
134
146
|
end
|
135
147
|
|
136
148
|
# Sets the class attribute save_in_memory, set it to true to ignore model_class attribute
|
137
149
|
# and persist objects in memory
|
138
150
|
def self.set_save_in_memory(value)
|
151
|
+
puts '[deprecation warning] This method is going to be deprecated, use "save_in_memory=" instead.'
|
139
152
|
self.save_in_memory = value
|
140
153
|
end
|
141
154
|
|
@@ -151,8 +164,6 @@ module ActiveRepository
|
|
151
164
|
|
152
165
|
result_set = ActiveRepository::ResultSet.new(self)
|
153
166
|
|
154
|
-
# binding.pry
|
155
|
-
|
156
167
|
result_set.where(args)
|
157
168
|
|
158
169
|
# if repository?
|
@@ -168,8 +179,13 @@ module ActiveRepository
|
|
168
179
|
# end
|
169
180
|
end
|
170
181
|
|
182
|
+
def persistence_class
|
183
|
+
self.class.persistence_class
|
184
|
+
end
|
185
|
+
|
171
186
|
def get_model_class
|
172
|
-
|
187
|
+
puts '[deprecation warning] This method is going to be deprecated, use "persistence_class" instead.'
|
188
|
+
self.class.persistence_class
|
173
189
|
end
|
174
190
|
|
175
191
|
# Persists the object using the class defined on the model_class attribute, if none defined it
|
@@ -183,15 +199,15 @@ module ActiveRepository
|
|
183
199
|
# Gathers the persisted object from database and updates self with it's attributes.
|
184
200
|
def reload
|
185
201
|
object = self.id.present? ?
|
186
|
-
|
202
|
+
persistence_class.where(id: self.id).first_or_initialize :
|
187
203
|
self
|
188
204
|
|
189
205
|
serialize! object.attributes
|
190
206
|
end
|
191
207
|
|
192
208
|
def save(force=false)
|
193
|
-
if self.class ==
|
194
|
-
object =
|
209
|
+
if self.class == persistence_class
|
210
|
+
object = persistence_class.where(id: self.id).first_or_initialize
|
195
211
|
|
196
212
|
if force || self.id.nil?
|
197
213
|
self.id = nil if self.id.nil?
|
@@ -223,10 +239,10 @@ module ActiveRepository
|
|
223
239
|
# Find related object on the database and updates it with attributes in self, if it didn't
|
224
240
|
# find it on database it creates a new one.
|
225
241
|
def convert(attribute="id")
|
226
|
-
klass =
|
242
|
+
klass = persistence_class
|
227
243
|
object = klass.where(attribute.to_sym => self.send(attribute)).first
|
228
244
|
|
229
|
-
object ||=
|
245
|
+
object ||= persistence_class.new
|
230
246
|
|
231
247
|
attributes = self.attributes
|
232
248
|
|
@@ -243,7 +259,7 @@ module ActiveRepository
|
|
243
259
|
|
244
260
|
private
|
245
261
|
def self.repository?
|
246
|
-
self ==
|
262
|
+
self == persistence_class
|
247
263
|
end
|
248
264
|
|
249
265
|
# Updates created_at and updated_at
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Module containing methods responsible for searching ActiveRepository objects
|
2
2
|
module ActiveRepository #:nodoc:
|
3
3
|
module Finders #:nodoc:
|
4
|
-
# Searches for
|
4
|
+
# Searches for an object containing the id in #id
|
5
5
|
def find(id)
|
6
6
|
begin
|
7
7
|
if repository?
|
@@ -2,13 +2,21 @@ class ActiveRepository::ResultSet
|
|
2
2
|
def initialize(klass, query={}, attributes={})
|
3
3
|
@klass = klass
|
4
4
|
convert_query(query)
|
5
|
-
@attributes =
|
5
|
+
@attributes = attributes.merge(SqlQueryExecutor::Query::Normalizers::QueryNormalizer.attributes_from_query(query))
|
6
6
|
end
|
7
7
|
|
8
8
|
def all
|
9
9
|
@query ? get_result(@query) : @klass.all
|
10
10
|
end
|
11
11
|
|
12
|
+
def build(attributes)
|
13
|
+
@klass.new(@attributes.merge(attributes))
|
14
|
+
end
|
15
|
+
|
16
|
+
def create(attributes)
|
17
|
+
@klass.create(@attributes.merge(attributes))
|
18
|
+
end
|
19
|
+
|
12
20
|
def count
|
13
21
|
all.size
|
14
22
|
end
|
@@ -51,7 +59,7 @@ class ActiveRepository::ResultSet
|
|
51
59
|
|
52
60
|
private
|
53
61
|
def convert_query(query)
|
54
|
-
@query = SqlQueryExecutor::Query::QueryNormalizer.clean_query(query)
|
62
|
+
@query = SqlQueryExecutor::Query::Normalizers::QueryNormalizer.clean_query(query)
|
55
63
|
end
|
56
64
|
|
57
65
|
def get_result(args)
|
@@ -70,7 +78,7 @@ private
|
|
70
78
|
end
|
71
79
|
|
72
80
|
def join_query(query, separator)
|
73
|
-
query = SqlQueryExecutor::Query::QueryNormalizer.clean_query(query)
|
81
|
+
query = SqlQueryExecutor::Query::Normalizers::QueryNormalizer.clean_query(query)
|
74
82
|
query.blank? ? @query : (@query.blank? ? query : "(#{@query}) #{separator} (#{query})")
|
75
83
|
end
|
76
84
|
end
|
@@ -11,62 +11,15 @@ module ActiveModel
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def validate_each(record, attribute, value)
|
14
|
-
duplicate = record.
|
14
|
+
duplicate = record.class.where("id is not ?", (record.id ? record.id : 'null')).all.select do |object|
|
15
15
|
object.id != record.id && object.send(attribute) == record.send(attribute)
|
16
16
|
end
|
17
17
|
|
18
18
|
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope, :conditions).merge(:value => value)) if duplicate.any?
|
19
19
|
end
|
20
|
-
|
21
|
-
protected
|
22
|
-
|
23
|
-
# The check for an existing value should be run from a class that
|
24
|
-
# isn't abstract. This means working down from the current class
|
25
|
-
# (self), to the first non-abstract class. Since classes don't know
|
26
|
-
# their subclasses, we have to build the hierarchy between self and
|
27
|
-
# the record's class.
|
28
|
-
def find_finder_class_for(record) #:nodoc:
|
29
|
-
class_hierarchy = [record.class]
|
30
|
-
|
31
|
-
while class_hierarchy.first != @klass
|
32
|
-
class_hierarchy.prepend(class_hierarchy.first.superclass)
|
33
|
-
end
|
34
|
-
|
35
|
-
class_hierarchy.detect { |klass| klass.respond_to?(:abstract_class?) ? !klass.abstract_class? : true }
|
36
|
-
end
|
37
|
-
|
38
|
-
def build_relation(klass, table, attribute, value) #:nodoc:
|
39
|
-
column, attribute, value = get_reflection_attributes(klass)
|
40
|
-
|
41
|
-
value = column.limit ? value.to_s[0, column.limit] : value.to_s if !value.nil? && column.text?
|
42
|
-
|
43
|
-
if !options[:case_sensitive] && value && column.text?
|
44
|
-
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
|
45
|
-
relation = klass.connection.case_insensitive_comparison(table, attribute, column, value)
|
46
|
-
else
|
47
|
-
value = klass.connection.case_sensitive_modifier(value) unless value.nil?
|
48
|
-
relation = table[attribute].eq(value)
|
49
|
-
end
|
50
|
-
|
51
|
-
relation
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
def get_reflection_attributes(klass, attribute, value)
|
56
|
-
reflection = klass.reflect_on_association(attribute)
|
57
|
-
column = klass.columns_hash[reflection.foreign_key]
|
58
|
-
|
59
|
-
if reflection
|
60
|
-
attribute = reflection.foreign_key
|
61
|
-
value = value.attributes[reflection.primary_key_column.name]
|
62
|
-
else
|
63
|
-
column = klass.columns_hash[attribute.to_s]
|
64
|
-
end
|
65
|
-
|
66
|
-
[column, attribute, value]
|
67
|
-
end
|
68
20
|
end
|
69
21
|
|
22
|
+
private
|
70
23
|
module ClassMethods
|
71
24
|
# Validates whether the value of the specified attributes are unique
|
72
25
|
# across the system. Useful for making sure that only one user
|
@@ -167,7 +120,7 @@ module ActiveModel
|
|
167
120
|
# | # title!
|
168
121
|
#
|
169
122
|
# This could even happen if you use transactions with the 'serializable'
|
170
|
-
# isolation level. The best way to work around this problem is to add
|
123
|
+
# isolation level. The best way to work around this problem is to add an unique
|
171
124
|
# index to the database table using
|
172
125
|
# ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the
|
173
126
|
# rare case that a race condition occurs, the database will guarantee
|
@@ -79,7 +79,7 @@ module ActiveHash
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def eql?(other)
|
82
|
-
(other.instance_of?(self.class) || other.instance_of?(
|
82
|
+
(other.instance_of?(self.class) || other.instance_of?(persistence_class)) && id.present? && (id == other.id) && (!self.respond_to?(:created_at) || (created_at == other.created_at))
|
83
83
|
end
|
84
84
|
|
85
85
|
alias == eql?
|
@@ -7,7 +7,7 @@ module ActiveRepository
|
|
7
7
|
object = self.new(attributes)
|
8
8
|
|
9
9
|
if object.present? && object.valid?
|
10
|
-
if
|
10
|
+
if persistence_class == self
|
11
11
|
object.id = nil unless exists?(object.id)
|
12
12
|
|
13
13
|
object.save
|
@@ -35,7 +35,7 @@ module ActiveRepository
|
|
35
35
|
# Deletes self from the repository.
|
36
36
|
def delete
|
37
37
|
klass = self.class
|
38
|
-
if klass.
|
38
|
+
if klass.persistence_class == klass
|
39
39
|
super
|
40
40
|
else
|
41
41
|
PersistenceAdapter.delete(klass, self.id)
|
@@ -47,7 +47,7 @@ module ActiveRepository
|
|
47
47
|
ret = true
|
48
48
|
key = key.to_sym
|
49
49
|
|
50
|
-
if self.class ==
|
50
|
+
if self.class == persistence_class
|
51
51
|
object = self.class.where(:id => self.id).first_or_initialize
|
52
52
|
|
53
53
|
self.send("#{key}=", value)
|
@@ -68,7 +68,7 @@ module ActiveRepository
|
|
68
68
|
def update_attributes(attributes)
|
69
69
|
attributes = attributes.symbolize_keys if attributes.respond_to?(:symbolize_keys)
|
70
70
|
klass = self.class
|
71
|
-
model_class =
|
71
|
+
model_class = persistence_class
|
72
72
|
|
73
73
|
if klass == model_class
|
74
74
|
attributes.each do |key, value|
|
@@ -18,6 +18,7 @@ describe ActiveRepository::Base, "associations" do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
class City < ActiveRepository::Base
|
21
|
+
fields :name
|
21
22
|
end
|
22
23
|
|
23
24
|
class Author < ActiveRepository::Base
|
@@ -68,7 +69,7 @@ describe ActiveRepository::Base, "associations" do
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
context "with
|
72
|
+
context "with ActiveRepository children" do
|
72
73
|
before do
|
73
74
|
Author.field :city_id
|
74
75
|
@included_author_1 = Author.create :city_id => 1
|
@@ -92,7 +93,6 @@ describe ActiveRepository::Base, "associations" do
|
|
92
93
|
end
|
93
94
|
|
94
95
|
describe "#belongs_to" do
|
95
|
-
|
96
96
|
context "with an ActiveRecord parent" do
|
97
97
|
it "find the correct records" do
|
98
98
|
City.belongs_to :country
|
@@ -108,7 +108,7 @@ describe ActiveRepository::Base, "associations" do
|
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
-
context "with an
|
111
|
+
context "with an ActiveRepository parent" do
|
112
112
|
it "find the correct records" do
|
113
113
|
Author.belongs_to :city
|
114
114
|
city = City.create
|
@@ -164,6 +164,21 @@ describe ActiveRepository::Base, "associations" do
|
|
164
164
|
author.city_id.should == @city.id
|
165
165
|
end
|
166
166
|
end
|
167
|
+
|
168
|
+
describe '#create_association' do
|
169
|
+
before do
|
170
|
+
Author.belongs_to :city
|
171
|
+
end
|
172
|
+
|
173
|
+
it "creates a city related to author" do
|
174
|
+
author = Author.new
|
175
|
+
city = author.create_city(name: 'Metropolis')
|
176
|
+
|
177
|
+
author.city.name.should == 'Metropolis'
|
178
|
+
author.city_id.should == city.id
|
179
|
+
author.city.should == city
|
180
|
+
end
|
181
|
+
end
|
167
182
|
end
|
168
183
|
|
169
184
|
describe "#has_one" do
|
@@ -184,7 +199,7 @@ describe ActiveRepository::Base, "associations" do
|
|
184
199
|
end
|
185
200
|
end
|
186
201
|
|
187
|
-
context "with
|
202
|
+
context "with ActiveRepository children" do
|
188
203
|
before do
|
189
204
|
City.has_one :author
|
190
205
|
Author.field :city_id
|
@@ -201,6 +216,34 @@ describe ActiveRepository::Base, "associations" do
|
|
201
216
|
city.author.should be_nil
|
202
217
|
end
|
203
218
|
end
|
219
|
+
|
220
|
+
describe '#create_association' do
|
221
|
+
before do
|
222
|
+
City.has_one :author
|
223
|
+
Author.field :city_id
|
224
|
+
Author.field :name
|
225
|
+
end
|
226
|
+
|
227
|
+
it "creates a city related to author" do
|
228
|
+
city = City.create
|
229
|
+
author = city.create_author(name: 'Clark Kent')
|
230
|
+
|
231
|
+
city.author.name.should == 'Clark Kent'
|
232
|
+
author.city_id.should == city.id
|
233
|
+
city.author.should == author
|
234
|
+
end
|
235
|
+
|
236
|
+
it "replaces existing relation" do
|
237
|
+
city = City.create
|
238
|
+
old_author = city.create_author(name: 'Clark Kent')
|
239
|
+
author = city.create_author(name: 'Bruce Wayne')
|
240
|
+
|
241
|
+
Author.where(city_id: city.id).count.should == 1
|
242
|
+
city.author.name.should == 'Bruce Wayne'
|
243
|
+
author.city_id.should == city.id
|
244
|
+
city.author.should == author
|
245
|
+
end
|
246
|
+
end
|
204
247
|
end
|
205
248
|
|
206
249
|
describe "#marked_for_destruction?" do
|
@@ -227,8 +270,8 @@ describe ActiveRepository::Base, "associations" do
|
|
227
270
|
end
|
228
271
|
|
229
272
|
class State < ActiveRepository::Base
|
230
|
-
State.
|
231
|
-
State.
|
273
|
+
State.persistence_class = StateModel
|
274
|
+
State.save_in_memory = false
|
232
275
|
belongs_to :country
|
233
276
|
has_many :cities
|
234
277
|
|
@@ -244,8 +287,8 @@ describe ActiveRepository::Base, "associations" do
|
|
244
287
|
end
|
245
288
|
|
246
289
|
class City < ActiveRepository::Base
|
247
|
-
City.
|
248
|
-
City.
|
290
|
+
City.persistence_class = CityModel
|
291
|
+
City.save_in_memory = false
|
249
292
|
belongs_to :state
|
250
293
|
has_many :regions
|
251
294
|
end
|
@@ -9,6 +9,7 @@ describe ActiveRepository, "Base" do
|
|
9
9
|
|
10
10
|
before do
|
11
11
|
class Country < ActiveRepository::Base
|
12
|
+
validates_presence_of :name
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
@@ -16,11 +17,51 @@ describe ActiveRepository, "Base" do
|
|
16
17
|
Object.send :remove_const, :Country
|
17
18
|
end
|
18
19
|
|
20
|
+
describe 'postfix' do
|
21
|
+
before do
|
22
|
+
class CountryPersistence
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when postfix is present' do
|
27
|
+
before do
|
28
|
+
Country.postfix = "persistence"
|
29
|
+
Country.save_in_memory = false
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'in persistence_class returns class name and postfix' do
|
33
|
+
Country.persistence_class.to_s.should == "CountryPersistence"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when postfix and persistence_class are present' do
|
38
|
+
before do
|
39
|
+
Country.postfix = "persistence"
|
40
|
+
Country.persistence_class = "CountryModel"
|
41
|
+
Country.save_in_memory = false
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'in persistence_class returns class name and postfix' do
|
45
|
+
Country.persistence_class.to_s.should == "CountryPersistence"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'whe postfix and savi_in_memory are present' do
|
50
|
+
before do
|
51
|
+
Country.postfix = "persistence"
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'in persistence_class returns class name and postfix' do
|
55
|
+
Country.persistence_class.to_s.should == "Country"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
19
60
|
context "in_memory", :in_memory do
|
20
61
|
before do
|
21
62
|
Country.fields :name, :monarch, :language, :created_at, :updated_at
|
22
|
-
Country.
|
23
|
-
Country.
|
63
|
+
Country.persistence_class = Country
|
64
|
+
Country.save_in_memory = true
|
24
65
|
|
25
66
|
Country.create(:id => 1, :name => "US", :language => 'English')
|
26
67
|
Country.create(:id => 2, :name => "Canada", :language => 'English', :monarch => "The Crown of England")
|
@@ -63,6 +104,7 @@ describe ActiveRepository, "Base" do
|
|
63
104
|
it_behaves_like '.transaction'
|
64
105
|
it_behaves_like '.delete_all'
|
65
106
|
it_behaves_like '#delete'
|
107
|
+
it_behaves_like 'uniqueness'
|
66
108
|
end
|
67
109
|
|
68
110
|
context "active_record", :active_record do
|
@@ -81,8 +123,8 @@ describe ActiveRepository, "Base" do
|
|
81
123
|
end
|
82
124
|
end
|
83
125
|
|
84
|
-
Country.
|
85
|
-
Country.
|
126
|
+
Country.persistence_class = CountryModel
|
127
|
+
Country.save_in_memory = false
|
86
128
|
|
87
129
|
Country.create(:id => 1, :name => "US", :language => 'English')
|
88
130
|
Country.create(:id => 2, :name => "Canada", :language => 'English', :monarch => "The Crown of England")
|
@@ -129,6 +171,7 @@ describe ActiveRepository, "Base" do
|
|
129
171
|
it_behaves_like '.transaction'
|
130
172
|
it_behaves_like '.delete_all'
|
131
173
|
it_behaves_like '#delete'
|
174
|
+
it_behaves_like 'uniqueness'
|
132
175
|
end
|
133
176
|
|
134
177
|
context "mongoid", :mongoid do
|
@@ -150,8 +193,8 @@ describe ActiveRepository, "Base" do
|
|
150
193
|
field :created_at
|
151
194
|
end
|
152
195
|
|
153
|
-
Country.
|
154
|
-
Country.
|
196
|
+
Country.persistence_class = CountryModel
|
197
|
+
Country.save_in_memory = false
|
155
198
|
|
156
199
|
Country.delete_all
|
157
200
|
|
@@ -200,5 +243,6 @@ describe ActiveRepository, "Base" do
|
|
200
243
|
it_behaves_like '.transaction'
|
201
244
|
it_behaves_like '.delete_all'
|
202
245
|
it_behaves_like '#delete'
|
246
|
+
it_behaves_like 'uniqueness'
|
203
247
|
end
|
204
248
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'active_repository'
|
3
3
|
require 'active_repository/result_set'
|
4
|
-
require 'pry'
|
5
4
|
|
6
5
|
describe ActiveRepository::ResultSet, :result_set do
|
7
6
|
before do
|
@@ -85,7 +84,7 @@ describe ActiveRepository::ResultSet, :result_set do
|
|
85
84
|
end
|
86
85
|
|
87
86
|
describe '#and' do
|
88
|
-
it 'is
|
87
|
+
it 'is an alias for #where' do
|
89
88
|
expect(described_class.instance_method(:and)).to eq described_class.instance_method(:where)
|
90
89
|
end
|
91
90
|
end
|
@@ -112,6 +111,48 @@ describe ActiveRepository::ResultSet, :result_set do
|
|
112
111
|
end
|
113
112
|
end
|
114
113
|
|
114
|
+
describe '#build' do
|
115
|
+
subject { ActiveRepository::ResultSet.new(Country) }
|
116
|
+
|
117
|
+
it "returns a Country object" do
|
118
|
+
expect(subject.build(name: 'Canada')).to be_a(Country)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'returns a new_record' do
|
122
|
+
result = subject.build(continent: 'America')
|
123
|
+
|
124
|
+
expect(result).to be_new_record
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'merges attributes' do
|
128
|
+
result_set = subject.where(name: 'Canada')
|
129
|
+
result = result_set.build(continent: 'America')
|
130
|
+
|
131
|
+
expect(result.attributes).to eq(name: 'Canada', continent: 'America')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#create' do
|
136
|
+
subject { ActiveRepository::ResultSet.new(Country) }
|
137
|
+
|
138
|
+
it "returns a Country object" do
|
139
|
+
expect(subject.create(name: 'Canada')).to be_a(Country)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'returns a persisted object' do
|
143
|
+
result = subject.create(continent: 'America')
|
144
|
+
|
145
|
+
expect(result).not_to be_new_record
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'merges attributes' do
|
149
|
+
result_set = subject.where(name: 'Canada')
|
150
|
+
result = result_set.create(continent: 'America')
|
151
|
+
|
152
|
+
expect(result.attributes).to eq(name: 'Canada', continent: 'America', id: result.id)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
115
156
|
describe '#all' do
|
116
157
|
before do
|
117
158
|
Country.delete_all
|
@@ -243,7 +284,7 @@ describe ActiveRepository::ResultSet, :result_set do
|
|
243
284
|
it 'returns a new object with specified attributes' do
|
244
285
|
object = subject.where("name = 'Poland'").first_or_initialize
|
245
286
|
|
246
|
-
expect(object.attributes).to eq(
|
287
|
+
expect(object.attributes).to eq(name: 'Poland')
|
247
288
|
end
|
248
289
|
end
|
249
290
|
end
|
@@ -271,13 +312,13 @@ describe ActiveRepository::ResultSet, :result_set do
|
|
271
312
|
it 'returns a new object with all Hashes as attributes' do
|
272
313
|
object = subject.where(name: 'Poland').and("continent = 'Europe'").first_or_initialize
|
273
314
|
|
274
|
-
expect(object.attributes).to eq(name: 'Poland')
|
315
|
+
expect(object.attributes).to eq(name: 'Poland', continent: 'Europe')
|
275
316
|
end
|
276
317
|
|
277
318
|
it 'returns a new object with all Hashes as attributes' do
|
278
319
|
object = subject.where("name = 'Poland'").and("continent = 'Europe'").first_or_initialize
|
279
320
|
|
280
|
-
expect(object.attributes).to eq(
|
321
|
+
expect(object.attributes).to eq(name: 'Poland', continent: 'Europe')
|
281
322
|
end
|
282
323
|
end
|
283
324
|
end
|
@@ -323,7 +364,7 @@ describe ActiveRepository::ResultSet, :result_set do
|
|
323
364
|
it 'returns a new object with specified attributes' do
|
324
365
|
object = subject.where("name = 'Poland'").first_or_create
|
325
366
|
|
326
|
-
expect(object.attributes).to eq(id: 5)
|
367
|
+
expect(object.attributes).to eq(name: 'Poland', id: 5)
|
327
368
|
end
|
328
369
|
end
|
329
370
|
end
|
@@ -351,13 +392,13 @@ describe ActiveRepository::ResultSet, :result_set do
|
|
351
392
|
it 'returns a new object with all Hashes as attributes' do
|
352
393
|
object = subject.where(name: 'Poland').and("continent = 'Europe'").first_or_create
|
353
394
|
|
354
|
-
expect(object.attributes).to eq(id: 5, name: 'Poland')
|
395
|
+
expect(object.attributes).to eq(id: 5, name: 'Poland', continent: 'Europe')
|
355
396
|
end
|
356
397
|
|
357
398
|
it 'returns a new object with all Hashes as attributes' do
|
358
399
|
object = subject.where("name = 'Poland'").and("continent = 'Europe'").first_or_create
|
359
400
|
|
360
|
-
expect(object.attributes).to eq(
|
401
|
+
expect(object.attributes).to eq(:name=>"Poland", :continent=>"Europe", :id=>5)
|
361
402
|
end
|
362
403
|
end
|
363
404
|
end
|
@@ -88,7 +88,7 @@ shared_examples ".where" do
|
|
88
88
|
results.last.name.should == "UK"
|
89
89
|
end
|
90
90
|
|
91
|
-
it "filters the records from
|
91
|
+
it "filters the records from an AR-like conditions hash" do
|
92
92
|
first_id = Country.first.id
|
93
93
|
|
94
94
|
results = Country.where(:name => 'US').all
|
@@ -194,7 +194,7 @@ shared_examples ".find_by" do
|
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
-
context 'with
|
197
|
+
context 'with an existing name' do
|
198
198
|
it "returns found element" do
|
199
199
|
Country.find_by(name: 'Canada').should == Country.all[1]
|
200
200
|
end
|
@@ -236,7 +236,7 @@ shared_examples ".find_by!" do
|
|
236
236
|
end
|
237
237
|
end
|
238
238
|
|
239
|
-
context 'with
|
239
|
+
context 'with an existing name' do
|
240
240
|
it "returns found element" do
|
241
241
|
Country.find_by!(name: 'Canada').should == Country.all[1]
|
242
242
|
end
|
@@ -441,7 +441,7 @@ end
|
|
441
441
|
|
442
442
|
shared_examples "#to_param" do
|
443
443
|
it "should return id as a string" do
|
444
|
-
country = Country.create
|
444
|
+
country = Country.create(name: 'Brazil')
|
445
445
|
country.to_param.should == country.id.to_s
|
446
446
|
end
|
447
447
|
end
|
@@ -449,7 +449,7 @@ end
|
|
449
449
|
shared_examples "#persisted?" do
|
450
450
|
it "should return true if the object has been saved" do
|
451
451
|
Country.delete_all
|
452
|
-
Country.create(:id => 2).should be_persisted
|
452
|
+
Country.create(:id => 2, name: 'Brazil').should be_persisted
|
453
453
|
end
|
454
454
|
|
455
455
|
it "should return false if the object has not been saved" do
|
@@ -563,6 +563,12 @@ shared_examples "#save" do
|
|
563
563
|
Country.delete_all
|
564
564
|
end
|
565
565
|
|
566
|
+
it "does not add object to the collection if it is not valid" do
|
567
|
+
country = Country.new :monarch => "King", :language => "bar"
|
568
|
+
country.save.should be_false
|
569
|
+
Country.count.should == 0
|
570
|
+
end
|
571
|
+
|
566
572
|
it "adds the new object to the data collection" do
|
567
573
|
Country.all.should be_empty
|
568
574
|
country = Country.new :name => "foo", :monarch => "King", :language => "bar"
|
@@ -589,7 +595,7 @@ shared_examples ".create" do
|
|
589
595
|
|
590
596
|
it "works with no args" do
|
591
597
|
Country.all.should be_empty
|
592
|
-
country = Country.create
|
598
|
+
country = Country.create(name: 'Brazil')
|
593
599
|
|
594
600
|
country.id.should == Country.last.id
|
595
601
|
end
|
@@ -656,7 +662,7 @@ end
|
|
656
662
|
|
657
663
|
shared_examples "#valid?" do
|
658
664
|
it "should return true" do
|
659
|
-
Country.new.should be_valid
|
665
|
+
Country.new(name: 'Brazil').should be_valid
|
660
666
|
end
|
661
667
|
end
|
662
668
|
|
@@ -704,7 +710,7 @@ shared_examples "#delete" do
|
|
704
710
|
end
|
705
711
|
|
706
712
|
it "removes a record" do
|
707
|
-
country = Country.create
|
713
|
+
country = Country.create(name: 'Brazil')
|
708
714
|
|
709
715
|
Country.count.should == 1
|
710
716
|
|
@@ -720,8 +726,8 @@ shared_examples ".delete_all" do
|
|
720
726
|
end
|
721
727
|
|
722
728
|
it "clears out all record" do
|
723
|
-
country1 = Country.create
|
724
|
-
country2 = Country.create
|
729
|
+
country1 = Country.create(name: 'Brazil')
|
730
|
+
country2 = Country.create(name: 'Brazil')
|
725
731
|
|
726
732
|
countries_attributes = Country.all.map(&:attributes)
|
727
733
|
expected_attributes = [country1, country2].map(&:attributes)
|
@@ -740,4 +746,21 @@ shared_examples ".delete_all" do
|
|
740
746
|
Country.delete_all
|
741
747
|
Country.all.should be_empty
|
742
748
|
end
|
749
|
+
end
|
750
|
+
|
751
|
+
shared_examples "uniqueness" do
|
752
|
+
before do
|
753
|
+
Country.delete_all
|
754
|
+
Country.validates_uniqueness_of :name
|
755
|
+
end
|
756
|
+
|
757
|
+
it "does not accept duplicated ids" do
|
758
|
+
country1 = Country.create(name: 'Brazil')
|
759
|
+
country2 = Country.create(name: 'Brazil')
|
760
|
+
|
761
|
+
country1.should be_valid
|
762
|
+
country2.should_not be_valid
|
763
|
+
Country.count.should == 1
|
764
|
+
Country.all.should == [country1]
|
765
|
+
end
|
743
766
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_repository
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Caio Torres
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_hash
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.3.
|
47
|
+
version: 0.3.4
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.3.
|
54
|
+
version: 0.3.4
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pry
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|