orange 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +15 -2
- data/lib/orange.rb +2 -2
- data/lib/orange/carton.rb +15 -1
- data/lib/orange/magick.rb +4 -4
- data/lib/orange/packet.rb +96 -2
- data/lib/orange/resource.rb +11 -3
- data/lib/orange/resources/model_resource.rb +248 -0
- data/lib/orange/resources/parser.rb +7 -7
- data/lib/orange/{routable_resource.rb → resources/routable_resource.rb} +0 -0
- data/spec/magick_spec.rb +0 -4
- data/spec/middleware/access_control_spec.rb +0 -0
- data/spec/middleware/base_spec.rb +0 -0
- data/spec/middleware/database_spec.rb +0 -0
- data/spec/middleware/globals_spec.rb +0 -0
- data/spec/middleware/recapture_spec.rb +0 -0
- data/spec/middleware/rerouter_spec.rb +0 -0
- data/spec/middleware/restful_router_spec.rb +0 -0
- data/spec/middleware/route_context_spec.rb +0 -0
- data/spec/middleware/route_site_spec.rb +0 -0
- data/spec/middleware/show_exceptions_spec.rb +0 -0
- data/spec/middleware/site_load_spec.rb +0 -0
- data/spec/middleware/static_file_spec.rb +0 -0
- data/spec/middleware/static_spec.rb +0 -0
- data/spec/middleware/template_spec.rb +0 -0
- data/spec/mock/mock_app.rb +0 -1
- data/spec/mock/mock_carton.rb +15 -0
- data/spec/mock/mock_model_resource.rb +43 -0
- data/spec/mock/mock_resource.rb +9 -0
- data/spec/packet_spec.rb +45 -0
- data/spec/resource_spec.rb +85 -1
- data/spec/resources/model_resource_spec.rb +142 -0
- data/spec/resources/routable_resource_spec.rb +5 -0
- data/spec/spec_helper.rb +13 -9
- metadata +22 -6
- data/lib/orange/model_resource.rb +0 -170
- data/spec/model_resource_spec.rb +0 -5
- data/spec/routable_resource_spec.rb +0 -5
data/README.markdown
CHANGED
@@ -93,7 +93,7 @@ is a bit overkill. We designed this to replace ModX in our web builds for client
|
|
93
93
|
Required Gems
|
94
94
|
-------------
|
95
95
|
|
96
|
-
Make sure
|
96
|
+
Make sure github gems can be downloaded:
|
97
97
|
|
98
98
|
$ gem sources -a http://gems.github.com
|
99
99
|
|
@@ -151,4 +151,17 @@ Pulp and Mixins
|
|
151
151
|
The ability to add pulp and mixins is incredibly handy because the packet and the core are
|
152
152
|
available from just about anywhere in the Orange framework. For instance, the haml parser
|
153
153
|
evaluates all local calls as if made to the packet, so adding pulp is essentially adding
|
154
|
-
functionality that is directly available to haml.
|
154
|
+
functionality that is directly available to haml.
|
155
|
+
|
156
|
+
|
157
|
+
LICENSE:
|
158
|
+
=========
|
159
|
+
(The MIT License)
|
160
|
+
|
161
|
+
Copyright © 2009 Orange Sparkle Ball, inc
|
162
|
+
|
163
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
164
|
+
|
165
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
166
|
+
|
167
|
+
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/orange.rb
CHANGED
@@ -3,5 +3,5 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
3
3
|
|
4
4
|
Dir.glob(File.join(libdir, 'orange', '*.rb')).each {|f| require f }
|
5
5
|
Dir.glob(File.join(libdir, 'orange', 'cartons', '*.rb')).each {|f| require f }
|
6
|
-
Dir.glob(File.join(libdir, 'orange', '
|
7
|
-
Dir.glob(File.join(libdir, 'orange', '
|
6
|
+
Dir.glob(File.join(libdir, 'orange', 'resources', '*.rb')).each {|f| require f }
|
7
|
+
Dir.glob(File.join(libdir, 'orange', 'middleware', '*.rb')).each {|f| require f }
|
data/lib/orange/carton.rb
CHANGED
@@ -1,8 +1,22 @@
|
|
1
1
|
require 'dm-core'
|
2
2
|
|
3
3
|
module Orange
|
4
|
+
# Orange::Carton is the main model class for Orange. It's based on Datamapper.
|
5
|
+
# In addition to handling the database interactions, the carton keeps
|
6
|
+
# track of declared properties, which is used to create scaffolds.
|
7
|
+
#
|
8
|
+
# All subclasses should start by declaring the "id" attribute. All models
|
9
|
+
# are assumed to have an id attribute by most everything else, so it's
|
10
|
+
# a good idea to have one.
|
11
|
+
#
|
12
|
+
# Orange::Carton adds many shortcut methods for adding various datatypes
|
13
|
+
# to the model in a more declarative style (`id` vs `property :id, Serial`)
|
14
|
+
#
|
15
|
+
# For classes that don't need anything but scaffolding, there's the
|
16
|
+
# as_resource method, which automatically creates a scaffolding resource
|
17
|
+
# for the model.
|
4
18
|
class Carton
|
5
|
-
|
19
|
+
#
|
6
20
|
def self.as_resource
|
7
21
|
name = self.to_s
|
8
22
|
eval <<-HEREDOC
|
data/lib/orange/magick.rb
CHANGED
@@ -23,11 +23,11 @@ end
|
|
23
23
|
# Monkey patch for awesome array -> hash conversions
|
24
24
|
# use:
|
25
25
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
26
|
+
# [:x, :y, :z].inject_hash do |results, letter|
|
27
|
+
# results[letter] = rand(100)
|
28
|
+
# end
|
29
29
|
#
|
30
|
-
# => {:x => 32, :y => 63, :z => 91}
|
30
|
+
# # => {:x => 32, :y => 63, :z => 91}
|
31
31
|
module Enumerable
|
32
32
|
def inject_hash(hash = {})
|
33
33
|
inject(hash) {|(h,item)| yield(h,item); h}
|
data/lib/orange/packet.rb
CHANGED
@@ -1,15 +1,58 @@
|
|
1
1
|
module Orange
|
2
|
+
# Orange::Packet is a wrapper for Rack's basic env variable.
|
3
|
+
# It acts somewhat like Rack::Request, except with more functionality.
|
4
|
+
# For each request a unique Packet is generated, and this packet is
|
5
|
+
# used to by middleware to create the response.
|
6
|
+
#
|
7
|
+
# All orange enhanced middleware has a packet_call method that
|
8
|
+
# automatically turns the generic rack call(env) into a call
|
9
|
+
# that has a packet instead, so all functions for the packet should
|
10
|
+
# be available for the request.
|
11
|
+
#
|
12
|
+
# Pulps are modules that are mixed into the Packet, allowing
|
13
|
+
# additional functionality to be used by the packet.
|
14
|
+
#
|
2
15
|
# By default, haml files are parsed in the context of their
|
3
16
|
# packet. This means all of instance variables and functions should
|
4
17
|
# be available to the haml parser.
|
5
18
|
class Packet
|
19
|
+
# By default, header will be content-type
|
6
20
|
DEFAULT_HEADERS = {"Content-Type" => 'text/html'} unless defined?(DEFAULT_HEADERS)
|
7
21
|
|
22
|
+
# We override the instantiation to only create one packet per env
|
23
|
+
# @param [Orange::Core] orange a pointer to the orange core
|
24
|
+
# @param [Hash] env a standard Rack hash
|
8
25
|
def self.new(orange, env)
|
9
26
|
return env['orange.packet'] if env['orange.packet']
|
10
27
|
super(orange, env)
|
11
28
|
end
|
12
29
|
|
30
|
+
# Allows tying in to the method_missing method without redefining it
|
31
|
+
# elsewhere. This lets dynamic methods be defined on the packet.
|
32
|
+
# Regexes are defined to match method names. #method_missing will
|
33
|
+
# loop through and try to find a match, executing the proc defined in
|
34
|
+
# the block.
|
35
|
+
# @param [Regexp] regex the regex to match
|
36
|
+
# @yield [Orange::Packet, MatchData, args] the block to execute if matched
|
37
|
+
# (passed instance, match data and args)
|
38
|
+
def self.meta_methods(regex, &block)
|
39
|
+
return unless block_given?
|
40
|
+
proc = block
|
41
|
+
@@matchers ||= {}
|
42
|
+
@@matchers[regex] = proc
|
43
|
+
end
|
44
|
+
|
45
|
+
# Allows access to the matchers added via the #meta_methods method
|
46
|
+
# @return [Hash] the matchers hash
|
47
|
+
def matchers
|
48
|
+
@@matchers || {}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Initialize is only called if a packet hasn't already been called for
|
52
|
+
# this env. Sets up the basic env, creating a pointer back to self
|
53
|
+
# and a Rack::Request object.
|
54
|
+
# @param [Orange::Core] orange a pointer to the orange core
|
55
|
+
# @param [Hash] env a standard Rack hash
|
13
56
|
def initialize(orange, env)
|
14
57
|
@orange = orange
|
15
58
|
@env = env
|
@@ -19,46 +62,77 @@ module Orange
|
|
19
62
|
@env['orange.env'][:headers] = {}
|
20
63
|
end
|
21
64
|
|
65
|
+
# Gives access to the orange.env key in the env, optionally
|
66
|
+
# including a default if key isn't involved.
|
67
|
+
# @param [Symbol, String] key the key to be found
|
68
|
+
# @param [optional, Object] default the return value if key doesn't exist (default is false)
|
69
|
+
# @return [Object] any value stored in the env
|
22
70
|
def [](key, default = false)
|
23
71
|
@env['orange.env'].has_key?(key) ? @env['orange.env'][key] : default
|
24
72
|
end
|
25
73
|
|
74
|
+
# Lets user set a value in the orange.env
|
75
|
+
# @param [Symbol, String] key the key to be set
|
76
|
+
# @param [Object] val the value to be set
|
26
77
|
def []=(key, val)
|
27
78
|
@env['orange.env'][key] = val
|
28
79
|
end
|
29
80
|
|
81
|
+
# Access to the main env (orange env is stored within the main env)
|
82
|
+
# @return [Hash] the request's env hash
|
30
83
|
def env
|
31
84
|
@env
|
32
85
|
end
|
33
86
|
|
87
|
+
# Access to the rack session
|
88
|
+
# @return [Hash] the session information made available by Rack
|
34
89
|
def session
|
35
90
|
env['rack.session']
|
36
91
|
end
|
37
92
|
|
93
|
+
# Generate headers for finalization
|
94
|
+
# @return [Hash] the header information stored in the orange.env, combined with the defaults
|
95
|
+
# set as DEFAULT_HEADERS
|
38
96
|
def headers
|
39
97
|
packet[:headers, {}].with_defaults(DEFAULT_HEADERS)
|
40
98
|
end
|
99
|
+
|
100
|
+
# Set a header
|
101
|
+
# @param [String] key the key to be set
|
102
|
+
# @param [Object] val the value to be set
|
41
103
|
def header(key, val)
|
42
104
|
@env['orange.env'][:headers][key] = val
|
43
105
|
end
|
44
106
|
|
107
|
+
# Set a header (same as #header)
|
108
|
+
# @param [String] key the key to be set
|
109
|
+
# @param [Object] val the value to be set
|
45
110
|
def add_header(key, val)
|
46
111
|
header key, val
|
47
112
|
end
|
48
113
|
|
114
|
+
# Returns the content ready to be used by Rack (wrapped in an array)
|
115
|
+
# @return [Array] array of strings to be rendered
|
49
116
|
def content
|
50
117
|
return [packet[:content]] if packet[:content]
|
51
|
-
return []
|
118
|
+
return ['']
|
52
119
|
end
|
53
120
|
|
121
|
+
# Returns the request object generated by Rack::Request(packet.env)
|
122
|
+
# @return [Rack::Request] the request object
|
54
123
|
def request
|
55
124
|
packet[:request]
|
56
125
|
end
|
57
126
|
|
127
|
+
# A pointer to the Orange::Core instance
|
128
|
+
# @return [Orange::Core] the orange core run by the application
|
58
129
|
def orange
|
59
130
|
@orange
|
60
131
|
end
|
61
132
|
|
133
|
+
# Returns the array of [status, headers, content] Rack expects
|
134
|
+
# @return [Array] the triple array expected by Rack at the end
|
135
|
+
# of a call
|
62
136
|
def finish
|
63
137
|
headers = packet.headers
|
64
138
|
status = packet[:status, 200]
|
@@ -70,19 +144,39 @@ module Orange
|
|
70
144
|
[status, headers, content]
|
71
145
|
end
|
72
146
|
|
147
|
+
# Returns self
|
148
|
+
# @return [Orange::Packet] self
|
73
149
|
def packet
|
74
150
|
self
|
75
151
|
end
|
76
152
|
|
153
|
+
# Includes the module passed
|
154
|
+
# @param [Module] inc the module to be mixed into the class
|
77
155
|
def self.mixin(inc)
|
78
156
|
include inc
|
79
157
|
end
|
80
158
|
|
159
|
+
# Route calls the router object set in the packet
|
160
|
+
# @return [void] route doesn't return anything directly, the
|
161
|
+
# main application calls packet.route then returns packet.finish.
|
162
|
+
# Routers set content, headers and status if necessary.
|
163
|
+
# They can also raise redirect errors to circumvent the process.
|
81
164
|
def route
|
82
165
|
router = packet['route.router']
|
83
166
|
raise 'Router not found' unless router
|
84
167
|
router.route(self)
|
85
168
|
end
|
169
|
+
|
170
|
+
# Method Missing allows defining custom methods
|
171
|
+
def method_missing(id, *args)
|
172
|
+
matched = false
|
173
|
+
id = id.to_s
|
174
|
+
@@matchers.each_key do |k|
|
175
|
+
matched = k if id =~ k
|
176
|
+
break if matched
|
177
|
+
end
|
178
|
+
return @@matchers[matched].call(packet, matched.match(id), args) if matched
|
179
|
+
raise NoMethodError
|
180
|
+
end
|
86
181
|
end
|
87
|
-
|
88
182
|
end
|
data/lib/orange/resource.rb
CHANGED
@@ -4,7 +4,7 @@ module Orange
|
|
4
4
|
# Orange Resource for being subclassed
|
5
5
|
class Resource
|
6
6
|
def initialize(*args, &block)
|
7
|
-
@options = Options.new(args, &block).hash
|
7
|
+
@options = Options.new(*args, &block).hash
|
8
8
|
end
|
9
9
|
|
10
10
|
def set_orange(orange, name)
|
@@ -15,7 +15,7 @@ module Orange
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.set_orange(*args)
|
18
|
-
raise '
|
18
|
+
raise 'instantiate the resource before calling set orange'
|
19
19
|
end
|
20
20
|
|
21
21
|
def afterLoad
|
@@ -30,8 +30,16 @@ module Orange
|
|
30
30
|
false
|
31
31
|
end
|
32
32
|
|
33
|
-
def view(packet = false)
|
33
|
+
def view(packet = false, *args)
|
34
34
|
''
|
35
35
|
end
|
36
|
+
|
37
|
+
def orange_name
|
38
|
+
@my_orange_name
|
39
|
+
end
|
40
|
+
|
41
|
+
def options
|
42
|
+
@options
|
43
|
+
end
|
36
44
|
end
|
37
45
|
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require 'orange/resources/routable_resource'
|
2
|
+
|
3
|
+
module Orange
|
4
|
+
class ModelResource < RoutableResource
|
5
|
+
extend ClassInheritableAttributes
|
6
|
+
# Defines a model class as an inheritable class attribute and also an instance
|
7
|
+
# attribute
|
8
|
+
cattr_inheritable :model_class
|
9
|
+
attr_accessor :model_class
|
10
|
+
|
11
|
+
# Tells the Model resource which Carton class to scaffold
|
12
|
+
# @param [Orange::Carton] my_model_class class name of the carton class to scaffold
|
13
|
+
def self.use(my_model_class)
|
14
|
+
self.model_class = my_model_class
|
15
|
+
end
|
16
|
+
|
17
|
+
# Overrides the instantiation of new Resource object to set instance model
|
18
|
+
# class to the class-level model class defined by #use
|
19
|
+
def self.new(*args, &block)
|
20
|
+
me = super(*args, &block)
|
21
|
+
me.model_class = self.model_class
|
22
|
+
me
|
23
|
+
end
|
24
|
+
|
25
|
+
# Views a packet by calling method defined as opts[:mode].
|
26
|
+
# Defaults mode to show or list, if it can't find opts[:mode].
|
27
|
+
# Decision between show or list is determined by whether an id has been chosen.
|
28
|
+
# An id is set in opts[:id], or extracted from the packet['route.resource_id'].
|
29
|
+
# Calling view is equivalent to calling a viewable method directly, view just
|
30
|
+
# sets up safe defaults so method missing errors are less likely.
|
31
|
+
# @param [Orange::Packet] packet the packet calling view on this resource
|
32
|
+
def view(packet, *args)
|
33
|
+
opts = args.last || {}
|
34
|
+
resource_id = opts[:id] || packet['route.resource_id', false]
|
35
|
+
mode = opts[:mode] || packet['route.resource_action'] ||
|
36
|
+
(resource_id ? :show : :index)
|
37
|
+
self.__send__(mode, packet, *args)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Renders a view, with all options set for haml to access.
|
41
|
+
# Calls #view_opts to generate the haml options.
|
42
|
+
# @param [Orange::Packet] packet the packet we are returning a view for
|
43
|
+
# @param [Symbol] mode the mode we are trying to view (used to find template name)
|
44
|
+
# @param [optional, Array] args the args array
|
45
|
+
# @return [String] haml parsed string to be placed in packet[:content] by #route
|
46
|
+
def do_view(packet, mode, *args)
|
47
|
+
haml_opts = view_opts(packet, mode, false, *args)
|
48
|
+
orange[:parser].haml("#{mode.to_s}.haml", packet, haml_opts)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Renders a view, with all options set for haml to access. Same as do_view, but
|
52
|
+
# calls #view_opts with is_list set to true to generate the haml options.
|
53
|
+
# @param [Orange::Packet] packet the packet we are returning a view for
|
54
|
+
# @param [Symbol] mode the mode we are trying to view (used to find template name)
|
55
|
+
# @param [optional, Array] args the args array
|
56
|
+
# @return [String] haml parsed string to be placed in packet[:content] by #route
|
57
|
+
def do_list_view(packet, mode, *args)
|
58
|
+
haml_opts = view_opts(packet, mode, true, *args)
|
59
|
+
orange[:parser].haml("#{mode.to_s}.haml", packet, haml_opts)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the options for including in template rendering. All keys passed in the args array
|
63
|
+
# will automatically be local variables in the haml template.
|
64
|
+
# In addition, the props, resource, and model_name variables will be available.
|
65
|
+
# @param [Orange::Packet] packet the packet we are returning a view for
|
66
|
+
# @param [Symbol] mode the mode we are trying to view (used to find template name)
|
67
|
+
# @param [boolean] is_list whether we want a list or not (view_opts will automatically look up
|
68
|
+
# a single object or a list of objects, so we need to know which)
|
69
|
+
# @param [optional, Array] args the args array
|
70
|
+
# @return [Hash] hash of options to be used
|
71
|
+
def view_opts(packet, mode, is_list, *args)
|
72
|
+
opts = args.extract_options!.with_defaults({:path => ''})
|
73
|
+
props = model_class.form_props(packet['route.context'])
|
74
|
+
resource_id = opts[:id] || packet['route.resource_id'] || false
|
75
|
+
all_opts = {:props => props, :resource => self.class.to_s, :model_name => @my_orange_name}.merge!(opts)
|
76
|
+
all_opts.with_defaults! :model => find_one(packet, mode, resource_id) unless is_list
|
77
|
+
all_opts.with_defaults! :list => find_list(packet, mode) if is_list
|
78
|
+
all_opts.with_defaults! find_extras(packet, mode)
|
79
|
+
all_opts
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns a single object found by the model class, given an id.
|
83
|
+
# If id isn't given, we return false.
|
84
|
+
# @param [Orange::Packet] packet the packet we are returning a view for
|
85
|
+
# @param [Symbol] mode the mode we are trying to view (used to find template name)
|
86
|
+
# @param [Numeric] id the id to lookup on the model class
|
87
|
+
# @return [Object] returns an object of type set by #use, if one found with same id
|
88
|
+
def find_one(packet, mode, id = false)
|
89
|
+
return false unless id
|
90
|
+
model_class.get(id)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a list of all objects found by the model class
|
94
|
+
# If none, returns an empty array
|
95
|
+
# @param [Orange::Packet] packet the packet we are returning a view for
|
96
|
+
# @param [Symbol] mode the mode we are trying to view (used to find template name)
|
97
|
+
# @param [Numeric] id the id to lookup on the model class
|
98
|
+
# @return [Enumerable] returns a collection of objects of type set by #use
|
99
|
+
def find_list(packet, mode)
|
100
|
+
model_class.all || []
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns a hash of extra options to be set and made available by the haml parser.
|
104
|
+
# Overriding this method is useful for passing extra bits of info to rendering
|
105
|
+
# for certain view modes without rewriting all of the other scaffolding
|
106
|
+
# @param [Orange::Packet] packet the packet we are returning a view for
|
107
|
+
# @param [Symbol] mode the mode we are trying to view (used to find template name)
|
108
|
+
# @return [Hash] a hash of extras to be included in the rendering
|
109
|
+
def find_extras(packet, mode)
|
110
|
+
{}
|
111
|
+
end
|
112
|
+
|
113
|
+
# Creates a new model object and saves it (if a post), then reroutes to the main page
|
114
|
+
# @param [Orange::Packet] packet the packet being routed
|
115
|
+
def new(packet, *opts)
|
116
|
+
if packet.request.post?
|
117
|
+
model_class.new(packet.request.params[@my_orange_name.to_s]).save
|
118
|
+
end
|
119
|
+
packet.reroute(@my_orange_name, :orange)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Deletes an object specified by packet['route.resource_id'], then reroutes to main
|
123
|
+
# @param [Orange::Packet] packet the packet being routed
|
124
|
+
def delete(packet, *opts)
|
125
|
+
if packet.request.delete?
|
126
|
+
m = model_class.get(packet['route.resource_id'])
|
127
|
+
m.destroy! if m
|
128
|
+
end
|
129
|
+
packet.reroute(@my_orange_name, :orange)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Saves updates to an object specified by packet['route.resource_id'], then reroutes to main
|
133
|
+
# @param [Orange::Packet] packet the packet being routed
|
134
|
+
def save(packet, *opts)
|
135
|
+
if packet.request.post?
|
136
|
+
m = model_class.get(packet['route.resource_id'])
|
137
|
+
if m
|
138
|
+
m.update(packet.request.params[@my_orange_name.to_s])
|
139
|
+
else
|
140
|
+
end
|
141
|
+
end
|
142
|
+
packet.reroute(@my_orange_name, :orange)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Calls #do_view with :show mode
|
146
|
+
# @param [Orange::Packet] packet the packet being routed
|
147
|
+
def show(packet, *opts)
|
148
|
+
do_view(packet, :show, *opts)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Calls #do_view with :edit mode
|
152
|
+
# @param [Orange::Packet] packet the packet being routed
|
153
|
+
def edit(packet, *opts)
|
154
|
+
do_view(packet, :edit, *opts)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Calls #do_view with :create mode
|
158
|
+
# @param [Orange::Packet] packet the packet being routed
|
159
|
+
def create(packet, *opts)
|
160
|
+
do_view(packet, :create, *opts)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Calls #do_view with :table_row mode
|
164
|
+
# @param [Orange::Packet] packet the packet being routed
|
165
|
+
def table_row(packet, *opts)
|
166
|
+
do_view(packet, :table_row, *opts)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Calls #do_list_view with :list mode
|
170
|
+
# @param [Orange::Packet] packet the packet being routed
|
171
|
+
def list(packet, *opts)
|
172
|
+
do_list_view(packet, :list, *opts)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Calls #do_list_view with :list mode.
|
176
|
+
# @param [Orange::Packet] packet the packet being routed
|
177
|
+
def index(packet, *opts)
|
178
|
+
do_list_view(packet, :list, *opts)
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
class Packet
|
184
|
+
# Adds view_[mode_name] magic methods to the packet
|
185
|
+
meta_methods(/view_([a-zA-Z_]+)/) do |packet, match, args|
|
186
|
+
model = args.shift
|
187
|
+
args = args.extract_with_defaults(:mode => match[1].to_sym)
|
188
|
+
packet.view(model, args)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Creates a button that appears to be a link but
|
192
|
+
# does form submission with custom method (_method param in POST)
|
193
|
+
# This is to avoid issues of a destructive get.
|
194
|
+
# @param [String] text link text to show
|
195
|
+
# @param [String] link the actual href value of the link
|
196
|
+
# @param [String, false] confirm text of the javascript confirm (false for none [default])
|
197
|
+
# @param [optional, Array] args array of optional arguments, only opts[:method] defined
|
198
|
+
# @option opts [String] method method name (Should be 'DELETE', 'PUT' or 'POST')
|
199
|
+
def form_link(text, link, confirm = false, *args)
|
200
|
+
opts = args.extract_options!
|
201
|
+
meth = (opts[:method]? "<input type='hidden' name='_method' value='#{opts[:method]}' />" : '')
|
202
|
+
if confirm
|
203
|
+
"<form action='#{link}' method='post' class='mini' onsubmit='return confirm(\"#{confirm}\")'><button class='link_button'><a href='#'>#{text}</a></button>#{meth}</form>"
|
204
|
+
else
|
205
|
+
"<form action='#{link}' method='post' class='mini'><button class='link_button'><a href='#'>#{text}</a></button>#{meth}</form>"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Calls view for an orange resource.
|
210
|
+
def view(model_name, *args)
|
211
|
+
orange[model_name].view(self, *args)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Returns a scaffolded attribute
|
215
|
+
def view_attribute(prop, model_name, *args)
|
216
|
+
args = args.extract_options!
|
217
|
+
val = args[:value] || ''
|
218
|
+
label = args[:label] || false
|
219
|
+
show = args[:show] || false
|
220
|
+
name = prop[:name]
|
221
|
+
unless show
|
222
|
+
case prop[:type]
|
223
|
+
when :title
|
224
|
+
ret = "<input class='title' type='text' value='#{val}' name='#{model_name}[#{name}]' />"
|
225
|
+
when :text
|
226
|
+
ret = "<input type='text' value='#{val}' name='#{model_name}[#{name}]' />"
|
227
|
+
when :fulltext
|
228
|
+
ret = "<textarea name='#{model_name}[#{name}]'>#{val}</textarea>"
|
229
|
+
else
|
230
|
+
ret = "<input type='text' value='#{val}' name='#{model_name}[#{name}]' />"
|
231
|
+
end
|
232
|
+
ret = "<label for=''>#{name}</label><br />" + ret if label
|
233
|
+
else
|
234
|
+
case prop[:type]
|
235
|
+
when :title
|
236
|
+
ret = "<h3 class='#{model_name}-#{name}'>#{val}</h3>"
|
237
|
+
when :text
|
238
|
+
ret = "<p class='#{model_name}-#{name}'>#{val}</p>"
|
239
|
+
when :fulltext
|
240
|
+
ret = "<div class='#{model_name}-#{name}'>#{val}</div>"
|
241
|
+
else
|
242
|
+
ret = "<div class='#{model_name}-#{name}'>#{val}</div>"
|
243
|
+
end
|
244
|
+
end
|
245
|
+
ret
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
@@ -26,19 +26,19 @@ module Orange
|
|
26
26
|
default_dir = File.join(views_dir, 'default_resource')
|
27
27
|
|
28
28
|
string = false
|
29
|
-
string ||=
|
30
|
-
string ||=
|
31
|
-
string ||=
|
32
|
-
string ||=
|
33
|
-
string ||=
|
34
|
-
string ||=
|
29
|
+
string ||= read_if_exists('templates', file) if temp
|
30
|
+
string ||= read_if_exists(templates_dir, file) if temp
|
31
|
+
string ||= read_if_exists('views', resource, file) if resource
|
32
|
+
string ||= read_if_exists('views', file)
|
33
|
+
string ||= read_if_exists(views_dir, file)
|
34
|
+
string ||= read_if_exists(views_dir, 'default_resource', file)
|
35
35
|
raise LoadError, "Couldn't find haml file '#{file}" unless string
|
36
36
|
|
37
37
|
haml_engine = Haml::Engine.new(string)
|
38
38
|
out = haml_engine.render(packet, opts, &block)
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
41
|
+
def read_if_exists(*args)
|
42
42
|
return File.read(File.join(*args)) if File.exists?(File.join(*args))
|
43
43
|
false
|
44
44
|
end
|
File without changes
|
data/spec/magick_spec.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/mock/mock_app.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
class MockModelResource < Orange::ModelResource
|
2
|
+
use MockCarton
|
3
|
+
end
|
4
|
+
|
5
|
+
class MockModelResourceOne < Orange::ModelResource
|
6
|
+
use MockCarton
|
7
|
+
def index(packet, *args)
|
8
|
+
raise 'I see you\'re using index'
|
9
|
+
end
|
10
|
+
def show(packet, *args)
|
11
|
+
raise 'I see you\'re using show'
|
12
|
+
end
|
13
|
+
def other(packet, *args)
|
14
|
+
raise 'I see you\'re using other'
|
15
|
+
end
|
16
|
+
def find_one(packet, mode, resource_id =false)
|
17
|
+
raise 'calling find_one'
|
18
|
+
end
|
19
|
+
def find_list(packet, mode)
|
20
|
+
raise 'calling find_list'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class MockModelResourceTwo < Orange::ModelResource
|
25
|
+
use MockCartonTwo
|
26
|
+
end
|
27
|
+
|
28
|
+
class MockModelResourceThree < Orange::ModelResource
|
29
|
+
use MockCarton
|
30
|
+
def find_extras(packet, mode)
|
31
|
+
raise 'calling find_extras'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class MockModelResourceFour < Orange::ModelResource
|
36
|
+
use MockCarton
|
37
|
+
def find_one(packet, mode, resource_id =false)
|
38
|
+
'mock_one'
|
39
|
+
end
|
40
|
+
def find_list(packet, mode)
|
41
|
+
'mock_list'
|
42
|
+
end
|
43
|
+
end
|
data/spec/mock/mock_resource.rb
CHANGED
@@ -2,4 +2,13 @@ class MockResource < Orange::Resource
|
|
2
2
|
def mock_method
|
3
3
|
'MockResource#mock_method'
|
4
4
|
end
|
5
|
+
def afterLoad
|
6
|
+
@options[:mocked] = true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class MockHamlParser < Orange::Resource
|
11
|
+
def haml(template, packet, opts)
|
12
|
+
[template, packet, opts]
|
13
|
+
end
|
5
14
|
end
|
data/spec/packet_spec.rb
CHANGED
@@ -131,4 +131,49 @@ describe Orange::Packet do
|
|
131
131
|
p= Orange::Packet.new(Orange::Core.new, {})
|
132
132
|
p.request.should be_an_instance_of Rack::Request
|
133
133
|
end
|
134
|
+
|
135
|
+
it "should store method matchers for extending method_missing handlers" do
|
136
|
+
class Orange::Packet
|
137
|
+
meta_methods(/pretend_method_we_dont_want/) do |match, args|
|
138
|
+
"my mock meta method"
|
139
|
+
end
|
140
|
+
|
141
|
+
meta_methods(/pretend_method_we_dont_want(\w+)/) do |match, args|
|
142
|
+
"my mock meta method"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
p= Orange::Packet.new(Orange::Core.new, {})
|
146
|
+
p.matchers.size.should >= 2
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should have method_missing capabilities" do
|
150
|
+
p= Orange::Packet.new(Orange::Core.new, {})
|
151
|
+
p.should respond_to(:method_missing)
|
152
|
+
lambda {
|
153
|
+
p.my_mock_meta_method
|
154
|
+
p.mock_meta_test
|
155
|
+
p.mock_meta_test_with_args
|
156
|
+
}.should raise_error(NoMethodError)
|
157
|
+
class Orange::Packet
|
158
|
+
meta_methods(/my_mock_meta_method/) do
|
159
|
+
"my mock meta method"
|
160
|
+
end
|
161
|
+
|
162
|
+
meta_methods(/mock_meta_(\w+)/) do |packet, match|
|
163
|
+
"my mock #{match[1]} method"
|
164
|
+
end
|
165
|
+
|
166
|
+
meta_methods(/mock_meta_(\w+)_with_args/) do |packet, match, args|
|
167
|
+
"my mock #{match[1]} method args0 = #{args[0]}"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
lambda {
|
171
|
+
p.my_mock_meta_method
|
172
|
+
p.mock_meta_test
|
173
|
+
p.mock_meta_test_with_args 'test'
|
174
|
+
}.should_not raise_error(NoMethodError)
|
175
|
+
p.my_mock_meta_method.should == "my mock meta method"
|
176
|
+
p.mock_meta_test.should == "my mock test method"
|
177
|
+
p.mock_meta_test_with_args('test').should == "my mock test method args0 = test"
|
178
|
+
end
|
134
179
|
end
|
data/spec/resource_spec.rb
CHANGED
@@ -1,5 +1,89 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe Orange::Resource do
|
4
|
-
it "should
|
4
|
+
it "should allow options" do
|
5
|
+
r= Orange::Resource.new(:opt_1 => true){ opt_2 true }
|
6
|
+
r.options[:opt_1].should == true
|
7
|
+
r.options[:opt_2].should == true
|
8
|
+
r.options.should have_key(:opt_1)
|
9
|
+
r.options.should_not have_key(:opt_3)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should accept an orange core on set_orange" do
|
13
|
+
c= Orange::Core.new
|
14
|
+
r= Orange::Resource.new
|
15
|
+
r.set_orange(c, :name)
|
16
|
+
r.orange.should equal(c)
|
17
|
+
r.orange.should be_a_kind_of(Orange::Core)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should call afterLoad after calling set_orange" do
|
21
|
+
c= Orange::Core.new
|
22
|
+
r= MockResource.new
|
23
|
+
r.options.should_not have_key(:mocked)
|
24
|
+
r.set_orange(c, :name)
|
25
|
+
r.options.should have_key(:mocked)
|
26
|
+
r.options[:mocked].should == true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should set the orange_name after calling set_orange" do
|
30
|
+
c= Orange::Core.new
|
31
|
+
r= Orange::Resource.new
|
32
|
+
r2= Orange::Resource.new
|
33
|
+
r.set_orange(c, :name)
|
34
|
+
r2.set_orange(c, 'name')
|
35
|
+
r.orange_name.should == :name
|
36
|
+
r2.orange_name.should_not == :name
|
37
|
+
r2.orange_name.should == 'name'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return self after set_orange" do
|
41
|
+
c= Orange::Core.new
|
42
|
+
r= Orange::Resource.new
|
43
|
+
me = r.set_orange(c, :name)
|
44
|
+
me.should equal r
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return an error if setting orange on a class" do
|
48
|
+
lambda {
|
49
|
+
Orange::Resource.set_orange(Orange::Core.new, :mock)
|
50
|
+
}.should raise_error(RuntimeError, "instantiate the resource before calling set orange")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should give access to the core through orange" do
|
54
|
+
c= Orange::Core.new
|
55
|
+
r= Orange::Resource.new
|
56
|
+
r.set_orange(c, :name)
|
57
|
+
r.orange.should equal(c)
|
58
|
+
r.orange.should be_a_kind_of(Orange::Core)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should respond to routable" do
|
62
|
+
r = Orange::Resource.new
|
63
|
+
r.should respond_to(:routable)
|
64
|
+
r.routable.should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return an empty string on calling view" do
|
68
|
+
r = Orange::Resource.new
|
69
|
+
r.view.should == ''
|
70
|
+
r.view(Orange::Packet.new(Orange::Core.new, {})).should == ''
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should accept an options hash to view" do
|
74
|
+
p = Orange::Packet.new(Orange::Core.new, {})
|
75
|
+
r = Orange::Resource.new
|
76
|
+
lambda{
|
77
|
+
r.view(p, :opts => 'foo', :test => 'bar')
|
78
|
+
}.should_not raise_error
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should give access to the orange name attribute" do
|
82
|
+
c= Orange::Core.new
|
83
|
+
r= Orange::Resource.new
|
84
|
+
r.set_orange(c, :name)
|
85
|
+
r.orange_name.should == :name
|
86
|
+
end
|
87
|
+
|
88
|
+
|
5
89
|
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Orange::ModelResource do
|
4
|
+
|
5
|
+
it "should extend class inheritable attributes" do
|
6
|
+
Orange::ModelResource.should be_a_kind_of(ClassInheritableAttributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have a model class when calling use" do
|
10
|
+
a = MockModelResourceOne.new
|
11
|
+
b = MockModelResourceTwo.new
|
12
|
+
MockModelResourceOne.model_class.should equal MockCarton
|
13
|
+
a.model_class.should equal MockCarton
|
14
|
+
MockModelResourceTwo.model_class.should equal MockCartonTwo
|
15
|
+
b.model_class.should equal MockCartonTwo
|
16
|
+
end
|
17
|
+
|
18
|
+
it "have a usable view method" do
|
19
|
+
a = MockModelResource.new
|
20
|
+
a.should respond_to(:view)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should call index or show by default for an orange packet" do
|
24
|
+
c = Orange::Core.new
|
25
|
+
c.load(MockModelResourceOne.new, :mocked)
|
26
|
+
p = Orange::Packet.new(c, {})
|
27
|
+
p2 = Orange::Packet.new(c, {})
|
28
|
+
p2['route.resource_id'] = 1
|
29
|
+
lambda {
|
30
|
+
c[:mocked].view(p)
|
31
|
+
}.should raise_error(RuntimeError, "I see you're using index")
|
32
|
+
lambda {
|
33
|
+
c[:mocked].view(p2)
|
34
|
+
}.should raise_error(RuntimeError, "I see you're using show")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should send the mode to the appropriate method" do
|
38
|
+
c = Orange::Core.new
|
39
|
+
c.load(MockModelResourceOne.new, :mocked)
|
40
|
+
p = Orange::Packet.new(c, {})
|
41
|
+
lambda {
|
42
|
+
c[:mocked].view(p, :mode => :other)
|
43
|
+
}.should raise_error(RuntimeError, "I see you're using other")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "shouldn't give a shit" do
|
47
|
+
lambda{
|
48
|
+
MockModelResource.shit
|
49
|
+
}.should raise_error(NoMethodError)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should call find_one if calling view_opts with is_list false" do
|
53
|
+
a= MockModelResourceOne.new
|
54
|
+
lambda{
|
55
|
+
a.view_opts(Orange::Packet.new(Orange::Core.new, {}), :list, false)
|
56
|
+
}.should raise_error(RuntimeError, "calling find_one")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should call find_list if calling view_opts with is_list true" do
|
60
|
+
a= MockModelResourceOne.new
|
61
|
+
lambda{
|
62
|
+
a.view_opts(Orange::Packet.new(Orange::Core.new, {}), :list, true)
|
63
|
+
}.should raise_error(RuntimeError, "calling find_list")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should return a hash of options on calling view_opts" do
|
67
|
+
a= MockModelResourceFour.new
|
68
|
+
c= Orange::Core.new
|
69
|
+
p= Orange::Packet.new(c, {})
|
70
|
+
lambda{
|
71
|
+
a.view_opts(p, :list, true)
|
72
|
+
}.should_not raise_error(RuntimeError)
|
73
|
+
opts = a.view_opts(p, :list, true, :extra => 'foo')
|
74
|
+
opts3 = a.view_opts(p, :list, false, :extra => 'foo')
|
75
|
+
opts2 = a.view_opts(p, :list, true, :list => 'banana')
|
76
|
+
opts[:props].should == MockCarton.form_props(p['route.context'])
|
77
|
+
opts.should have_key(:list)
|
78
|
+
opts3.should_not have_key(:list)
|
79
|
+
opts.should have_key(:resource)
|
80
|
+
opts.should have_key(:model_name)
|
81
|
+
opts.should_not have_key(:model)
|
82
|
+
opts3.should have_key(:model)
|
83
|
+
opts.should have_key(:extra)
|
84
|
+
opts3.should have_key(:extra)
|
85
|
+
opts[:extra].should == 'foo'
|
86
|
+
opts3[:extra].should == 'foo'
|
87
|
+
opts[:list].should_not == opts2[:list]
|
88
|
+
opts2[:list].should == 'banana'
|
89
|
+
opts[:list].should == 'mock_list'
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should call view_extras after during view_opts" do
|
93
|
+
a= MockModelResourceThree.new
|
94
|
+
lambda{
|
95
|
+
a.view_opts(Orange::Packet.new(Orange::Core.new, {}), :list, true)
|
96
|
+
}.should raise_error(RuntimeError, "calling find_extras")
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should call haml parser with opts on do_view" do
|
100
|
+
c= Orange::Core.new
|
101
|
+
p= Orange::Packet.new(c, {})
|
102
|
+
c.load(MockHamlParser.new, :parser)
|
103
|
+
c.load(MockModelResourceFour.new, :mocked)
|
104
|
+
parsed = c[:mocked].do_view(p, :test, :extra => 'foo')
|
105
|
+
parsed.first.should == 'test.haml'
|
106
|
+
parsed.last.should == c[:mocked].view_opts(p, :test, false, :extra => 'foo')
|
107
|
+
parsed.last.should_not == c[:mocked].view_opts(p, :test, true, :extra => 'foo')
|
108
|
+
parsed.last.should have_key(:extra)
|
109
|
+
parsed[1].should equal(p)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should call haml parser with opts on do_list_view" do
|
113
|
+
c= Orange::Core.new
|
114
|
+
p= Orange::Packet.new(c, {})
|
115
|
+
c.load(MockHamlParser.new, :parser)
|
116
|
+
c.load(MockModelResourceFour.new, :mocked)
|
117
|
+
parsed = c[:mocked].do_list_view(p, :test, :extra => 'foo')
|
118
|
+
parsed.first.should == 'test.haml'
|
119
|
+
parsed.last.should == c[:mocked].view_opts(p, :test, true, :extra => 'foo')
|
120
|
+
parsed.last.should_not == c[:mocked].view_opts(p, :test, false, :extra => 'foo')
|
121
|
+
parsed.last.should have_key(:extra)
|
122
|
+
parsed[1].should equal(p)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should call carton's get on find_one(packet, mode, id)" do
|
126
|
+
a= MockModelResourceTwo.new
|
127
|
+
a.find_one(Orange::Packet.new(Orange::Core.new, {}), :show).should == false
|
128
|
+
a.find_one(Orange::Packet.new(Orange::Core.new, {}), :show, 1).should == 'mock_get'
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should call carton's all on find_list(packet, mode)" do
|
132
|
+
a= MockModelResourceTwo.new
|
133
|
+
a.find_list(Orange::Packet.new(Orange::Core.new, {}), :show).should == 'mock_all'
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should return an empty hash by default for find_extras" do
|
137
|
+
a= MockModelResourceTwo.new
|
138
|
+
a.find_extras(Orange::Packet.new(Orange::Core.new, {}), :show).should == {}
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
|
-
require 'spec/mock/mock_app'
|
2
|
-
require 'spec/mock/mock_pulp'
|
3
|
-
require 'spec/mock/mock_core'
|
4
|
-
require 'spec/mock/mock_mixins'
|
5
|
-
require 'spec/mock/mock_router'
|
6
|
-
require 'spec/mock/mock_resource'
|
7
|
-
require 'spec/mock/mock_middleware'
|
8
|
-
require 'rack/test'
|
9
|
-
|
10
1
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
11
2
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
12
3
|
|
13
4
|
require 'orange'
|
5
|
+
|
6
|
+
require 'mock/mock_app'
|
7
|
+
require 'mock/mock_pulp'
|
8
|
+
require 'mock/mock_core'
|
9
|
+
require 'mock/mock_carton'
|
10
|
+
require 'mock/mock_model_resource'
|
11
|
+
require 'mock/mock_mixins'
|
12
|
+
require 'mock/mock_router'
|
13
|
+
require 'mock/mock_resource'
|
14
|
+
require 'mock/mock_middleware'
|
15
|
+
require 'rack/test'
|
16
|
+
|
17
|
+
|
14
18
|
Spec::Runner.configure do |config|
|
15
19
|
config.include(Rack::Test::Methods)
|
16
20
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orange
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Haslem
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-28 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -131,14 +131,14 @@ files:
|
|
131
131
|
- lib/orange/middleware/static.rb
|
132
132
|
- lib/orange/middleware/static_file.rb
|
133
133
|
- lib/orange/middleware/template.rb
|
134
|
-
- lib/orange/model_resource.rb
|
135
134
|
- lib/orange/packet.rb
|
136
135
|
- lib/orange/resource.rb
|
137
136
|
- lib/orange/resources/flex_router.rb
|
138
137
|
- lib/orange/resources/mapper.rb
|
138
|
+
- lib/orange/resources/model_resource.rb
|
139
139
|
- lib/orange/resources/page_parts.rb
|
140
140
|
- lib/orange/resources/parser.rb
|
141
|
-
- lib/orange/routable_resource.rb
|
141
|
+
- lib/orange/resources/routable_resource.rb
|
142
142
|
- lib/orange/stack.rb
|
143
143
|
- README.markdown
|
144
144
|
has_rdoc: true
|
@@ -174,21 +174,37 @@ test_files:
|
|
174
174
|
- spec/carton_spec.rb
|
175
175
|
- spec/core_spec.rb
|
176
176
|
- spec/magick_spec.rb
|
177
|
+
- spec/middleware/access_control_spec.rb
|
178
|
+
- spec/middleware/base_spec.rb
|
179
|
+
- spec/middleware/database_spec.rb
|
180
|
+
- spec/middleware/globals_spec.rb
|
181
|
+
- spec/middleware/recapture_spec.rb
|
182
|
+
- spec/middleware/rerouter_spec.rb
|
183
|
+
- spec/middleware/restful_router_spec.rb
|
184
|
+
- spec/middleware/route_context_spec.rb
|
185
|
+
- spec/middleware/route_site_spec.rb
|
186
|
+
- spec/middleware/show_exceptions_spec.rb
|
187
|
+
- spec/middleware/site_load_spec.rb
|
188
|
+
- spec/middleware/static_file_spec.rb
|
189
|
+
- spec/middleware/static_spec.rb
|
190
|
+
- spec/middleware/template_spec.rb
|
177
191
|
- spec/mock/mock_app.rb
|
192
|
+
- spec/mock/mock_carton.rb
|
178
193
|
- spec/mock/mock_core.rb
|
179
194
|
- spec/mock/mock_middleware.rb
|
180
195
|
- spec/mock/mock_mixins.rb
|
196
|
+
- spec/mock/mock_model_resource.rb
|
181
197
|
- spec/mock/mock_pulp.rb
|
182
198
|
- spec/mock/mock_resource.rb
|
183
199
|
- spec/mock/mock_router.rb
|
184
|
-
- spec/model_resource_spec.rb
|
185
200
|
- spec/orange_spec.rb
|
186
201
|
- spec/packet_spec.rb
|
187
202
|
- spec/resource_spec.rb
|
188
203
|
- spec/resources/flex_router_spec.rb
|
189
204
|
- spec/resources/mapper_spec.rb
|
205
|
+
- spec/resources/model_resource_spec.rb
|
190
206
|
- spec/resources/parser_spec.rb
|
191
|
-
- spec/routable_resource_spec.rb
|
207
|
+
- spec/resources/routable_resource_spec.rb
|
192
208
|
- spec/spec_helper.rb
|
193
209
|
- spec/stack_spec.rb
|
194
210
|
- spec/stats.rb
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'orange/routable_resource'
|
2
|
-
|
3
|
-
module Orange
|
4
|
-
class ModelResource < RoutableResource
|
5
|
-
extend ClassInheritableAttributes
|
6
|
-
cattr_inheritable :model_class
|
7
|
-
|
8
|
-
def self.use(my_model_class)
|
9
|
-
@model_class = my_model_class
|
10
|
-
end
|
11
|
-
|
12
|
-
|
13
|
-
def model_class
|
14
|
-
self.class.model_class
|
15
|
-
end
|
16
|
-
|
17
|
-
def view(packet, *args)
|
18
|
-
opts = args.extract_options!.with_defaults({:path => ''})
|
19
|
-
props = model_class.form_props(packet['route.context'])
|
20
|
-
resource_id = opts[:id] || packet['route.resource_id'] || false
|
21
|
-
mode = opts[:mode] || packet['route.resource_action'] ||
|
22
|
-
(resource_id ? :show : :list)
|
23
|
-
|
24
|
-
haml_opts = {:props => props, :resource => self.class.to_s, :model_name => @my_orange_name}.merge!(opts)
|
25
|
-
|
26
|
-
case mode
|
27
|
-
when :show
|
28
|
-
haml_opts.with_defaults! :model => findOne(packet, mode, resource_id)
|
29
|
-
orange[:parser].haml('show.haml', packet, haml_opts)
|
30
|
-
when :edit
|
31
|
-
haml_opts.with_defaults! :model => findOne(packet, mode, resource_id)
|
32
|
-
orange[:parser].haml('edit.haml', packet, haml_opts)
|
33
|
-
when :create
|
34
|
-
haml_opts.with_defaults! :model => findOne(packet, mode, resource_id)
|
35
|
-
orange[:parser].haml('create.haml', packet, haml_opts)
|
36
|
-
when :table_row
|
37
|
-
haml_opts.with_defaults! :model => findOne(packet, mode, resource_id)
|
38
|
-
orange[:parser].haml('table_row.haml', packet, haml_opts)
|
39
|
-
when :list
|
40
|
-
haml_opts.with_defaults! :list => findList(packet, mode)
|
41
|
-
orange[:parser].haml('list.haml', packet, haml_opts)
|
42
|
-
else
|
43
|
-
self.__send__(mode, packet, haml_opts)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def findOne(packet, mode, id = false)
|
48
|
-
return false unless id
|
49
|
-
model_class.get(id)
|
50
|
-
end
|
51
|
-
|
52
|
-
def findList(packet, mode)
|
53
|
-
model_class.all || []
|
54
|
-
end
|
55
|
-
|
56
|
-
def viewExtras(packet, mode)
|
57
|
-
{}
|
58
|
-
end
|
59
|
-
|
60
|
-
def route(path, packet)
|
61
|
-
parts = path.split('/')
|
62
|
-
if parts[0] =~ /^[0-9]+$/
|
63
|
-
route_id = parts.shift
|
64
|
-
else
|
65
|
-
route_id = false
|
66
|
-
end
|
67
|
-
parts.unshift('show') if parts.empty? && route_id
|
68
|
-
new_path = parts.join('/')
|
69
|
-
packet['route.resource_id'] = route_id if route_id
|
70
|
-
super(new_path, packet)
|
71
|
-
end
|
72
|
-
|
73
|
-
def new(packet, *opts)
|
74
|
-
if packet.request.post?
|
75
|
-
model_class.new(packet.request.params[@my_orange_name.to_s]).save
|
76
|
-
end
|
77
|
-
packet.reroute(@my_orange_name, :orange)
|
78
|
-
end
|
79
|
-
|
80
|
-
def delete(packet, *opts)
|
81
|
-
if packet.request.delete?
|
82
|
-
m = model_class.get(packet['route.resource_id'])
|
83
|
-
m.destroy! if m
|
84
|
-
end
|
85
|
-
packet.reroute(@my_orange_name, :orange)
|
86
|
-
end
|
87
|
-
|
88
|
-
def save(packet, *opts)
|
89
|
-
if packet.request.post?
|
90
|
-
m = model_class.get(packet['route.resource_id'])
|
91
|
-
if m
|
92
|
-
m.update(packet.request.params[@my_orange_name.to_s])
|
93
|
-
else
|
94
|
-
end
|
95
|
-
end
|
96
|
-
packet.reroute(@my_orange_name, :orange)
|
97
|
-
end
|
98
|
-
|
99
|
-
|
100
|
-
def show(packet, *opts)
|
101
|
-
view(packet, :mode => :show, *opts)
|
102
|
-
end
|
103
|
-
|
104
|
-
def edit(packet, *opts)
|
105
|
-
view(packet, :mode => :edit, *opts)
|
106
|
-
end
|
107
|
-
|
108
|
-
def create(packet, *opts)
|
109
|
-
view(packet, :mode => :create, *opts)
|
110
|
-
end
|
111
|
-
|
112
|
-
def table_row(packet, *opts)
|
113
|
-
view(packet, :mode => :table_row, *opts)
|
114
|
-
end
|
115
|
-
|
116
|
-
def list(packet, *opts)
|
117
|
-
view(packet, :mode => :list, *opts)
|
118
|
-
end
|
119
|
-
|
120
|
-
def index(packet, *opts)
|
121
|
-
view(packet, :mode => :list, *opts)
|
122
|
-
end
|
123
|
-
|
124
|
-
end
|
125
|
-
|
126
|
-
class Packet
|
127
|
-
def form_link(text, link, confirm = false, *args)
|
128
|
-
opts = args.extract_options!
|
129
|
-
meth = (opts[:method]? "<input type='hidden' name='_method' value='#{opts[:method]}' />" : '')
|
130
|
-
if confirm
|
131
|
-
"<form action='#{link}' method='post' class='mini' onsubmit='return confirm(\"#{confirm}\")'><button class='link_button'><a href='#'>#{text}</a></button>#{meth}</form>"
|
132
|
-
else
|
133
|
-
"<form action='#{link}' method='post' class='mini'><button class='link_button'><a href='#'>#{text}</a></button>#{meth}</form>"
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def view(model_name, *args)
|
138
|
-
orange[model_name].view(self, *args)
|
139
|
-
end
|
140
|
-
|
141
|
-
def view_attribute(prop, model_name, *args)
|
142
|
-
args = args.extract_options!
|
143
|
-
val = args[:value] || ''
|
144
|
-
label = args[:label] || false
|
145
|
-
show = args[:show] || false
|
146
|
-
name = prop[:name]
|
147
|
-
if !show
|
148
|
-
case prop[:type]
|
149
|
-
when :title
|
150
|
-
ret = "<input class='title' type='text' value='#{val}' name='#{model_name}[#{name}]' />"
|
151
|
-
when :text
|
152
|
-
ret = "<input type='text' value='#{val}' name='#{model_name}[#{name}]' />"
|
153
|
-
when :fulltext
|
154
|
-
ret = "<textarea name='#{model_name}[#{name}]'>#{val}</textarea>"
|
155
|
-
end
|
156
|
-
ret = "<label for=''>#{name}</label><br />" + ret if label
|
157
|
-
else
|
158
|
-
case prop[:type]
|
159
|
-
when :title
|
160
|
-
ret = "<h3 class='#{model_name}-#{name}'>#{val}</h3>"
|
161
|
-
when :text
|
162
|
-
ret = "<p class='#{model_name}-#{name}'>#{val}</p>"
|
163
|
-
when :fulltext
|
164
|
-
ret = "<div class='#{model_name}-#{name}'>#{val}</div>"
|
165
|
-
end
|
166
|
-
end
|
167
|
-
ret
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
data/spec/model_resource_spec.rb
DELETED