matic 0.1.1 → 0.2.0
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.
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +33 -10
- data/lib/matic.rb +17 -27
- data/lib/matic/version.rb +1 -1
- data/spec/matic_spec.rb +119 -72
- data/spec/models/book.rb +8 -0
- data/spec/models/person.rb +2 -2
- metadata +6 -4
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,31 +1,54 @@
|
|
1
1
|
# Matic
|
2
2
|
|
3
|
-
Matic adds attribute accessors and dirty tracking to Mongomatic
|
3
|
+
Matic adds attribute accessors and dirty tracking to Mongomatic and
|
4
|
+
optionally shortens field names to optimize storing and indexing.
|
4
5
|
|
5
6
|
## Examples
|
6
7
|
|
7
8
|
class Person < Mongomatic::Base
|
8
9
|
include Matic
|
9
10
|
|
10
|
-
|
11
|
+
fields :first_name,
|
12
|
+
:last_name
|
11
13
|
end
|
12
14
|
|
13
15
|
person = Person.new
|
14
|
-
person.
|
16
|
+
person.first_name = "John"
|
15
17
|
|
16
|
-
person.
|
18
|
+
person.first_name_changed?
|
17
19
|
=> true
|
18
20
|
|
19
|
-
person.changes["
|
20
|
-
=> [nil, "John
|
21
|
+
person.changes["first_name"]
|
22
|
+
=> [nil, "John"]
|
21
23
|
|
22
24
|
person.insert
|
23
25
|
|
24
|
-
person.
|
26
|
+
person.first_name_changed?
|
25
27
|
=> false
|
26
28
|
|
27
|
-
person.changes["
|
29
|
+
person.changes["first_name"]
|
28
30
|
=> nil
|
29
31
|
|
30
|
-
person.previous_changes["
|
31
|
-
=> [nil, "John
|
32
|
+
person.previous_changes["first_name"]
|
33
|
+
=> [nil, "John"]
|
34
|
+
|
35
|
+
This is a model with short field names:
|
36
|
+
|
37
|
+
class Person < Mongomatic::Base
|
38
|
+
include Matic
|
39
|
+
|
40
|
+
fields :first_name => 'f',
|
41
|
+
:last_name => 'l'
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
person = Person.new
|
46
|
+
|
47
|
+
person.first_name = "John"
|
48
|
+
person.last_name = "Doe"
|
49
|
+
|
50
|
+
person.insert
|
51
|
+
=> #<Person:0x000001023cea30
|
52
|
+
@doc=
|
53
|
+
{"f"=>"John", "l" => "Doe", "_id"=>BSON::ObjectId('4cdd1b0c6aa2b112e1000001')}
|
54
|
+
...>
|
data/lib/matic.rb
CHANGED
@@ -9,33 +9,31 @@ module Matic
|
|
9
9
|
self.name.tableize
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
12
|
+
def fields(*attrs)
|
13
|
+
if attrs.first.is_a? Hash
|
14
|
+
attrs.first.each { |k, v| define_accessor(k, v) }
|
15
|
+
define_attribute_methods(attrs.first.keys)
|
16
|
+
else
|
17
|
+
attrs.each { |k, v| define_accessor(k, v) }
|
18
|
+
define_attribute_methods(attrs)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def define_accessor(attr_name, attr_field=nil)
|
25
|
+
attr_field ||= attr_name
|
14
26
|
|
15
27
|
define_method(attr_name) do
|
16
|
-
self[
|
28
|
+
self[attr_field.to_s]
|
17
29
|
end
|
18
30
|
|
19
31
|
define_method("#{attr_name}=") do |val|
|
20
|
-
unless val == self[
|
32
|
+
unless val == self[attr_field.to_s]
|
21
33
|
eval("#{attr_name}_will_change!")
|
22
34
|
end
|
23
35
|
|
24
|
-
self[
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def generate_attribute_methods(attr_name)
|
31
|
-
attribute_method_matchers.each do |matcher|
|
32
|
-
method_name = matcher.method_name(attr_name)
|
33
|
-
|
34
|
-
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
35
|
-
def #{method_name}(*args)
|
36
|
-
send(:#{matcher.method_missing_target}, '#{attr_name}', *args)
|
37
|
-
end
|
38
|
-
STR
|
36
|
+
self[attr_field.to_s] = val
|
39
37
|
end
|
40
38
|
end
|
41
39
|
end
|
@@ -44,18 +42,10 @@ module Matic
|
|
44
42
|
clear_changes if super
|
45
43
|
end
|
46
44
|
|
47
|
-
def insert!(opts={})
|
48
|
-
insert(opts.merge(:safe => true))
|
49
|
-
end
|
50
|
-
|
51
45
|
def update(opts={}, update_doc=@doc)
|
52
46
|
clear_changes if super
|
53
47
|
end
|
54
48
|
|
55
|
-
def update!(opts={}, update_doc=@doc)
|
56
|
-
update(opts.merge(:safe => true), update_doc)
|
57
|
-
end
|
58
|
-
|
59
49
|
def save
|
60
50
|
is_new ? insert : update
|
61
51
|
end
|
data/lib/matic/version.rb
CHANGED
data/spec/matic_spec.rb
CHANGED
@@ -1,137 +1,184 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe "
|
3
|
+
describe "a mongomatic model that includes matic" do
|
4
4
|
|
5
5
|
let(:person) { Person.new }
|
6
|
+
let(:book) { Book.new }
|
6
7
|
|
7
8
|
it "has a collection first_name" do
|
8
9
|
person.class.collection_name.should eql "people"
|
9
10
|
end
|
10
11
|
|
11
|
-
describe ".
|
12
|
-
it "defines a getter" do
|
13
|
-
person["first_name"] = "John"
|
12
|
+
describe ".fields" do
|
14
13
|
|
15
|
-
|
16
|
-
lambda { person.foo }.should raise_error NoMethodError
|
17
|
-
end
|
14
|
+
context "when it is passed an array" do
|
18
15
|
|
19
|
-
|
20
|
-
|
16
|
+
it "defines a getter" do
|
17
|
+
person["first_name"] = "John"
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
person.first_name.should eql "John"
|
20
|
+
lambda { person.foo }.should raise_error NoMethodError
|
21
|
+
end
|
22
|
+
|
23
|
+
it "defines a setter" do
|
24
|
+
person.first_name = "John"
|
26
25
|
|
27
|
-
|
26
|
+
person["first_name"].should eql "John"
|
27
|
+
lambda { person.foo= "bar" }.should raise_error NoMethodError
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
28
31
|
|
29
|
-
|
32
|
+
context "when it is passed a hash" do
|
30
33
|
|
31
|
-
it "
|
32
|
-
|
33
|
-
|
34
|
+
it "defines a getter" do
|
35
|
+
book["i"] = "9780485113358"
|
36
|
+
book.isbn.should eql "9780485113358"
|
34
37
|
|
35
|
-
|
36
|
-
|
38
|
+
book["a"] = ["Gilles Deleuze"]
|
39
|
+
book.authors.should eql ["Gilles Deleuze"]
|
37
40
|
end
|
38
41
|
|
39
|
-
it "
|
40
|
-
|
42
|
+
it "defines a setter" do
|
43
|
+
book.isbn = "9780485113358"
|
44
|
+
book["i"].should eql "9780485113358"
|
45
|
+
|
46
|
+
book.authors = ["Gilles Deleuze"]
|
47
|
+
book["a"].should eql ["Gilles Deleuze"]
|
41
48
|
end
|
42
49
|
|
50
|
+
it "stores documents with short field names" do
|
51
|
+
book.isbn = "9780485113358"
|
52
|
+
book.insert
|
53
|
+
|
54
|
+
book.instance_variable_get(:@doc).should have_key 'i'
|
55
|
+
end
|
43
56
|
end
|
44
57
|
|
45
|
-
|
58
|
+
end
|
46
59
|
|
47
|
-
|
48
|
-
person.first_name_changed?.should be_true
|
49
|
-
person.last_name_changed?.should be_true
|
50
|
-
end
|
60
|
+
shared_examples_for "a dirty-tracking command" do
|
51
61
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
62
|
+
it "marks a current change as previous" do
|
63
|
+
person.first_name_changed?.should be_false
|
64
|
+
person.previous_changes["first_name"].should eql [nil, "John"]
|
56
65
|
|
66
|
+
person.last_name_changed?.should be_false
|
67
|
+
person.previous_changes["last_name"].should eql [nil, "Doe"]
|
57
68
|
end
|
58
69
|
|
59
|
-
|
70
|
+
it "does callbacks" do
|
71
|
+
person.instance_variable_get(:@called_back).should be_true
|
72
|
+
end
|
60
73
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "a dirty-tracking setter" do
|
65
77
|
|
66
|
-
|
78
|
+
context "when an attribute is set" do
|
67
79
|
|
68
|
-
|
80
|
+
context "and its value has changed" do
|
69
81
|
|
70
|
-
before
|
82
|
+
before do
|
83
|
+
person.first_name = "John"
|
84
|
+
end
|
71
85
|
|
72
|
-
|
86
|
+
it "marks the attribute as changed" do
|
87
|
+
person.first_name_changed?.should be_true
|
88
|
+
end
|
89
|
+
|
90
|
+
it "remembers changes to the attribute" do
|
91
|
+
person.changes["first_name"].should eql [nil, "John"]
|
92
|
+
end
|
73
93
|
|
74
94
|
end
|
75
95
|
|
76
|
-
|
96
|
+
context "and its value has not changed" do
|
77
97
|
|
78
|
-
before
|
98
|
+
before do
|
99
|
+
person.first_name = nil
|
100
|
+
end
|
79
101
|
|
80
|
-
|
102
|
+
it "does not mark the attribute as changed" do
|
103
|
+
person.first_name_changed?.should be_false
|
104
|
+
end
|
81
105
|
|
82
106
|
end
|
83
107
|
|
84
|
-
|
108
|
+
end
|
85
109
|
|
86
|
-
|
110
|
+
end
|
87
111
|
|
88
|
-
|
112
|
+
context "when object is new" do
|
89
113
|
|
90
|
-
|
114
|
+
before do
|
115
|
+
person.first_name = "John"
|
116
|
+
person.last_name = "Doe"
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#insert" do
|
120
|
+
|
121
|
+
before { person.insert }
|
122
|
+
|
123
|
+
it_behaves_like "a dirty-tracking command"
|
91
124
|
|
92
125
|
end
|
93
126
|
|
94
|
-
|
127
|
+
describe "#insert!" do
|
95
128
|
|
96
|
-
before
|
97
|
-
person.insert
|
98
|
-
person.instance_variable_set(:@called_back, false)
|
99
|
-
person.first_name = "John"
|
100
|
-
person.last_name = "Doe"
|
101
|
-
end
|
129
|
+
before { person.insert! }
|
102
130
|
|
103
|
-
it_behaves_like "a dirty
|
131
|
+
it_behaves_like "a dirty-tracking command"
|
104
132
|
|
105
|
-
|
133
|
+
end
|
106
134
|
|
107
|
-
|
135
|
+
describe "#save" do
|
108
136
|
|
109
|
-
|
137
|
+
before { person.save }
|
110
138
|
|
111
|
-
|
139
|
+
it_behaves_like "a dirty-tracking command"
|
112
140
|
|
113
|
-
|
141
|
+
end
|
114
142
|
|
115
|
-
|
143
|
+
end
|
116
144
|
|
117
|
-
|
145
|
+
context "when object is not new" do
|
118
146
|
|
119
|
-
|
147
|
+
before do
|
148
|
+
person.insert
|
149
|
+
person.instance_variable_set(:@called_back, false)
|
150
|
+
person.first_name = "John"
|
151
|
+
person.last_name = "Doe"
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "#update" do
|
155
|
+
|
156
|
+
before { person.update }
|
157
|
+
|
158
|
+
it_behaves_like "a dirty-tracking command"
|
120
159
|
|
121
160
|
end
|
122
161
|
|
123
|
-
|
162
|
+
describe "#update!" do
|
124
163
|
|
125
|
-
before
|
126
|
-
person.stub!(:valid?).and_return(false)
|
127
|
-
person.first_name = "John"
|
128
|
-
end
|
164
|
+
before { person.update! }
|
129
165
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
166
|
+
it_behaves_like "a dirty-tracking command"
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when an invalid object is saved" do
|
173
|
+
|
174
|
+
before do
|
175
|
+
person.stub!(:valid?).and_return(false)
|
176
|
+
person.first_name = "John"
|
177
|
+
end
|
134
178
|
|
179
|
+
it "does not clear changes" do
|
180
|
+
person.save
|
181
|
+
person.first_name_changed?.should be_true
|
135
182
|
end
|
136
183
|
|
137
184
|
end
|
data/spec/models/book.rb
ADDED
data/spec/models/person.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Hakan Ensari
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-12 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -130,6 +130,7 @@ files:
|
|
130
130
|
- lib/matic/version.rb
|
131
131
|
- matic.gemspec
|
132
132
|
- spec/matic_spec.rb
|
133
|
+
- spec/models/book.rb
|
133
134
|
- spec/models/person.rb
|
134
135
|
- spec/spec_helper.rb
|
135
136
|
- spec/support/mongomatic.rb
|
@@ -168,6 +169,7 @@ specification_version: 3
|
|
168
169
|
summary: Mongomatic with attribute accessors and dirty tracking
|
169
170
|
test_files:
|
170
171
|
- spec/matic_spec.rb
|
172
|
+
- spec/models/book.rb
|
171
173
|
- spec/models/person.rb
|
172
174
|
- spec/spec_helper.rb
|
173
175
|
- spec/support/mongomatic.rb
|