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.
@@ -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... but such a clone doesn't exist [does it](http://github.com/therabidbanana/orange-juice)?
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
- No. This is where Ruby on Rails shines, it's a well supported, thoroughly tested framework
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
- Yes. This is what orange was designed for - we're building it to be able to quickly deploy
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
@@ -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}"}
@@ -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
 
@@ -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
- Dir.glob(File.join(orange.app_dir, 'resources', '*.rb')).each do |f|
6
- require f
7
- orange.load Orange::Inflector.constantize(Orange::Inflector.camelize(File.basename(f, '.rb'))).new
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)
@@ -62,6 +62,7 @@ module Orange
62
62
  end
63
63
 
64
64
  def viewable(packet, mode, opts={})
65
+ self.class.viewable_actions ||= []
65
66
  if(self.respond_to?(mode))
66
67
  self.__send__(mode, packet, opts)
67
68
  elsif(self.class.viewable_actions.include?(mode))
@@ -22,6 +22,7 @@ module Orange
22
22
  args.unshift(resource)
23
23
  args.unshift(context)
24
24
  args.unshift(site)
25
+ orange.fire(:route_extras, packet, args)
25
26
  root_url(packet) + args.compact.join('/')
26
27
  end
27
28
  end
@@ -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 resource
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!({:packet => packet, :value => '', :label => false, :show => false})
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!('"', '&quot;')
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!('"', '&quot;')
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 = "<h3 class='#{model_name}-#{name}'>#{val}</h3>"
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
@@ -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
- %p= view_attribute(prop, model_name, :label => true)
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
- %p!= view_attribute(prop, model_name, :label => true, :value => model.attribute_get(prop[:name]), :model => model)
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
- = view_attribute(prop, model_name, :show => true, :value => model.attribute_get(prop[:name]), :model => model)
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
- %td= model.attribute_get(prop[:name]).to_s[0..150]
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::Types::Serial)
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::Types::Text, anything())
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)
@@ -40,4 +40,7 @@ class MockCartonBlank < Orange::Carton
40
40
  end
41
41
 
42
42
  class MockCartonBlankTwo < Orange::Carton
43
+ end
44
+
45
+ class MockCartonForCore < Orange::Carton
43
46
  end
@@ -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(9).middlewares
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(8).middlewares
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
- - 0
9
- version: 0.7.0
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-05 00:00:00 -04:00
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: therabidbanana@gmail.com
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/therabidbanana/orange-core
164
+ homepage: http://github.com/orange-project/orange-core
165
165
  licenses: []
166
166
 
167
167
  post_install_message: |