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.
@@ -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: []