norman 0.1.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 +2 -0
- data/Guide.md +320 -0
- data/MIT-LICENSE +18 -0
- data/README.md +104 -0
- data/Rakefile +39 -0
- data/extras/bench.rb +107 -0
- data/extras/cookie_demo.rb +111 -0
- data/extras/countries.rb +70 -0
- data/lib/generators/norman_generator.rb +22 -0
- data/lib/norman.rb +54 -0
- data/lib/norman/abstract_key_set.rb +106 -0
- data/lib/norman/active_model.rb +122 -0
- data/lib/norman/adapter.rb +53 -0
- data/lib/norman/adapters/cookie.rb +55 -0
- data/lib/norman/adapters/file.rb +38 -0
- data/lib/norman/adapters/yaml.rb +17 -0
- data/lib/norman/hash_proxy.rb +55 -0
- data/lib/norman/mapper.rb +66 -0
- data/lib/norman/model.rb +164 -0
- data/lib/norman/version.rb +9 -0
- data/lib/rack/norman.rb +21 -0
- data/norman.gemspec +25 -0
- data/spec/active_model_spec.rb +115 -0
- data/spec/adapter_spec.rb +48 -0
- data/spec/cookie_adapter_spec.rb +81 -0
- data/spec/file_adapter_spec.rb +48 -0
- data/spec/fixtures.yml +18 -0
- data/spec/key_set_spec.rb +104 -0
- data/spec/mapper_spec.rb +97 -0
- data/spec/model_spec.rb +162 -0
- data/spec/spec_helper.rb +38 -0
- metadata +136 -0
data/spec/mapper_spec.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
MockAdapter = Struct.new(:db)
|
4
|
+
|
5
|
+
class Value
|
6
|
+
extend Norman::Model
|
7
|
+
field :a
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Norman::Mapper do
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
|
14
|
+
before do
|
15
|
+
Norman.adapters.clear
|
16
|
+
@adapter = Norman::Adapter.new
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
Norman.adapters.clear
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should set default adapter name if unspecified" do
|
24
|
+
mapper = Norman::Mapper.new "Class"
|
25
|
+
assert_equal Norman.default_adapter_name, mapper.adapter_name
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should set adapter name if unspecified" do
|
29
|
+
Norman::Adapter.new :name => :hello
|
30
|
+
mapper = Norman::Mapper.new "Class", :hello
|
31
|
+
assert_equal :hello, mapper.adapter_name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "hash operations" do
|
36
|
+
|
37
|
+
before { load_fixtures }
|
38
|
+
after { Norman.adapters.clear }
|
39
|
+
|
40
|
+
describe "#hash" do
|
41
|
+
it "should get a hash corresponding to the mapped class" do
|
42
|
+
assert_equal Person.mapper.adapter.db["Person"], Person.mapper.hash
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#[]" do
|
47
|
+
it "should return an attributes hash" do
|
48
|
+
assert_kind_of Hash, Person.mapper["moe@3stooges.com"]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should raise NotFoundError if key doesn't exist" do
|
52
|
+
assert_raises Norman::NotFoundError do
|
53
|
+
Person.mapper["BADKEY"]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#[]=" do
|
59
|
+
it "should return the value" do
|
60
|
+
value = Person.mapper[:a] = Value.new(:a => "b")
|
61
|
+
assert_equal "b", value.a
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should set value#to_hash as value for key" do
|
65
|
+
value = Person.mapper[:bogus] = Value.new(:a => "b")
|
66
|
+
assert_equal "b", Person.mapper[:bogus][:a]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should freeze the value" do
|
70
|
+
value = Person.mapper[:bogus] = Value.new(:a => "b")
|
71
|
+
assert Person.mapper[:bogus].frozen?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#get" do
|
76
|
+
it "should return a model instance" do
|
77
|
+
assert_kind_of Person, Person.mapper.get("moe@3stooges.com")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#key_set" do
|
82
|
+
it "should return a Norman::KeySet with all keys" do
|
83
|
+
ks = Person.mapper.key_set
|
84
|
+
assert_kind_of Norman::AbstractKeySet, ks
|
85
|
+
assert_equal Person.count, ks.count
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#put" do
|
90
|
+
it "should add to hash and return the value" do
|
91
|
+
instance = Value.new(:a => "b")
|
92
|
+
assert value = Value.mapper.put(instance)
|
93
|
+
assert_equal instance, value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/spec/model_spec.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
describe Norman::Model do
|
4
|
+
|
5
|
+
before { load_fixtures }
|
6
|
+
after { Norman.adapters.clear }
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
|
10
|
+
it "can be called with no arguments" do
|
11
|
+
assert Person.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can be called with a block" do
|
15
|
+
p = Person.new do |person|
|
16
|
+
person.name = "joe"
|
17
|
+
end
|
18
|
+
assert_equal "joe", p.name
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can be called with attributes and a block" do
|
22
|
+
assert Person.new(:name => "foo") {|p| p.name = "bar"}
|
23
|
+
end
|
24
|
+
|
25
|
+
it "calls the block after setting sttributes" do
|
26
|
+
p = Person.new(:name => "foo") {|p| p.name = "bar"}
|
27
|
+
assert_equal "bar", p.name
|
28
|
+
end
|
29
|
+
|
30
|
+
it "can set attributes from a hash" do
|
31
|
+
p = Person.new :name => "joe"
|
32
|
+
assert_equal "joe", p.name
|
33
|
+
end
|
34
|
+
|
35
|
+
# This means your custom accessors will be invoked.
|
36
|
+
it "invokes attr writers" do
|
37
|
+
Person.any_instance.expects(:name=).once
|
38
|
+
Person.new(:name => "joe")
|
39
|
+
end
|
40
|
+
|
41
|
+
# Don't loop through params that potentially came from the Internet,
|
42
|
+
# because we need to cast keys to Symbol, and that could leak memory.
|
43
|
+
it "iterates over attribute names, not params" do
|
44
|
+
Person.attribute_names.expects(:each)
|
45
|
+
Person.new(:name => "joe")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ".mapper" do
|
50
|
+
it "lazy-loads mapper if it's not set" do
|
51
|
+
Person.instance_variable_set :@mapper, nil
|
52
|
+
assert Person.mapper
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ".use" do
|
57
|
+
it "sets a new mapper for the specified adapter" do
|
58
|
+
Person.instance_variable_set :@mapper, nil
|
59
|
+
Person.use :main
|
60
|
+
refute_nil Person.mapper
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe ".create" do
|
65
|
+
it "should add an instance to the database" do
|
66
|
+
Person.create(:name => "Ted Healy", :email => "ted@3stooges.com")
|
67
|
+
assert_equal "Ted Healy", Person.get("ted@3stooges.com").name
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
describe "an attribute reader" do
|
73
|
+
it "reads (first) from an instance var" do
|
74
|
+
p = Person.first
|
75
|
+
p.instance_variable_set :@name, "foo"
|
76
|
+
p.instance_variable_set :@attributes, nil
|
77
|
+
assert_equal "foo", p.name
|
78
|
+
end
|
79
|
+
|
80
|
+
# This also provides an easy way to check if a model instance has been
|
81
|
+
# edited. However most of the time we don't need this because Norman is
|
82
|
+
# not intended for frequent writes.
|
83
|
+
it "reads (second) from an attribute array" do
|
84
|
+
p = Person.first
|
85
|
+
assert_nil p.instance_variable_get :@name
|
86
|
+
refute_nil p.instance_variable_get :@attributes
|
87
|
+
refute_nil p.name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "an attribute writer" do
|
92
|
+
|
93
|
+
# The attributes hash is never written to, only replaced.
|
94
|
+
it "only sets instance vars" do
|
95
|
+
p = Person.first
|
96
|
+
p.name = "foo"
|
97
|
+
assert_equal "foo", p.instance_variable_get(:@name)
|
98
|
+
refute_equal "foo", p.instance_variable_get(:@attributes)[:name]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#==" do
|
103
|
+
it "returns true if the class and id are the same" do
|
104
|
+
p = Person.first
|
105
|
+
p2 = Person.new(:email => p.email)
|
106
|
+
assert_equal p, p2
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#to_hash" do
|
111
|
+
it "returns a hash of the model's attributes" do
|
112
|
+
p = Person.new(:name => "joe")
|
113
|
+
assert_equal "joe", p.to_hash[:name]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#to_id" do
|
118
|
+
it "returns the key attribute" do
|
119
|
+
p = Person.first
|
120
|
+
assert_equal p.email, p.to_id
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#id_changed?" do
|
125
|
+
it "should be true if the id changed" do
|
126
|
+
p = Person.get("moe@3stooges.com")
|
127
|
+
refute p.id_changed?
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should be false if the id didn't change" do
|
131
|
+
p = Person.get("moe@3stooges.com")
|
132
|
+
p.email = "moe2@3stooges.com"
|
133
|
+
assert p.id_changed?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#update" do
|
138
|
+
it "updates the database" do
|
139
|
+
p = Person.get("moe@3stooges.com")
|
140
|
+
original = p.name
|
141
|
+
p.update(:name => "Joe Schmoe")
|
142
|
+
p = Person.get("moe@3stooges.com")
|
143
|
+
refute_equal original, p.name
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should allow updating the key" do
|
147
|
+
count = Person.count
|
148
|
+
p = Person.get("moe@3stooges.com")
|
149
|
+
p.update(:email => "moe2@3stooges.com")
|
150
|
+
assert_equal count, Person.count
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "#save" do
|
156
|
+
it "passes itself to Mapper#put" do
|
157
|
+
p = Person.new(:name => "hello")
|
158
|
+
Person.mapper.expects(:put)
|
159
|
+
p.save
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
if ENV["coverage"]
|
2
|
+
require "simplecov"
|
3
|
+
SimpleCov.start
|
4
|
+
end
|
5
|
+
require "rubygems"
|
6
|
+
require "bundler/setup"
|
7
|
+
require "norman"
|
8
|
+
require "norman/adapters/yaml"
|
9
|
+
require 'minitest/spec'
|
10
|
+
require "mocha"
|
11
|
+
require "fileutils"
|
12
|
+
require "ffaker"
|
13
|
+
|
14
|
+
class Person
|
15
|
+
extend Norman::Model
|
16
|
+
field :email, :name
|
17
|
+
|
18
|
+
def self.stooges
|
19
|
+
with_index do
|
20
|
+
find_by_key {|k| k =~ /3stooges.com/}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
filters do
|
25
|
+
def non_howards
|
26
|
+
find {|p| p[:name] !~ /Howard/}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_fixtures
|
32
|
+
Norman.adapters.clear
|
33
|
+
file = File.expand_path("../fixtures.yml", __FILE__)
|
34
|
+
Norman::Adapters::YAML.new :file => file
|
35
|
+
Person.use :main
|
36
|
+
end
|
37
|
+
|
38
|
+
MiniTest::Unit.autorun
|
metadata
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: norman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Norman Clarke
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-17 00:00:00.000000000 -03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ffaker
|
17
|
+
requirement: &70174904768720 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70174904768720
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: minitest
|
28
|
+
requirement: &70174904768080 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70174904768080
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: mocha
|
39
|
+
requirement: &70174904767520 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *70174904767520
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: activesupport
|
50
|
+
requirement: &70174904766420 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '3.0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70174904766420
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: activemodel
|
61
|
+
requirement: &70174904765540 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ~>
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '3.0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *70174904765540
|
70
|
+
description: ! " Norman is not an ORM, man! It's a database and ORM replacement
|
71
|
+
for (mostly)\n static models and small datasets. It provides ActiveModel compatibility,
|
72
|
+
and\n flexible searching and storage.\n"
|
73
|
+
email: norman@njclarke.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- Changelog.md
|
79
|
+
- Gemfile
|
80
|
+
- Guide.md
|
81
|
+
- MIT-LICENSE
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- extras/bench.rb
|
85
|
+
- extras/cookie_demo.rb
|
86
|
+
- extras/countries.rb
|
87
|
+
- lib/generators/norman_generator.rb
|
88
|
+
- lib/norman.rb
|
89
|
+
- lib/norman/abstract_key_set.rb
|
90
|
+
- lib/norman/active_model.rb
|
91
|
+
- lib/norman/adapter.rb
|
92
|
+
- lib/norman/adapters/cookie.rb
|
93
|
+
- lib/norman/adapters/file.rb
|
94
|
+
- lib/norman/adapters/yaml.rb
|
95
|
+
- lib/norman/hash_proxy.rb
|
96
|
+
- lib/norman/mapper.rb
|
97
|
+
- lib/norman/model.rb
|
98
|
+
- lib/norman/version.rb
|
99
|
+
- lib/rack/norman.rb
|
100
|
+
- norman.gemspec
|
101
|
+
- spec/active_model_spec.rb
|
102
|
+
- spec/adapter_spec.rb
|
103
|
+
- spec/cookie_adapter_spec.rb
|
104
|
+
- spec/file_adapter_spec.rb
|
105
|
+
- spec/fixtures.yml
|
106
|
+
- spec/key_set_spec.rb
|
107
|
+
- spec/mapper_spec.rb
|
108
|
+
- spec/model_spec.rb
|
109
|
+
- spec/spec_helper.rb
|
110
|
+
has_rdoc: true
|
111
|
+
homepage: http://github.com/norman/norman
|
112
|
+
licenses: []
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project: ! '[none]'
|
131
|
+
rubygems_version: 1.6.2
|
132
|
+
signing_key:
|
133
|
+
specification_version: 3
|
134
|
+
summary: An ActiveModel-compatible ORM-like library for storing model instances in
|
135
|
+
an in-memory Hash.
|
136
|
+
test_files: []
|