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,111 @@
1
+ -# adapted from Django <djangoproject.com>
2
+ -# Copyright (c) 2005, the Lawrence Journal-World
3
+ -# Used under the modified BSD license:
4
+ -# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
5
+ !!!
6
+ %html
7
+ %head
8
+ %meta{:name=>"robots", :content=>"NONE,NOARCHIVE"}
9
+ %title Orange raised #{h exception.class} at #{h path}
10
+ %link{:rel=>"stylesheet", :href=>"/assets/_orange_/css/exceptions.css", :type=>"text/css"}
11
+ %script{:type=>"text/javascript", :src=>"/assets/_orange_/js/exceptions.js"}
12
+ %body
13
+ #summary
14
+ %h1 #{h exception.class} at #{h path}
15
+ %h2 #{h exception.message}
16
+ %table
17
+ %tr
18
+ %th Ruby
19
+ %td= "<code>#{h frames.first.filename}</code>: in <code>#{h frames.first.function}</code>, line #{h frames.first.lineno }"
20
+ %tr
21
+ %th Web
22
+ %td= "<code>#{h req.request_method} #{h(req.host + path)}</code>"
23
+ %h3= "Jump to:"
24
+ %ul#quicklinks
25
+ %li
26
+ %a{:href=>"#get-info"} GET
27
+ %li
28
+ %a{:href=>"#post-info"} POST
29
+ %li
30
+ %a{:href=>"#cookie-info"} Cookies
31
+ %li
32
+ %a{:href=>"#env-info"} ENV
33
+ %li
34
+ %a{:href=>"#orange-info"} Orange
35
+ #traceback
36
+ %h2= "Traceback <span>(innermost first)</span>"
37
+ %ul.traceback
38
+ - frames.each do |frame|
39
+ %li.frame
40
+ = "<code>#{h frame.filename}</code>: in <code>#{h frame.function}</code>"
41
+ - if frame.context_line
42
+ .context{:id => "c#{frame.object_id}"}
43
+ - if frame.pre_context
44
+ %ol.pre-context{:start=>"#{h frame.pre_context_lineno+1}", :id=>"pre#{h frame.object_id }"}
45
+ - frame.pre_context.each do |line|
46
+ %li{:onclick=>"toggle('pre#{h frame.object_id}', 'post#{h frame.object_id }')"} #{h line}
47
+ %ol.context-line{:start=>"#{h frame.lineno}"}
48
+ %li{ :onclick=>"toggle('pre#{h frame.object_id}', 'post#{h frame.object_id }')"}= "#{h frame.context_line} <span>...</span>"
49
+ - if frame.post_context
50
+ %ol.post-context{ :start=>"#{h frame.lineno+1 }", :id=>"post#{h frame.object_id}"}
51
+ - frame.post_context.each do |line|
52
+ %li{:onclick=>"toggle('pre#{h frame.object_id}', 'post#{h frame.object_id }')"} #{h line}
53
+ #requestinfo
54
+ %h2 Request information
55
+ - for var in [:GET, :POST, :cookies]
56
+ %h3{:id => "#{var.to_s.downcase}-info"}= "#{var.to_s}"
57
+ - unless req.__send__(var).empty?
58
+ %table.req
59
+ %thead
60
+ %tr
61
+ %th Variable
62
+ %th Value
63
+ %tbody
64
+ - req.__send__(var).sort_by { |k, v| k.to_s }.each do |key, val|
65
+ %tr
66
+ %td #{h key}
67
+ %td.code
68
+ %div #{h val.inspect}
69
+ - else
70
+ %p No #{var.to_s} data.
71
+ %h3#env-info Rack ENV
72
+ %table.req
73
+ %thead
74
+ %tr
75
+ %th Variable
76
+ %th Value
77
+ %tbody
78
+ - env.sort_by { |k, v| k.to_s }.each do |key, val|
79
+ - unless key =~ /^orange\./
80
+ %tr
81
+ %td #{h key}
82
+ %td.code
83
+ %div #{h val}
84
+ %h3#orange-info Orange ENV
85
+ %table.req
86
+ %thead
87
+ %tr
88
+ %th Variable
89
+ %th Value
90
+ %tbody
91
+ - env['orange.env'].sort_by { |k, v| k.to_s }.each do |key, val|
92
+ - if(![:request, :headers, :content].include?(key))
93
+ %tr
94
+ %td #{h key}
95
+ %td.code
96
+ %div #{h val}
97
+ %h3#orange-info= 'Orange<br /> Response'
98
+ %table.req
99
+ %thead
100
+ %tr
101
+ %th Variable
102
+ %th Value
103
+ %tbody
104
+ - env['orange.env'].sort_by { |k, v| k.to_s }.each do |key, val|
105
+ - if([:request, :headers, :content].include?(key))
106
+ %tr
107
+ %td #{h key}
108
+ %td.code
109
+ %div #{h val}
110
+ #explanation
111
+ %p= "You're seeing this error because you use <code>Orange::Middleware::ShowExceptions</code>."
@@ -0,0 +1,4 @@
1
+ %form{:action => "#{packet.route_to(model_name, 'new')}", :method => 'post'}
2
+ - for prop in props
3
+ %p= view_attribute(prop, model_name, :label => true)
4
+ %input{:type => 'submit', :value => 'Save New Item'}
@@ -0,0 +1,9 @@
1
+ - if model
2
+ - if resource.options[:sitemappable, false]
3
+ = orange[:sitemap, true].sitemap_links(packet, {:slug_me => orange[:sitemap, true].slug_for(model, props)})
4
+ %form{:action => packet.route_to(model_name, model[:id], 'save'), :method => 'post'}
5
+ - for prop in props
6
+ %p!= view_attribute(prop, model_name, :label => true, :value => model.attribute_get(prop[:name]), :model => model)
7
+ %input{:type => 'submit', :value => 'Save Changes'}
8
+ - else
9
+ %p Couldn't find the item you're looking for.
@@ -0,0 +1,10 @@
1
+ %table
2
+ %thead
3
+ %tr
4
+ - for prop in props
5
+ %th= prop[:name].to_s.split("_").each{|str| str.capitalize!}.join(" ")
6
+ %th
7
+ %tbody
8
+ - for obj in list
9
+ = view_table_row(model_name, :model => obj)
10
+ %a{:href => route_to(model_name, 'create')} New
@@ -0,0 +1,4 @@
1
+ - if model
2
+ %div{ :class => model_name}
3
+ - for prop in props
4
+ = view_attribute(prop, model_name, :show => true, :value => model.attribute_get(prop[:name]), :model => model)
@@ -0,0 +1,7 @@
1
+ - if model
2
+ %tr
3
+ - for prop in props
4
+ %td= model.attribute_get(prop[:name]).to_s[0..150]
5
+ %td.actions
6
+ = form_link('Delete', route_to(model_name, model.id, 'delete'), 'Are you sure you want to delete this?', {:method => 'delete'})
7
+ %a{:href => route_to(model_name, model.id, 'edit')} Edit
@@ -0,0 +1,2 @@
1
+ %h1= "#{request.request_method}: #{request.path}"
2
+ %h2 The file you were looking for cannot be found
@@ -0,0 +1,183 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Orange::Application do
4
+ before(:all) do
5
+ class MockApplication
6
+ set :banana, 'foo'
7
+ attr_accessor :quux, :wibble
8
+ def init
9
+ opts[:init] = true
10
+ @quux = true
11
+ end
12
+ def stack_init
13
+ opts[:stack_init] = true
14
+ @wibble = true
15
+ end
16
+ end
17
+ # allow deep introspection into rack builder
18
+ class Rack::Builder
19
+ attr_accessor :ins
20
+ # introspection into the Builder object's list of items
21
+ # builder uses Proc magic to chain the middleware together,
22
+ # so we undo it.
23
+ def ins_no_procs
24
+ @ins.map{|x| x.instance_of?(Proc)? x.call(nil) : x }
25
+ end
26
+ end
27
+ class Orange::Stack
28
+ attr_accessor :build
29
+ def middlewarez
30
+ build.ins_no_procs
31
+ end
32
+ end
33
+ end
34
+
35
+ def app
36
+ MockApplication.app
37
+ end
38
+
39
+ it "should be a subclass of Orange::Application" do
40
+ MockApplication.new(Orange::Core.new).should be_a_kind_of(Orange::Application)
41
+ end
42
+
43
+ it "should have a stack method" do
44
+ MockApplication.should respond_to(:stack)
45
+ end
46
+
47
+ it "should have a different app stack after using stack method" do
48
+ lambda {
49
+ MockApplication.stack do
50
+ end
51
+ }.should change(MockApplication, :app)
52
+ end
53
+
54
+ it "should respond to the app method" do
55
+ MockApplication.should respond_to(:app)
56
+ end
57
+
58
+ it "should return an Orange::Stack with the app method" do
59
+ MockApplication.stack do
60
+ end
61
+ MockApplication.app.should be_an_instance_of(Orange::Stack)
62
+ end
63
+
64
+ it "should be able to set options" do
65
+ MockApplication.set(:test4, Time.now.to_f-5)
66
+ opts_test4 = MockApplication.opts[:test4]
67
+ MockApplication.set(:test4, Time.now.to_f)
68
+ MockApplication.opts[:test4].should_not == opts_test4
69
+ MockApplication.opts[:banana].should == 'foo'
70
+ end
71
+
72
+ it "should be able to accept instance option setting" do
73
+ x= MockApplication.new(Orange::Core.new, {:test => 'go'}){
74
+ baz 'bar'
75
+ }
76
+ x.opts.should have_key(:baz)
77
+ x.opts.should have_key(:banana)
78
+ x.opts[:baz].should == 'bar'
79
+ x.opts[:test].should == 'go'
80
+ end
81
+
82
+ it "should override class variables with instance ones" do
83
+ x= MockApplication.new(Orange::Core.new)
84
+ y= MockApplication.new(Orange::Core.new){
85
+ banana 'bar'
86
+ }
87
+ x.opts.should have_key(:banana)
88
+ y.opts.should have_key(:banana)
89
+ x.opts[:banana].should == 'foo'
90
+ y.opts[:banana].should == 'bar'
91
+ x.opts[:banana].should_not == y.opts[:banana]
92
+ end
93
+
94
+ it "should be able to access options via #opts" do
95
+ x= MockApplication.new(Orange::Core.new){
96
+ baz 'bar'
97
+ }
98
+ x.opts.should be_an_instance_of(Hash)
99
+ x.opts.should respond_to(:[])
100
+ x.opts.should have_key(:baz)
101
+ x.opts[:baz].should == 'bar'
102
+ end
103
+
104
+ it "should call init after being initialized" do
105
+ x=MockApplication.new(Orange::Core.new){
106
+ init false
107
+ }
108
+ x.opts[:init].should be_true
109
+ x.quux.should be_true
110
+ end
111
+
112
+ it "should call stack_init after stack loaded" do
113
+ c = Orange::Core.new
114
+ app = MockApplication.new(c){
115
+ stack_init false
116
+ }
117
+ c.fire(:stack_loaded, false) # Falsify the stack_load call
118
+ app.opts[:stack_init].should be_true
119
+ app.wibble.should be_true
120
+ end
121
+
122
+ it "should raise a default error if route isn't redefined" do
123
+ x= MockApplication.new(Orange::Core.new)
124
+ lambda{
125
+ x.route(Orange::Packet.new(x.orange, {}))
126
+ }.should raise_error(Exception, 'default response from Orange::Application.route')
127
+ end
128
+
129
+ it "should return the orange core on #orange" do
130
+ c = Orange::Core.new
131
+ x= MockApplication.new(c)
132
+ x.orange.should eql(c)
133
+ end
134
+
135
+ it "should change the core on #set_core(orange_core)" do
136
+ c1 = Orange::Core.new
137
+ c2 = Orange::Core.new
138
+ x= MockApplication.new(c1)
139
+ c1.should_not eql(c2)
140
+ lambda {
141
+ x.set_core(c2)
142
+ }.should change(x, :orange)
143
+ end
144
+
145
+ it "should allow setting the core via #app" do
146
+ c = Orange::Core.new
147
+ x= MockApplication.app(c)
148
+ x.orange.should equal(c)
149
+ end
150
+
151
+ it "should allow setting the core via #stack" do
152
+ c = Orange::Core.new
153
+ MockApplication.stack(c) do
154
+ run MockApplication.new(orange)
155
+ end
156
+ x= MockApplication.app
157
+ x.orange.should equal(c)
158
+ x.middlewarez.first.orange.should equal(c)
159
+ p = Orange::Packet.new(c, {'orange.core' => c})
160
+ Orange::Packet.should_receive(:new).with(c, {'orange.core' => c}).and_return(p)
161
+ lambda{
162
+ x.call({}) # We don't care about the error, we care about the should_receive
163
+ }.should raise_error
164
+ end
165
+
166
+ it "should respond correctly to call" do
167
+ x= MockApplication.new(Orange::Core.new)
168
+ lambda{
169
+ x.call({})
170
+ }.should raise_error(Exception, 'default response from Orange::Application.route')
171
+ r = TestRouter.new
172
+ lambda{
173
+ x.call({'orange.env' => {'route.router' => r}})
174
+ }.should change(r, :x)
175
+ end
176
+
177
+ it "should auto initialize the self.opts" do
178
+ lambda{
179
+ MockApplication2.opts
180
+ }.should_not raise_error
181
+ end
182
+
183
+ end
@@ -0,0 +1,136 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Orange::Carton do
4
+ it "should call property with :id, Serial on #self.id" do
5
+ MockCartonBlank.should_receive(:property).with(:id, DataMapper::Types::Serial)
6
+ MockCartonBlank.id
7
+ end
8
+
9
+ it "should call self.init after calling id" do
10
+ MockCartonBlankTwo.should_receive(:init)
11
+ MockCartonBlankTwo.id
12
+ end
13
+
14
+ it "should give form properties" do
15
+ MockCarton.form_props(:live).length.should >= 1
16
+ MockCarton.form_props(:admin).length.should >= 2
17
+ MockCarton.form_props(:orange).length.should >= 3
18
+ MockCarton.form_props(:banana).should have(0).items
19
+ end
20
+
21
+ it "should call instance eval on admin block" do
22
+ MockCartonBlank.should_receive(:instance_eval)
23
+ MockCartonBlank.admin {}
24
+ end
25
+
26
+ it "should call instance eval on orange block" do
27
+ MockCartonBlank.should_receive(:instance_eval)
28
+ MockCartonBlank.orange {}
29
+ end
30
+
31
+ it "should call instance eval on front block" do
32
+ MockCartonBlank.should_receive(:instance_eval)
33
+ MockCartonBlank.front {}
34
+ end
35
+
36
+ it "should change props when calling front_property" do
37
+ lambda {
38
+ MockCarton.front_property :foo, String
39
+ }.should change(MockCarton, :form_props)
40
+
41
+ end
42
+
43
+ it "should change admin props when calling admin_property (but not front props)" do
44
+ old_props = MockCarton.form_props(:admin)
45
+ lambda {
46
+ MockCarton.admin_property :foo, String
47
+ }.should_not change(MockCarton, :form_props)
48
+ old_props.should_not == MockCarton.form_props(:admin)
49
+ end
50
+
51
+ it "should change orange props when calling orange_property (but not front/admin props)" do
52
+ admin_props = MockCarton.form_props(:admin)
53
+ old_props = MockCarton.form_props(:orange)
54
+ lambda {
55
+ MockCarton.orange_property :foo, String
56
+ }.should_not change(MockCarton, :form_props)
57
+ admin_props.should == MockCarton.form_props(:admin)
58
+ old_props.should_not == MockCarton.form_props(:orange)
59
+ end
60
+
61
+ it "should change the levels var when using front block" do
62
+ MockCartonBlank.should_receive(:test_levels){|me| me.levels.should include(:live)}
63
+ MockCartonBlank.front{ test_levels(self) }
64
+ MockCartonBlank.levels.should == false
65
+ end
66
+
67
+ it "should change the levels var when using admin block" do
68
+ MockCartonBlank.should_receive(:test_levels){|me|
69
+ me.levels.should_not include(:front)
70
+ me.levels.should include(:admin)
71
+ }
72
+ MockCartonBlank.admin{ test_levels(self) }
73
+ MockCartonBlank.levels.should == false
74
+ end
75
+
76
+ it "should change the levels var when using orange block" do
77
+ MockCartonBlank.should_receive(:test_levels){|me|
78
+ me.levels.should_not include(:front)
79
+ me.levels.should_not include(:admin)
80
+ me.levels.should include(:orange)
81
+ }
82
+ MockCartonBlank.orange{ test_levels(self) }
83
+ MockCartonBlank.levels.should == false
84
+ end
85
+
86
+ it "should have a front property after calling #front" do
87
+ front = MockCarton.scaffold_properties.select{|i| i[:name] == :front}
88
+ front.should have_at_least(1).items
89
+ front.first[:levels].should include(:live)
90
+ end
91
+
92
+ it "should have an admin property after calling #admin" do
93
+ front = MockCarton.scaffold_properties.select{|i| i[:name] == :admin}
94
+ front.should have_at_least(1).items
95
+ front.first[:levels].should_not include(:live)
96
+ front.first[:levels].should include(:admin)
97
+ end
98
+
99
+ it "should have an orange property after calling #orange" do
100
+ front = MockCarton.scaffold_properties.select{|i| i[:name] == :orange}
101
+ front.should have_at_least(1).items
102
+ front.first[:levels].should_not include(:live)
103
+ front.first[:levels].should_not include(:admin)
104
+ front.first[:levels].should include(:orange)
105
+ end
106
+
107
+ it "should call property on title" do
108
+ MockCarton.should_receive(:property).with(an_instance_of(Symbol), String, anything())
109
+ MockCarton.title(:wibble)
110
+ end
111
+
112
+ it "should call property on text" do
113
+ MockCarton.should_receive(:property).with(an_instance_of(Symbol), String, anything())
114
+ MockCarton.text(:wobble)
115
+ end
116
+
117
+ it "should call property on string" do
118
+ MockCarton.should_receive(:property).with(an_instance_of(Symbol), String, anything())
119
+ MockCarton.string(:wubble)
120
+ end
121
+
122
+ it "should call property on fulltext" do
123
+ MockCarton.should_receive(:property).with(an_instance_of(Symbol), DataMapper::Types::Text, anything())
124
+ MockCarton.fulltext(:cudge)
125
+ end
126
+
127
+ it "should define a constant (resource class)" do
128
+ lambda{
129
+ MockCartonBlankTwo_Resource.nil?
130
+ }.should raise_error(NameError)
131
+ MockCartonBlankTwo.as_resource
132
+ lambda{
133
+ MockCartonBlankTwo_Resource.nil?
134
+ }.should_not raise_error
135
+ end
136
+ end