norman 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -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: []