orange-core 0.5.3

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.
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