orange-core 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/README.markdown +145 -0
  2. data/lib/orange-core.rb +8 -0
  3. data/lib/orange-core/application.rb +132 -0
  4. data/lib/orange-core/assets/css/exceptions.css +50 -0
  5. data/lib/orange-core/assets/js/exceptions.js +44 -0
  6. data/lib/orange-core/carton.rb +178 -0
  7. data/lib/orange-core/core.rb +266 -0
  8. data/lib/orange-core/magick.rb +270 -0
  9. data/lib/orange-core/middleware/base.rb +96 -0
  10. data/lib/orange-core/middleware/database.rb +45 -0
  11. data/lib/orange-core/middleware/four_oh_four.rb +45 -0
  12. data/lib/orange-core/middleware/globals.rb +17 -0
  13. data/lib/orange-core/middleware/loader.rb +13 -0
  14. data/lib/orange-core/middleware/rerouter.rb +53 -0
  15. data/lib/orange-core/middleware/restful_router.rb +99 -0
  16. data/lib/orange-core/middleware/route_context.rb +39 -0
  17. data/lib/orange-core/middleware/route_site.rb +51 -0
  18. data/lib/orange-core/middleware/show_exceptions.rb +80 -0
  19. data/lib/orange-core/middleware/static.rb +67 -0
  20. data/lib/orange-core/middleware/static_file.rb +32 -0
  21. data/lib/orange-core/middleware/template.rb +60 -0
  22. data/lib/orange-core/packet.rb +232 -0
  23. data/lib/orange-core/plugin.rb +172 -0
  24. data/lib/orange-core/resource.rb +96 -0
  25. data/lib/orange-core/resources/mapper.rb +36 -0
  26. data/lib/orange-core/resources/model_resource.rb +228 -0
  27. data/lib/orange-core/resources/not_found.rb +10 -0
  28. data/lib/orange-core/resources/page_parts.rb +68 -0
  29. data/lib/orange-core/resources/parser.rb +113 -0
  30. data/lib/orange-core/resources/routable_resource.rb +16 -0
  31. data/lib/orange-core/resources/scaffold.rb +106 -0
  32. data/lib/orange-core/stack.rb +226 -0
  33. data/lib/orange-core/templates/exceptions.haml +111 -0
  34. data/lib/orange-core/views/default_resource/create.haml +4 -0
  35. data/lib/orange-core/views/default_resource/edit.haml +9 -0
  36. data/lib/orange-core/views/default_resource/list.haml +10 -0
  37. data/lib/orange-core/views/default_resource/show.haml +4 -0
  38. data/lib/orange-core/views/default_resource/table_row.haml +7 -0
  39. data/lib/orange-core/views/not_found/404.haml +2 -0
  40. data/spec/orange-core/application_spec.rb +183 -0
  41. data/spec/orange-core/carton_spec.rb +136 -0
  42. data/spec/orange-core/core_spec.rb +248 -0
  43. data/spec/orange-core/magick_spec.rb +96 -0
  44. data/spec/orange-core/middleware/base_spec.rb +38 -0
  45. data/spec/orange-core/middleware/globals_spec.rb +3 -0
  46. data/spec/orange-core/middleware/rerouter_spec.rb +3 -0
  47. data/spec/orange-core/middleware/restful_router_spec.rb +3 -0
  48. data/spec/orange-core/middleware/route_context_spec.rb +3 -0
  49. data/spec/orange-core/middleware/route_site_spec.rb +3 -0
  50. data/spec/orange-core/middleware/show_exceptions_spec.rb +3 -0
  51. data/spec/orange-core/middleware/static_file_spec.rb +3 -0
  52. data/spec/orange-core/middleware/static_spec.rb +3 -0
  53. data/spec/orange-core/mock/mock_app.rb +16 -0
  54. data/spec/orange-core/mock/mock_carton.rb +43 -0
  55. data/spec/orange-core/mock/mock_core.rb +2 -0
  56. data/spec/orange-core/mock/mock_middleware.rb +25 -0
  57. data/spec/orange-core/mock/mock_mixins.rb +19 -0
  58. data/spec/orange-core/mock/mock_model_resource.rb +47 -0
  59. data/spec/orange-core/mock/mock_pulp.rb +24 -0
  60. data/spec/orange-core/mock/mock_resource.rb +26 -0
  61. data/spec/orange-core/mock/mock_router.rb +10 -0
  62. data/spec/orange-core/orange_spec.rb +19 -0
  63. data/spec/orange-core/packet_spec.rb +203 -0
  64. data/spec/orange-core/resource_spec.rb +96 -0
  65. data/spec/orange-core/resources/mapper_spec.rb +5 -0
  66. data/spec/orange-core/resources/model_resource_spec.rb +246 -0
  67. data/spec/orange-core/resources/parser_spec.rb +5 -0
  68. data/spec/orange-core/resources/routable_resource_spec.rb +5 -0
  69. data/spec/orange-core/spec_helper.rb +53 -0
  70. data/spec/orange-core/stack_spec.rb +232 -0
  71. data/spec/stats.rb +182 -0
  72. metadata +227 -0
@@ -0,0 +1,248 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Orange::Core do
4
+ before(:all) do
5
+ class Orange::Core; attr_reader :resources, :events, :file; end;
6
+ end
7
+
8
+ it "should allow core mixin via class mixin method" do
9
+ c= Orange::Core.new
10
+ c.should_not respond_to(:mixin_core_one)
11
+ Orange::Core.mixin MockMixinCore1
12
+ c2= Orange::Core.new
13
+ c.should respond_to(:mixin_core_one)
14
+ c2.should respond_to(:mixin_core_one)
15
+ end
16
+
17
+ it "should allow pulp mixin via class pulp method" do
18
+ c= Orange::Core.new
19
+ p= Orange::Packet.new(c, {})
20
+ p.should_not respond_to(:pulp_core_one)
21
+ Orange::Core.add_pulp MockPulpCore1
22
+ p2= Orange::Packet.new(c, {})
23
+ p.should respond_to(:pulp_core_one)
24
+ p2.should respond_to(:pulp_core_one)
25
+ end
26
+
27
+ it "should allow core mixin via instance mixin method" do
28
+ c= Orange::Core.new
29
+ c.should_not respond_to(:mixin_core_two)
30
+ c.mixin MockMixinCore2
31
+ c2= Orange::Core.new
32
+ c.should respond_to(:mixin_core_two)
33
+ c2.should respond_to(:mixin_core_two)
34
+ end
35
+
36
+ it "should allow pulp mixin via instance pulp method" do
37
+ c= Orange::Core.new
38
+ p= Orange::Packet.new(c, {})
39
+ p.should_not respond_to(:pulp_core_two)
40
+ c.add_pulp MockPulpCore2
41
+ p2= Orange::Packet.new(c, {})
42
+ p.should respond_to(:pulp_core_two)
43
+ p2.should respond_to(:pulp_core_two)
44
+ end
45
+
46
+ it "should have three contexts by default" do
47
+ Orange::Core::DEFAULT_CORE_OPTIONS.should have_key(:contexts)
48
+ Orange::Core::DEFAULT_CORE_OPTIONS[:contexts].should have(3).items
49
+ end
50
+
51
+ it "should default to live context" do
52
+ Orange::Core::DEFAULT_CORE_OPTIONS.should have_key(:default_context)
53
+ Orange::Core::DEFAULT_CORE_OPTIONS[:default_context].should == :live
54
+ end
55
+
56
+ it "should load at least two resources by default" do
57
+ c= Orange::Core.new
58
+ c.resources.size.should >= 2
59
+ c.loaded?(:mapper).should be_true
60
+ c.loaded?(:parser).should be_true
61
+ end
62
+
63
+ it "should have two events by default" do
64
+ c= Orange::Core.new
65
+ c.events.should have(2).events
66
+ c.events.should have_key(:stack_reloading)
67
+ c.events.should have_key(:stack_loaded)
68
+ end
69
+
70
+ it "should return a directory that contains core.rb when calling core_dir" do
71
+ c= Orange::Core.new
72
+ c.core_dir.should match(/orange-core$/)
73
+ File.should exist(File.join(c.core_dir, 'core.rb'))
74
+ File.should exist(File.join(c.core_dir, 'stack.rb'))
75
+ File.should exist(File.join(c.core_dir, 'application.rb'))
76
+ File.should exist(File.join(c.core_dir, 'carton.rb'))
77
+ File.should exist(File.join(c.core_dir, 'views'))
78
+ File.should exist(File.join(c.core_dir, 'templates'))
79
+ File.should exist(File.join(c.core_dir, 'assets'))
80
+ end
81
+
82
+ it "should return the directory of the super class when calling core_dir on subclass" do
83
+ c= MockCoreSubclass.new
84
+ c.core_dir.should match(/orange-core$/)
85
+ File.should exist(File.join(c.core_dir, 'core.rb'))
86
+ File.should exist(File.join(c.core_dir, 'stack.rb'))
87
+ File.should exist(File.join(c.core_dir, 'application.rb'))
88
+ File.should exist(File.join(c.core_dir, 'carton.rb'))
89
+ File.should exist(File.join(c.core_dir, 'views'))
90
+ File.should exist(File.join(c.core_dir, 'templates'))
91
+ File.should exist(File.join(c.core_dir, 'assets'))
92
+ end
93
+
94
+ it "should call afterLoad after init" do
95
+ c1= MockCoreSubclass.new
96
+ class MockCoreSubclass
97
+ def afterLoad
98
+ options[:called_afterload_for_subclass] = true
99
+ end
100
+ end
101
+ c2= MockCoreSubclass.new
102
+ c1.options[:called_afterload_for_subclass].should_not == c2.options[:called_afterload_for_subclass]
103
+ c1.options.should_not have_key(:called_afterload_for_subclass)
104
+ c2.options.should have_key(:called_afterload_for_subclass)
105
+ c2.options[:called_afterload_for_subclass].should be_true
106
+ end
107
+
108
+ it "should allow changing of default core_dir" do
109
+ c= Orange::Core.new
110
+ c.options[:core_dir] = "/non/existent/dir"
111
+ c.core_dir.should_not == File.dirname(c.file)
112
+ c.core_dir.should == "/non/existent/dir"
113
+ File.should exist(File.join(File.dirname(c.file), 'core.rb'))
114
+ end
115
+
116
+ it "should return Dir.pwd for app_dir by default" do
117
+ Orange::Core.new.app_dir.should == Dir.pwd
118
+ end
119
+
120
+ it "should return assigned app_dir if option set" do
121
+ c= Orange::Core.new
122
+ c.options[:app_dir] = "/non/existent/dir"
123
+ c.app_dir.should_not == Dir.pwd
124
+ c.app_dir.should == "/non/existent/dir"
125
+ end
126
+
127
+ it "should return assigned app_dir with extra path if args passed" do
128
+ c= Orange::Core.new
129
+ c.options[:app_dir] = "/non/existent/dir"
130
+ c.app_dir('foo', 'bar').should_not == c.app_dir
131
+ c.app_dir('foo', 'bar').should == "/non/existent/dir/foo/bar"
132
+ end
133
+
134
+ it "should allow options" do
135
+ c= Orange::Core.new(:opt_1 => true){ opt_2 true }
136
+ c.options[:opt_1].should == true
137
+ c.options[:opt_2].should == true
138
+ c.options.should have_key(:opt_1)
139
+ c.options.should_not have_key(:opt_3)
140
+ end
141
+
142
+ it "should load a resource when passed resource instance" do
143
+ c= Orange::Core.new
144
+ c.load(MockResource.new, :mock_one)
145
+ c.resources.should have_key(:mock_one)
146
+ c.resources[:mock_one].should be_an_instance_of(MockResource)
147
+
148
+ end
149
+
150
+ it "should default to lowercase resource name to symbol as resource short name" do
151
+ c= Orange::Core.new
152
+ c.load(MockResource.new)
153
+ sym = MockResource.to_s.gsub(/::/, '_').downcase.to_sym
154
+ c.resources.should have_key(sym)
155
+ c.should be_loaded(sym)
156
+ end
157
+
158
+ it "should say a resource is loaded after calling load for resource" do
159
+ c= Orange::Core.new
160
+ c.load(MockResource.new, :mock_one)
161
+ c.should be_loaded(:mock_one)
162
+ c.resources.should have_key(:mock_one)
163
+ end
164
+
165
+ it "should return self on orange" do
166
+ c= Orange::Core.new
167
+ c.orange.should eql(c)
168
+ end
169
+
170
+ it "should add event to events list when register called" do
171
+ c= Orange::Core.new
172
+ c.register(:mock_event) {|x| x }
173
+ c.events.should_not be_empty
174
+ c.events.should have_key(:mock_event)
175
+ c.events[:mock_event].should be_an_instance_of(Array)
176
+ c.events[:mock_event].should have(1).callback
177
+ c.register(:mock_event) {|x| x }
178
+ c.events[:mock_event].should have(2).callbacks
179
+ end
180
+
181
+ it "should add events in specified order when registered with position" do
182
+ c= Orange::Core.new
183
+ c.register(:mock_event, 5) {|x| '5' }
184
+ c.events.should_not be_empty
185
+ c.events.should have_key(:mock_event)
186
+ c.events[:mock_event].compact.should have(1).callback
187
+ 5.times{ |i| c.events[:mock_event][i].should be_nil }
188
+ c.register(:mock_event, 2) {|x| '2' }
189
+ c.events[:mock_event].compact.should have(2).callbacks
190
+ c.events[:mock_event][2].call(nil).should eql '2'
191
+ c.events[:mock_event][6].call(nil).should eql '5'
192
+ c.events[:mock_event].compact.first.call(nil).should eql '2'
193
+ c.events[:mock_event].compact.last.call(nil).should eql '5'
194
+ c.register(:mock_event, 5) {|x| '5.2' }
195
+ c.events[:mock_event].compact.should have(3).callbacks
196
+ c.events[:mock_event][2].call(nil).should eql '2'
197
+ c.events[:mock_event][5].call(nil).should eql '5.2'
198
+ c.events[:mock_event][7].call(nil).should eql '5'
199
+ c.events[:mock_event].compact.first.call(nil).should eql '2'
200
+ c.events[:mock_event].compact.last.call(nil).should eql '5'
201
+ end
202
+
203
+ it "should fire registered events when fire called" do
204
+ class OtherMockCore < Orange::Core
205
+ attr_accessor :mock_counter
206
+ def afterLoad
207
+ @mock_counter = 0
208
+ end
209
+ end
210
+ c= OtherMockCore.new
211
+ c.mock_counter.should == 0
212
+ c.register(:mock_event) {|i| c.mock_counter += i }
213
+ c.register(:mock_event_two) {|i| c.mock_counter -= i }
214
+ c.mock_counter.should == 0
215
+ c.fire(:mock_event, 3)
216
+ c.mock_counter.should_not == 0
217
+ c.mock_counter.should == 3
218
+ c.fire(:mock_event_two, 2)
219
+ c.mock_counter.should_not == 0
220
+ c.mock_counter.should == 1
221
+ c.register(:mock_event) {|i| c.mock_counter += i }
222
+ c.fire(:mock_event, 3)
223
+ c.mock_counter.should_not == 1
224
+ c.mock_counter.should == 7
225
+ end
226
+
227
+ it "should have an options hash" do
228
+ Orange::Core.new.options.should be_an_instance_of(Hash)
229
+ end
230
+
231
+ it "should allow access to the resources via []" do
232
+ c= Orange::Core.new
233
+ c.load(MockResource.new, :mock)
234
+ c[:mock].should be_an_instance_of(MockResource)
235
+ c[:mock].should be_an_kind_of(Orange::Resource)
236
+ c[:mock].mock_method.should eql 'MockResource#mock_method'
237
+ end
238
+
239
+ it "should have option to silently ignore resource calls" do
240
+ c= Orange::Core.new
241
+ lambda {
242
+ c[:mock].test
243
+ }.should raise_error
244
+ lambda {
245
+ c[:mock, true].test
246
+ }.should_not raise_error
247
+ end
248
+ end
@@ -0,0 +1,96 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Orange::DefaultHash do
4
+ it "should be a kind of Hash" do
5
+ Orange::DefaultHash.new.should be_a_kind_of Hash
6
+ end
7
+ it "should handle setting default" do
8
+ x = Orange::DefaultHash.new
9
+ y = Orange::DefaultHash.new
10
+ x.default = true
11
+ y.default = false
12
+ x[:not_there].should be_true
13
+ y[:not_there].should be_false
14
+ end
15
+
16
+ it "should handle default in key access []" do
17
+ x = Orange::DefaultHash.new
18
+ x.default = 'baz'
19
+ x[:not_there].should == 'baz'
20
+ x[:not_there, 'bar'].should == 'bar'
21
+ end
22
+ end
23
+
24
+ describe Orange::Ignore do
25
+ it "should silently accept method" do
26
+ o = Orange::Ignore.new
27
+ lambda {
28
+ o.banana
29
+ o.args
30
+ o.foo.bar('banana').baz
31
+ }.should_not raise_error
32
+ end
33
+ end
34
+
35
+ describe "Orange::Options" do
36
+ it "should give a hash on hash" do
37
+ Orange::Options.new.hash.should be_an_instance_of(Hash)
38
+ end
39
+
40
+ it "should accept hash key options" do
41
+ hash1 = Orange::Options.new(:one => '1', :two => ['foo']).hash
42
+ hash2 = Orange::Options.new(:one => '1').hash
43
+ hash3 = Orange::Options.new({:one => '1', :two => ['foo']}).hash
44
+ hash4 = Orange::Options.new({:one => '1'}).hash
45
+ hash5 = Orange::Options.new(1,2, {:one => '1', :two => ['foo']}).hash
46
+ hash6 = Orange::Options.new(1,2, {:one => '1'}).hash
47
+ [hash2, hash4, hash6].each{ |hash|
48
+ hash.should have_key(:one)
49
+ hash.should_not have_key(:three)
50
+ hash[:one].should == '1'
51
+ }
52
+ [hash1, hash3, hash5].each{ |hash|
53
+ hash.should have_key(:one)
54
+ hash.should have_key(:two)
55
+ hash.should_not have_key(:three)
56
+ hash[:one].should == '1'
57
+ hash[:two].should == ['foo']
58
+ }
59
+ end
60
+
61
+ it "should accept block options" do
62
+ hash = Orange::Options.new {
63
+ one '1'
64
+ two ['foo']
65
+ }.hash
66
+ hash.should have_key(:one)
67
+ hash.should have_key(:two)
68
+ hash.should_not have_key(:three)
69
+ hash[:one].should == '1'
70
+ hash[:two].should == ['foo']
71
+ end
72
+
73
+ it "should accept both kinds of options" do
74
+ hash = Orange::Options.new(:one => '1'){
75
+ two ['foo']
76
+ }.hash
77
+
78
+ hash.should have_key(:one)
79
+ hash.should have_key(:two)
80
+ hash.should_not have_key(:three)
81
+ hash[:one].should == '1'
82
+ hash[:two].should == ['foo']
83
+ end
84
+
85
+ it "should override hash key options with block options" do
86
+ hash = Orange::Options.new(:one => '1', :two => [:baz]){
87
+ two ['foo']
88
+ }.hash
89
+
90
+ hash.should have_key(:one)
91
+ hash.should have_key(:two)
92
+ hash.should_not have_key(:three)
93
+ hash[:one].should == '1'
94
+ hash[:two].should == ['foo']
95
+ end
96
+ end
@@ -0,0 +1,38 @@
1
+ describe Orange::Middleware::Base do
2
+ it "should call init after initializing" do
3
+ lambda{
4
+ mid = MockOrangeDeathMiddleware.new(nil, Orange::Core.new, :foo => 'bar')
5
+ }.should raise_error(RuntimeError, "middleware_init with foo=bar")
6
+ end
7
+
8
+ it "should create a packet and call packet call" do
9
+ mid = MockOrangeBasedMiddlewareTwo.new(nil, Orange::Core.new)
10
+ mid.should_receive(:packet_call).with(an_instance_of(Orange::Packet))
11
+ mid.call({})
12
+ end
13
+
14
+ it "should pass the packet on by default for packet_call" do
15
+ mid = MockOrangeBasedMiddlewareTwo.new(nil, Orange::Core.new)
16
+ mid.should_receive(:pass).with(an_instance_of(Orange::Packet))
17
+ mid.packet_call(empty_packet)
18
+ end
19
+
20
+ it "should call the downstream app on pass" do
21
+ app = mock("downstream")
22
+ app2 = mock("downstream_orange")
23
+ my_hash = {:foo => :bar}
24
+ app.should_receive(:call).with(my_hash).and_return([{},200,[]])
25
+ app2.should_receive(:packet_call).with(an_instance_of(Orange::Packet))
26
+ mid = MockOrangeBasedMiddlewareTwo.new(app, Orange::Core.new)
27
+ mid2 = MockOrangeBasedMiddlewareTwo.new(app2, Orange::Core.new)
28
+ mid.call(my_hash)
29
+ mid2.call(my_hash)
30
+ end
31
+
32
+ it "should give access to the orange core on calling orange" do
33
+ c = Orange::Core.new
34
+ mid = MockOrangeBasedMiddlewareTwo.new(nil, c)
35
+ mid.orange.should equal c
36
+ end
37
+
38
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::Globals do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::Rerouter do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::RestfulRouter do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::RouteContext do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::RouteSite do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::ShowExceptions do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::StaticFile do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,3 @@
1
+ describe Orange::Middleware::Static do
2
+ it "should be spec'ed"
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'rack/abstract_format'
3
+
4
+ class MockApplication < Orange::Application
5
+
6
+ end
7
+
8
+ class MockApplication2 < Orange::Application
9
+
10
+ end
11
+
12
+ class MockExitware
13
+ def call(env)
14
+ raise 'Mock Exitware'
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ class MockCarton < Orange::Carton
2
+ def self.scaffold_properties
3
+ @scaffold_properties
4
+ end
5
+ id
6
+ admin do
7
+ text :admin
8
+ end
9
+ orange do
10
+ text :orange
11
+ end
12
+ front do
13
+ text :front
14
+ end
15
+ end
16
+
17
+ class MockCartonTwo < Orange::Carton
18
+ id
19
+ def self.get(id)
20
+ 'mock_get'
21
+ end
22
+ def self.all
23
+ 'mock_all'
24
+ end
25
+ def save
26
+ raise 'mock_save'
27
+ end
28
+ def destroy!
29
+ raise 'mock_destroy'
30
+ end
31
+ def update(*args)
32
+ raise 'mock_update'
33
+ end
34
+ end
35
+
36
+ class MockCartonBlank < Orange::Carton
37
+ def self.levels
38
+ @levels
39
+ end
40
+ end
41
+
42
+ class MockCartonBlankTwo < Orange::Carton
43
+ end