orange-core 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +5 -4
- data/lib/orange-core/carton.rb +53 -1
- data/lib/orange-core/core.rb +28 -4
- data/lib/orange-core/magick.rb +9 -0
- data/lib/orange-core/middleware/loader.rb +7 -5
- data/lib/orange-core/middleware/rerouter.rb +1 -1
- data/lib/orange-core/middleware/restful_router.rb +3 -3
- data/lib/orange-core/resource.rb +1 -0
- data/lib/orange-core/resources/mapper.rb +1 -0
- data/lib/orange-core/resources/model_resource.rb +10 -1
- data/lib/orange-core/resources/parser.rb +3 -1
- data/lib/orange-core/resources/scaffold.rb +24 -3
- data/lib/orange-core/stack.rb +1 -1
- data/lib/orange-core/views/default_resource/create.haml +1 -1
- data/lib/orange-core/views/default_resource/edit.haml +4 -1
- data/lib/orange-core/views/default_resource/show.haml +4 -1
- data/lib/orange-core/views/default_resource/table_row.haml +4 -1
- data/spec/orange-core/carton_spec.rb +2 -2
- data/spec/orange-core/core_spec.rb +18 -0
- data/spec/orange-core/mock/mock_carton.rb +3 -0
- data/spec/orange-core/stack_spec.rb +2 -2
- metadata +5 -5
data/README.markdown
CHANGED
@@ -36,19 +36,19 @@ Should I Use Orange?
|
|
36
36
|
|
37
37
|
Sinatra is probably better for this kind of thing. It's perfect for creating quick web apps based on RESTful
|
38
38
|
ideals. Or perhaps use a Sinatra clone built on Orange, so you can incorporate orange plugins and built in
|
39
|
-
database support...
|
39
|
+
database support... But [orange-juice](http://github.com/therabidbanana/orange-juice) was written for orange 0.5, so it's a bit behind. Hopefully it will be updated soon.
|
40
40
|
|
41
41
|
"I want to create a powerful web application that needs to be rock solid and use a
|
42
42
|
well-tested foundation"
|
43
43
|
|
44
|
-
|
44
|
+
This is where Ruby on Rails shines, it's a well supported, thoroughly tested framework
|
45
45
|
for building web applications that gives you everything you need for the lifecycle of your
|
46
|
-
application
|
46
|
+
application.
|
47
47
|
|
48
48
|
"I want to deploy a website on Ruby that has some dynamic elements, maybe allowing me
|
49
49
|
to create my own plugin without jumping through too many hoops."
|
50
50
|
|
51
|
-
|
51
|
+
This is what orange was designed for - we're building it to be able to quickly deploy
|
52
52
|
websites that can have a Ruby base without the heavy-weight Ruby on Rails backend, but also
|
53
53
|
without feeling like you have to start from scratch like it feels in Sinatra.
|
54
54
|
|
@@ -60,6 +60,7 @@ orange-core tries to stay light on the dependencies.
|
|
60
60
|
|
61
61
|
* dm-core (+ dm-[sqlite3|mysql|...]-adapter )
|
62
62
|
* dm-migrations
|
63
|
+
* tilt
|
63
64
|
* rack
|
64
65
|
* haml
|
65
66
|
* crack
|
data/lib/orange-core/carton.rb
CHANGED
@@ -22,7 +22,7 @@ module Orange
|
|
22
22
|
# class and just include DataMapper::Resource. All carton methods are to
|
23
23
|
# improve scaffolding capability.
|
24
24
|
class Carton
|
25
|
-
SCAFFOLD_OPTIONS = [:display_name, :levels] unless defined?(SCAFFOLD_OPTIONS)
|
25
|
+
SCAFFOLD_OPTIONS = [:display_name, :levels, :related_to, :wrap_tag] unless defined?(SCAFFOLD_OPTIONS)
|
26
26
|
extend ClassInheritableAttributes
|
27
27
|
cattr_accessor :scaffold_properties
|
28
28
|
|
@@ -51,6 +51,7 @@ module Orange
|
|
51
51
|
|
52
52
|
# Return properties that should be shown for a given context
|
53
53
|
def self.form_props(context = :live, mode = :any)
|
54
|
+
self.scaffold_properties ||= []
|
54
55
|
self.scaffold_properties.select{|p| should_use?(p, context, mode) }
|
55
56
|
end
|
56
57
|
|
@@ -92,6 +93,10 @@ module Orange
|
|
92
93
|
self.property(name, dm_type, opts)
|
93
94
|
end
|
94
95
|
|
96
|
+
def self.relationship_scaffold(name, type, opts)
|
97
|
+
self.scaffold_properties << {:name => name, :type => type, :levels => @levels, :lazy => false, :relationship => true}.merge(opts) if @levels || opts.has_key?(:levels)
|
98
|
+
end
|
99
|
+
|
95
100
|
# Define a helper for title type database stuff
|
96
101
|
# Show in a context if wrapped in one of the helpers
|
97
102
|
def self.title(name, opts = {})
|
@@ -116,6 +121,12 @@ module Orange
|
|
116
121
|
add_scaffold(name, :time, Time, opts)
|
117
122
|
end
|
118
123
|
|
124
|
+
|
125
|
+
# Show in a context if wrapped in one of the helpers
|
126
|
+
def self.number(name, opts = {})
|
127
|
+
add_scaffold(name, :number, Float, opts)
|
128
|
+
end
|
129
|
+
|
119
130
|
# Define a helper for fulltext type database stuff
|
120
131
|
# Show in a context if wrapped in one of the helpers
|
121
132
|
def self.fulltext(name, opts = {})
|
@@ -134,12 +145,45 @@ module Orange
|
|
134
145
|
add_scaffold(name, :text, String, opts)
|
135
146
|
end
|
136
147
|
|
148
|
+
# Define a helper for belongs_to stuff
|
149
|
+
def self.belongs(name, model, opts = {})
|
150
|
+
relationship_scaffold(name, :belongs, opts.with_defaults(:related_to => model))
|
151
|
+
opts = opts.delete_if{|k,v| SCAFFOLD_OPTIONS.include?(k)} # DataMapper doesn't like arbitrary opts
|
152
|
+
self.belongs_to(name, model, opts)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Define a helper for has_one
|
156
|
+
def self.has_one(name, model, opts = {})
|
157
|
+
relationship_scaffold(name, :has_one, opts.with_defaults(:related_to => model))
|
158
|
+
opts = opts.delete_if{|k,v| SCAFFOLD_OPTIONS.include?(k)} # DataMapper doesn't like arbitrary opts
|
159
|
+
self.has(1, name, model, opts)
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
# Define a helper for has_many
|
164
|
+
def self.has_many(name, model, opts = {})
|
165
|
+
relationship_scaffold(name, :has_many, opts.with_defaults(:related_to => model))
|
166
|
+
opts = opts.delete_if{|k,v| SCAFFOLD_OPTIONS.include?(k)} # DataMapper doesn't like arbitrary opts
|
167
|
+
self.has(n, name, model, opts)
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
# Define a helper for has_many
|
172
|
+
def self.has_and_belongs_to_many(name, model, opts = {})
|
173
|
+
relationship_scaffold(name, :has_and_belongs_to_many, opts.with_defaults(:related_to => model))
|
174
|
+
opts = opts.delete_if{|k,v| SCAFFOLD_OPTIONS.include?(k)} # DataMapper doesn't like arbitrary opts
|
175
|
+
opts.with_defaults!({:through => DataMapper::Resource})
|
176
|
+
self.has(n, name, model, opts)
|
177
|
+
end
|
178
|
+
|
179
|
+
|
137
180
|
# Define a helper for type database stuff
|
138
181
|
# Show in a context if wrapped in one of the helpers
|
139
182
|
def self.expose(name, opts = {})
|
140
183
|
self.scaffold_properties << {:name => name, :type => :text, :levels => @levels, :opts => opts} if @levels
|
141
184
|
end
|
142
185
|
|
186
|
+
|
143
187
|
# Define a helper for input type="text" type database stuff
|
144
188
|
# Show in a context if wrapped in one of the helpers
|
145
189
|
def self.string(name, opts = {})
|
@@ -177,6 +221,14 @@ module Orange
|
|
177
221
|
add_scaffold(name, my_type, type, opts)
|
178
222
|
end
|
179
223
|
|
224
|
+
def scaffold_name
|
225
|
+
titles = self.class.scaffold_properties.select{|p| p[:type] == :title}
|
226
|
+
return __send__(titles.first[:name]) if(self.respond_to?(titles.first[:name]))
|
227
|
+
return title if(self.respond_to?(:title))
|
228
|
+
return name if(self.respond_to?(:name))
|
229
|
+
return "#{self.class.to_s} ##{id}"
|
230
|
+
end
|
231
|
+
|
180
232
|
def to_s
|
181
233
|
<<-DOC
|
182
234
|
{"class": "#{self.class.to_s}", "id": "#{self.id}"}
|
data/lib/orange-core/core.rb
CHANGED
@@ -40,6 +40,18 @@ module Orange
|
|
40
40
|
Packet.mixin inc
|
41
41
|
end
|
42
42
|
|
43
|
+
# Automatically load and require resources, cartons, and middleware
|
44
|
+
def self.autoload!
|
45
|
+
Dir.glob(File.join('cartons', '*.rb')).each { |f| require f }
|
46
|
+
Dir.glob(File.join('resources', '*.rb')).each { |f| require f }
|
47
|
+
Dir.glob(File.join('middleware', '*.rb')).each { |f| require f }
|
48
|
+
@required = true
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.autoloaded?
|
52
|
+
@required || false
|
53
|
+
end
|
54
|
+
|
43
55
|
# Core is one of two main sources of interaction for Orange Applications
|
44
56
|
#
|
45
57
|
# All portions of Orange based code have access to the Core upon
|
@@ -72,13 +84,13 @@ module Orange
|
|
72
84
|
# This method calls afterLoad when it is done. Subclasses can override
|
73
85
|
# the afterLoad method for initialization needs.
|
74
86
|
def initialize(*args, &block)
|
75
|
-
@options = Mash.new(Options.new(*args, &block).hash.with_defaults(DEFAULT_CORE_OPTIONS))
|
76
87
|
@resources = {}
|
77
88
|
@application = false
|
78
89
|
@stack = false
|
79
90
|
@middleware = []
|
80
91
|
@events = {}
|
81
92
|
@file = __FILE__
|
93
|
+
@options = Mash.new(Orange::Options.new(self, *args, &block).hash.with_defaults(DEFAULT_CORE_OPTIONS))
|
82
94
|
load(Orange::Parser.new, :parser)
|
83
95
|
load(Orange::Mapper.new, :mapper)
|
84
96
|
load(Orange::Scaffold.new, :scaffold)
|
@@ -127,7 +139,7 @@ module Orange
|
|
127
139
|
# @param [Symbol] resource_name The short name of the resource
|
128
140
|
# @return [Boolean] result of has_key? in the resources list
|
129
141
|
def loaded?(resource_name)
|
130
|
-
@resources.has_key?(resource_name)
|
142
|
+
@resources.has_key?(resource_name) && (!@resources[resource_name].blank?)
|
131
143
|
end
|
132
144
|
|
133
145
|
# Takes an instance of a Orange::Resource subclass, sets orange
|
@@ -140,6 +152,9 @@ module Orange
|
|
140
152
|
# Resources must respond to set_orange, which is automatically used to
|
141
153
|
# create a link back to the Core, and to notify the resource of its assigned
|
142
154
|
# short name.
|
155
|
+
#
|
156
|
+
# 0.7 Feature - Passing a Carton class instead of an Orange::Resource instance
|
157
|
+
# will call Carton#as_resource and then load the ModelResource for that carton
|
143
158
|
#
|
144
159
|
# @param [Orange::Resource] resource An instance of Orange::Resource subclass
|
145
160
|
# @param [optional, Symbol, String] name A short name to assign as key in Hash
|
@@ -147,11 +162,20 @@ module Orange
|
|
147
162
|
# Doesn't necessarily need to be a symbol, but generally is.
|
148
163
|
# Set to the class name lowercase as a symbol by default.
|
149
164
|
def load(resource, name = false)
|
165
|
+
if(resource.instance_of?(Class) && (resource < Orange::Carton))
|
166
|
+
carton = resource # Resource isn't really ar resource
|
167
|
+
carton.as_resource
|
168
|
+
resource_class = Object.const_get("#{carton.to_s}_Resource")
|
169
|
+
resource = resource_class.new
|
170
|
+
name = carton.to_s.gsub(/::/, '_').downcase.to_sym if(!name)
|
171
|
+
end
|
150
172
|
name = resource.orange_name if(!name)
|
151
|
-
name = resource.class.to_s.gsub(/::/, '_').downcase.to_sym if(!name)
|
173
|
+
name = resource.class.to_s.gsub(/::/, '_').downcase.to_sym if(!name)
|
152
174
|
@resources[name] = resource.set_orange(self, name)
|
153
175
|
end
|
154
176
|
|
177
|
+
|
178
|
+
|
155
179
|
# Takes an instance of Orange::Middleware::Base subclass and
|
156
180
|
# keeps it for later. This way we can provide introspection into the
|
157
181
|
# middleware instances (useful for calling stack_init on them)
|
@@ -229,7 +253,7 @@ module Orange
|
|
229
253
|
#
|
230
254
|
# @return [Mash] Hash-like mash of options
|
231
255
|
def options(*args, &block)
|
232
|
-
@options.merge(Options.new(*args, &block).hash) if (args.size > 0 || block_given?)
|
256
|
+
@options.merge(Options.new(self, *args, &block).hash) if (args.size > 0 || block_given?)
|
233
257
|
@options
|
234
258
|
end
|
235
259
|
|
data/lib/orange-core/magick.rb
CHANGED
@@ -139,6 +139,7 @@ module Orange
|
|
139
139
|
# so this should be used with caution.
|
140
140
|
class Ignore
|
141
141
|
def blank?; true; end
|
142
|
+
def include?(*args); false; end
|
142
143
|
def method_missing(name, *args, &block)
|
143
144
|
return self
|
144
145
|
end
|
@@ -148,6 +149,7 @@ module Orange
|
|
148
149
|
class Options
|
149
150
|
|
150
151
|
def initialize(*options, &block)
|
152
|
+
@core = options.first if(options.size > 0 && options.first.kind_of?(Orange::Core))
|
151
153
|
@options = options.extract_options!
|
152
154
|
@options ||= {}
|
153
155
|
instance_eval(&block) if block_given?
|
@@ -156,11 +158,18 @@ module Orange
|
|
156
158
|
def hash
|
157
159
|
@options
|
158
160
|
end
|
161
|
+
|
162
|
+
# Load needs fixing up.
|
163
|
+
def load(*args)
|
164
|
+
@core.load(*args)
|
165
|
+
end
|
159
166
|
|
160
167
|
def method_missing(key, *args)
|
161
168
|
return (@options[key.to_s.gsub(/\?$/, '').to_sym].eql?(true)) if key.to_s.match(/\?$/)
|
162
169
|
if args.empty?
|
163
170
|
@options[key.to_sym]
|
171
|
+
elsif(@core && @core.respond_to?(key.to_sym))
|
172
|
+
@core.__send__(key, *args)
|
164
173
|
elsif(key.to_s.match(/\=$/))
|
165
174
|
@options[key.to_s.gsub(/\=$/, '').to_sym] = (args.size == 1 ? args.first : args)
|
166
175
|
else
|
@@ -2,12 +2,14 @@ require 'orange-core/middleware/base'
|
|
2
2
|
module Orange::Middleware
|
3
3
|
class Loader < Base
|
4
4
|
def init(*args)
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
unless Orange.autoloaded?
|
6
|
+
Dir.glob(File.join(orange.app_dir, 'resources', '*.rb')).each do |f|
|
7
|
+
require f
|
8
|
+
orange.load Orange::Inflector.constantize(Orange::Inflector.camelize(File.basename(f, '.rb'))).new
|
9
|
+
end
|
10
|
+
Dir.glob(File.join(orange.app_dir, 'cartons', '*.rb')).each { |f| require f }
|
11
|
+
Dir.glob(File.join(orange.app_dir, 'middleware', '*.rb')).each { |f| require f }
|
8
12
|
end
|
9
|
-
Dir.glob(File.join(orange.app_dir, 'cartons', '*.rb')).each { |f| require f }
|
10
|
-
Dir.glob(File.join(orange.app_dir, 'middleware', '*.rb')).each { |f| require f }
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
@@ -40,7 +40,7 @@ module Orange
|
|
40
40
|
packet['reroute.to']
|
41
41
|
# Parsing for orange urls or something
|
42
42
|
when :orange
|
43
|
-
packet.route_to(packet['reroute.to'], *packet['reroute.args', []])
|
43
|
+
"http://"+packet.env['HTTP_HOST']+packet.route_to(packet['reroute.to'], *packet['reroute.args', []])
|
44
44
|
else
|
45
45
|
packet['reroute.to']
|
46
46
|
end
|
@@ -47,13 +47,13 @@ module Orange::Middleware
|
|
47
47
|
pad = parts.shift
|
48
48
|
if !parts.empty?
|
49
49
|
resource = parts.shift
|
50
|
-
if orange.loaded?(resource.to_sym) && (!nested_in || orange[nested_in].nests.keys.include?(resource.to_sym))
|
50
|
+
if orange.loaded?(resource.to_sym) && (!nested_in || orange[nested_in, true].nests.keys.include?(resource.to_sym))
|
51
51
|
return_parts[:resource] = resource.to_sym
|
52
52
|
if !parts.empty?
|
53
53
|
second = parts.shift
|
54
54
|
if second =~ /^\d+$/
|
55
55
|
return_parts[:resource_id] = second
|
56
|
-
if !(parts.empty? || orange[resource.to_sym].nests.keys.include?(parts.first.to_sym))
|
56
|
+
if !(parts.empty? || orange[resource.to_sym, true].nests.keys.include?(parts.first.to_sym))
|
57
57
|
return_parts[:resource_action] = parts.shift.to_sym
|
58
58
|
else
|
59
59
|
return_parts[:resource_action] = :show
|
@@ -88,7 +88,7 @@ module Orange::Middleware
|
|
88
88
|
new_path = parts[:remainder]
|
89
89
|
nested = my_parts.last[:resource]
|
90
90
|
end
|
91
|
-
my_parts
|
91
|
+
packet['route.route_parts'] = my_parts
|
92
92
|
end
|
93
93
|
|
94
94
|
def should_route?(packet, parts)
|
data/lib/orange-core/resource.rb
CHANGED
@@ -38,7 +38,7 @@ module Orange
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def nests
|
41
|
-
self.class.nests
|
41
|
+
self.class.nests || {}
|
42
42
|
end
|
43
43
|
|
44
44
|
# Allows the resource to nest inside other resources
|
@@ -163,6 +163,7 @@ module Orange
|
|
163
163
|
no_reroute = opts.delete(:no_reroute)
|
164
164
|
if packet.request.post? || !opts.blank?
|
165
165
|
params = opts.with_defaults(opts.delete(:params) || packet.request.params[@my_orange_name.to_s] || {})
|
166
|
+
params = params_parse(packet, :new, params)
|
166
167
|
before = beforeNew(packet, params)
|
167
168
|
obj = onNew(packet, params) if before
|
168
169
|
afterNew(packet, obj, params) if before
|
@@ -172,6 +173,12 @@ module Orange
|
|
172
173
|
obj || false
|
173
174
|
end
|
174
175
|
|
176
|
+
def params_parse(packet, mode, params)
|
177
|
+
props = model_class.form_props(packet['route.context'], :any)
|
178
|
+
params.each{|k,v| params[k] = nil if(k.to_s =~ /_id$/ && v.blank?)}
|
179
|
+
params
|
180
|
+
end
|
181
|
+
|
175
182
|
# A callback for the actual new item event
|
176
183
|
def onNew(packet, opts = {})
|
177
184
|
model_class.new(opts)
|
@@ -225,6 +232,7 @@ module Orange
|
|
225
232
|
my_id = opts.delete(:resource_id) || packet['route.resource_id']
|
226
233
|
m = opts.delete(:model) || model_class.get(my_id)
|
227
234
|
params = opts.with_defaults(opts.delete(:params) || packet.request.params[@my_orange_name.to_s] || {})
|
235
|
+
params = params_parse(packet, :save, params)
|
228
236
|
if m
|
229
237
|
before = beforeSave(packet, m, params)
|
230
238
|
onSave(packet, m, params) if before
|
@@ -298,6 +306,7 @@ module Orange
|
|
298
306
|
|
299
307
|
# Exposed method for helping the RestfulRouter class.
|
300
308
|
def exposed(packet)
|
309
|
+
self.class.exposed_actions ||= {:all => [:show, :list], :admin => :all, :orange => :all}
|
301
310
|
all = self.class.exposed_actions[:all]
|
302
311
|
all = [all] unless all.is_a?(Array)
|
303
312
|
context = self.class.exposed_actions[packet['route.context']]
|
@@ -66,9 +66,11 @@ module Orange
|
|
66
66
|
end unless string
|
67
67
|
|
68
68
|
# Check for default resource views
|
69
|
+
string ||= read_if_exists('views', 'default_resource', context+"."+file) if context
|
69
70
|
string ||= read_if_exists('views', 'default_resource', file)
|
70
71
|
@view_dirs.reverse_each do |views_dir|
|
71
|
-
string ||= read_if_exists(views_dir, 'default_resource', file) if
|
72
|
+
string ||= read_if_exists(views_dir, 'default_resource', context+"."+file) if context
|
73
|
+
string ||= read_if_exists(views_dir, 'default_resource', file)
|
72
74
|
end unless string
|
73
75
|
raise LoadError, "Couldn't find haml file '#{file}'" unless string
|
74
76
|
|
@@ -12,11 +12,13 @@ module Orange
|
|
12
12
|
end
|
13
13
|
@scaffold_types = {}
|
14
14
|
add_scaffold_type(:boolean) do |name, val, opts|
|
15
|
+
opts = opts.with_defaults({:wrap_tag => 'p'})
|
15
16
|
if opts[:show]
|
16
17
|
val ? "true" : "false"
|
17
18
|
else
|
18
19
|
ret = "<input type='hidden' name='#{opts[:model_name]}[#{name}]' value='0' /><input type='checkbox' name='#{opts[:model_name]}[#{name}]' value='1' #{'checked="checked"' if (val && val != '')}/>"
|
19
20
|
ret = "<label for=''>#{opts[:display_name]}</label><br />" + ret if opts[:label]
|
21
|
+
ret = "<#{opts[:wrap_tag]}>#{ret}</#{opts[:wrap_tag]}>" if opts[:wrap_tag]
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -27,12 +29,13 @@ module Orange
|
|
27
29
|
|
28
30
|
def scaffold_attribute(packet, prop, model_name, *args)
|
29
31
|
args = args.extract_options!
|
30
|
-
args.with_defaults
|
32
|
+
args = args.with_defaults({:packet => packet, :value => '', :label => false, :show => false, :wrap_tag => 'p'})
|
31
33
|
val = args[:value]
|
32
34
|
label = args[:label]
|
33
35
|
show = args[:show]
|
34
36
|
name = prop[:name]
|
35
37
|
human_readable_name = name.to_s.split('_').each{|w| w.capitalize!}.join(' ')
|
38
|
+
relationship = prop[:relationship]
|
36
39
|
display_name = prop[:display_name] || human_readable_name
|
37
40
|
return @scaffold_types[prop[:type]].call(name, val, args.with_defaults!(:display_name => display_name, :model_name => model_name)) if @scaffold_types.has_key?(prop[:type])
|
38
41
|
unless show
|
@@ -51,15 +54,33 @@ module Orange
|
|
51
54
|
when :date
|
52
55
|
val.gsub!('"', '"')
|
53
56
|
ret = "<input class=\"date\" type=\"text\" value=\"#{val}\" name=\"#{model_name}[#{name}]\" />"
|
57
|
+
when :belongs
|
58
|
+
val_id = val.blank? ? nil : val.id
|
59
|
+
vals = Object.const_get(prop[:related_to]).all
|
60
|
+
vals = vals.map{|obj| "<option value=\"#{obj.id}\"#{val_id && val_id == obj.id ? 'selected=\'selected\'' : ''}>#{obj.scaffold_name}</option>"}.join("\n")
|
61
|
+
ret = "<select name=\"#{model_name}[#{name}_id]\">#{prop[:required] ? '' : '<option value="">None</option>'}#{vals}</select>"
|
62
|
+
when :has_one
|
63
|
+
ret = ""
|
64
|
+
args[:wrap_tag] = false
|
65
|
+
when :has_many
|
66
|
+
ret = ""
|
67
|
+
args[:wrap_tag] = false
|
68
|
+
when :has_and_belongs_to_many
|
69
|
+
ret = ""
|
70
|
+
args[:wrap_tag] = false
|
71
|
+
when :number
|
72
|
+
val = val.to_s
|
73
|
+
ret = "<input class=\"number\" type=\"text\" value=\"#{val}\" name=\"#{model_name}[#{name}]\" />"
|
54
74
|
else
|
55
75
|
val.gsub!('"', '"')
|
56
76
|
ret = "<input type=\"text\" value=\"#{val}\" name=\"#{model_name}[#{name}]\" />"
|
57
77
|
end
|
58
|
-
ret = "<label for=''>#{display_name}</label><br />" + ret if label
|
78
|
+
ret = "<label for=''>#{display_name}</label><br />" + ret if label && !ret.blank?
|
79
|
+
ret = "<#{args[:wrap_tag]}>#{ret}</#{args[:wrap_tag]}>" if args[:wrap_tag]
|
59
80
|
else
|
60
81
|
case prop[:type]
|
61
82
|
when :title
|
62
|
-
ret = "<
|
83
|
+
ret = "<h1 class='#{model_name}-#{name}'>#{val}</h3>"
|
63
84
|
when :text
|
64
85
|
ret = "<p class='#{model_name}-#{name}'>#{val}</p>"
|
65
86
|
when :fulltext
|
data/lib/orange-core/stack.rb
CHANGED
@@ -94,7 +94,7 @@ module Orange
|
|
94
94
|
# Shortcut for adding Orange::Middleware::ShowExceptions to the middleware
|
95
95
|
# stack
|
96
96
|
def use_exceptions
|
97
|
-
stack Orange::Middleware::ShowExceptions
|
97
|
+
stack Orange::Middleware::ShowExceptions unless ENV['RACK_ENV'] == 'production'
|
98
98
|
end
|
99
99
|
|
100
100
|
# Alias for use_exceptions
|
@@ -1,4 +1,4 @@
|
|
1
1
|
%form{:action => "#{packet.route_to(model_name, 'new')}", :method => 'post', :"accept-charset" => "UTF-8"}
|
2
2
|
- for prop in props
|
3
|
-
|
3
|
+
!~ view_attribute(prop, model_name, :label => true)
|
4
4
|
%input{:type => 'submit', :value => 'Save New Item'}
|
@@ -3,7 +3,10 @@
|
|
3
3
|
= orange[:sitemap, true].sitemap_links(packet, {:slug_me => orange[:sitemap, true].slug_for(model, props)})
|
4
4
|
%form{:action => packet.route_to(model_name, model[:id], 'save'), :method => 'post', :"accept-charset" => "UTF-8"}
|
5
5
|
- for prop in props
|
6
|
-
|
6
|
+
- if(prop[:relationship])
|
7
|
+
!~ view_attribute(prop, model_name, :label => true, :value => model.__send__(prop[:name]), :model => model)
|
8
|
+
- else
|
9
|
+
!~ view_attribute(prop, model_name, :label => true, :value => model.attribute_get(prop[:name]), :model => model)
|
7
10
|
%input{:type => 'submit', :value => 'Save Changes'}
|
8
11
|
- else
|
9
12
|
%p Couldn't find the item you're looking for.
|
@@ -1,4 +1,7 @@
|
|
1
1
|
- if model
|
2
2
|
%div{ :class => model_name}
|
3
3
|
- for prop in props
|
4
|
-
|
4
|
+
- if(prop[:relationship])
|
5
|
+
!~ view_attribute(prop, model_name, :show => true, :value => model.__send__(prop[:name]), :model => model)
|
6
|
+
- else
|
7
|
+
!~ view_attribute(prop, model_name, :show => true, :value => model.attribute_get(prop[:name]), :model => model)
|
@@ -1,7 +1,10 @@
|
|
1
1
|
- if model
|
2
2
|
%tr
|
3
3
|
- for prop in props
|
4
|
-
|
4
|
+
- if(prop[:relationship])
|
5
|
+
%td= [:belongs, :has_one].include?(prop[:type]) ? (model.__send__(prop[:name]) ? model.__send__(prop[:name]).scaffold_name : "") : ""
|
6
|
+
- else
|
7
|
+
%td= model.attribute_get(prop[:name]).to_s[0..150]
|
5
8
|
%td.actions
|
6
9
|
= form_link('Delete', route_to(model_name, model.id, 'delete'), 'Are you sure you want to delete this?', {:method => 'delete'})
|
7
10
|
%a{:href => route_to(model_name, model.id, 'edit')} Edit
|
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe Orange::Carton do
|
4
4
|
it "should call property with :id, Serial on #self.id" do
|
5
|
-
MockCartonBlank.should_receive(:property).with(:id, DataMapper::
|
5
|
+
MockCartonBlank.should_receive(:property).with(:id, DataMapper::Property::Serial)
|
6
6
|
MockCartonBlank.id
|
7
7
|
end
|
8
8
|
|
@@ -120,7 +120,7 @@ describe Orange::Carton do
|
|
120
120
|
end
|
121
121
|
|
122
122
|
it "should call property on fulltext" do
|
123
|
-
MockCarton.should_receive(:property).with(an_instance_of(Symbol), DataMapper::
|
123
|
+
MockCarton.should_receive(:property).with(an_instance_of(Symbol), DataMapper::Property::Text, anything())
|
124
124
|
MockCarton.fulltext(:cudge)
|
125
125
|
end
|
126
126
|
|
@@ -3,6 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
3
3
|
describe Orange::Core do
|
4
4
|
before(:all) do
|
5
5
|
class Orange::Core; attr_reader :resources, :events, :file; end;
|
6
|
+
class MockCartonForCore < Orange::Carton; end;
|
6
7
|
end
|
7
8
|
|
8
9
|
it "should allow core mixin via class mixin method" do
|
@@ -139,6 +140,14 @@ describe Orange::Core do
|
|
139
140
|
c.options.should_not have_key(:opt_3)
|
140
141
|
end
|
141
142
|
|
143
|
+
it "should allow passthrough of options (for load method)" do
|
144
|
+
c= Orange::Core.new(:opt_1 => true) do
|
145
|
+
opt_2 true
|
146
|
+
load Orange::ModelResource.new, :foo
|
147
|
+
end
|
148
|
+
c[:foo].should be_an_instance_of(Orange::ModelResource)
|
149
|
+
end
|
150
|
+
|
142
151
|
it "should have a mash options hash" do
|
143
152
|
c= Orange::Core.new(:opt_1 => true, "opt_4" => 'banana'){ opt_2 true }
|
144
153
|
c.options.should be_an_instance_of(Mash)
|
@@ -177,6 +186,15 @@ describe Orange::Core do
|
|
177
186
|
c.resources.should have_key(:mock_one)
|
178
187
|
end
|
179
188
|
|
189
|
+
it "should say a resource is loaded after calling load for carton" do
|
190
|
+
c= Orange::Core.new
|
191
|
+
MockCartonForCore.should < Orange::Carton
|
192
|
+
c.load(MockCartonForCore, :mock_one)
|
193
|
+
c.should be_loaded(:mock_one)
|
194
|
+
c.resources.should have_key(:mock_one)
|
195
|
+
c[:mock_one].model_class.should == MockCartonForCore
|
196
|
+
end
|
197
|
+
|
180
198
|
it "should return self on orange" do
|
181
199
|
c= Orange::Core.new
|
182
200
|
c.orange.should eql(c)
|
@@ -160,7 +160,7 @@ describe Orange::Stack do
|
|
160
160
|
end
|
161
161
|
x.middlewarez.should have(1).middlewares
|
162
162
|
x.prerouting
|
163
|
-
x.middlewarez.should have(
|
163
|
+
x.middlewarez.should have(10).middlewares
|
164
164
|
x.middlewarez.select{|y| y.instance_of?(Orange::Middleware::AbstractFormat)}.should_not be_empty
|
165
165
|
x.middlewarez.select{|y| y.instance_of?(Orange::Middleware::RouteSite)}.should_not be_empty
|
166
166
|
end
|
@@ -188,7 +188,7 @@ describe Orange::Stack do
|
|
188
188
|
end
|
189
189
|
x.middlewarez.should have(1).middlewares
|
190
190
|
x.prerouting(:no_abstract_format => true)
|
191
|
-
x.middlewarez.should have(
|
191
|
+
x.middlewarez.should have(9).middlewares
|
192
192
|
x.middlewarez.select{|y| y.instance_of?(Orange::Middleware::AbstractFormat)}.should be_empty
|
193
193
|
x.middlewarez.select{|y| y.instance_of?(Orange::Middleware::RouteSite)}.should_not be_empty
|
194
194
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 7
|
8
|
-
-
|
9
|
-
version: 0.7.
|
8
|
+
- 1
|
9
|
+
version: 0.7.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- David Haslem
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-27 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -110,7 +110,7 @@ dependencies:
|
|
110
110
|
type: :development
|
111
111
|
version_requirements: *id007
|
112
112
|
description: Orange is a Ruby framework for building managed websites with code as simple as Sinatra
|
113
|
-
email:
|
113
|
+
email: david@orangesparkleball.com
|
114
114
|
executables: []
|
115
115
|
|
116
116
|
extensions: []
|
@@ -161,7 +161,7 @@ files:
|
|
161
161
|
- lib/orange-core/views/not_found/404.haml
|
162
162
|
- README.markdown
|
163
163
|
has_rdoc: true
|
164
|
-
homepage: http://github.com/
|
164
|
+
homepage: http://github.com/orange-project/orange-core
|
165
165
|
licenses: []
|
166
166
|
|
167
167
|
post_install_message: |
|