hobo 0.8.10 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +126 -2
- data/Rakefile +4 -1
- data/bin/hobo +1 -1
- data/doctest/scopes.rdoctest +11 -4
- data/dryml_generators/rapid/cards.dryml.erb +8 -2
- data/dryml_generators/rapid/forms.dryml.erb +5 -4
- data/dryml_generators/rapid/pages.dryml.erb +150 -65
- data/lib/hobo.rb +1 -1
- data/lib/hobo/accessible_associations.rb +2 -0
- data/lib/hobo/authentication_support.rb +1 -1
- data/lib/hobo/controller.rb +11 -3
- data/lib/hobo/dryml/dryml_doc.rb +1 -1
- data/lib/hobo/fake_initializer.rb +14 -0
- data/lib/hobo/hobo_helper.rb +94 -6
- data/lib/hobo/lifecycles.rb +17 -2
- data/lib/hobo/lifecycles/lifecycle.rb +1 -1
- data/lib/hobo/lifecycles/transition.rb +12 -4
- data/lib/hobo/model.rb +25 -22
- data/lib/hobo/model_controller.rb +42 -37
- data/lib/hobo/model_router.rb +11 -7
- data/lib/hobo/permissions.rb +12 -10
- data/lib/hobo/permissions/associations.rb +1 -1
- data/lib/hobo/static_tags +21 -0
- data/lib/hobo/user.rb +7 -3
- data/lib/hobo/user_controller.rb +7 -7
- data/lib/hobo/view_hints.rb +10 -3
- data/rails_generators/hobo/USAGE +4 -0
- data/rails_generators/hobo_admin_site/USAGE +16 -0
- data/rails_generators/hobo_front_controller/hobo_front_controller_generator.rb +11 -2
- data/rails_generators/hobo_front_controller/templates/controller.rb +6 -0
- data/rails_generators/hobo_front_controller/templates/summary.dryml +103 -0
- data/rails_generators/hobo_model_resource/USAGE +38 -0
- data/rails_generators/hobo_rapid/USAGE +3 -0
- data/rails_generators/hobo_rapid/templates/hobo-rapid.js +7 -3
- data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +4 -0
- data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +5 -0
- data/rails_generators/hobo_subsite/USAGE +16 -0
- data/rails_generators/hobo_subsite/hobo_subsite_generator.rb +1 -1
- data/rails_generators/hobo_user_controller/templates/controller.rb +2 -2
- data/rails_generators/hobo_user_model/templates/model.rb +6 -1
- data/taglibs/rapid.dryml +1 -0
- data/taglibs/rapid_core.dryml +4 -4
- data/taglibs/rapid_forms.dryml +29 -21
- data/taglibs/rapid_generics.dryml +3 -1
- data/taglibs/rapid_lifecycles.dryml +14 -9
- data/taglibs/rapid_navigation.dryml +1 -1
- data/taglibs/rapid_plus.dryml +1 -0
- data/taglibs/rapid_summary.dryml +300 -0
- data/taglibs/rapid_support.dryml +1 -1
- data/taglibs/rapid_user_pages.dryml +21 -19
- data/test/permissions/test_permissions.rb +1 -1
- metadata +12 -4
data/lib/hobo.rb
CHANGED
@@ -26,6 +26,8 @@ module Hobo
|
|
26
26
|
|
27
27
|
def find_or_create_and_update(owner, association_name, finder, record_hash_or_string)
|
28
28
|
if record_hash_or_string.is_a?(String)
|
29
|
+
return nil if record_hash_or_string.blank?
|
30
|
+
|
29
31
|
# An ID or a name - the passed block will find the record
|
30
32
|
record = find_by_name_or_id(finder, record_hash_or_string)
|
31
33
|
|
@@ -67,7 +67,7 @@ module Hobo
|
|
67
67
|
accepts.xml do
|
68
68
|
headers["Status"] = "Unauthorized"
|
69
69
|
headers["WWW-Authenticate"] = %(Basic realm="Web Password")
|
70
|
-
render :text => "Couldn't authenticate you", :status => '401 Unauthorized'
|
70
|
+
render :text => ht("hobo.messages.unauthenticated", :default=>["Couldn't authenticate you"], :status => '401 Unauthorized')
|
71
71
|
end
|
72
72
|
end
|
73
73
|
false
|
data/lib/hobo/controller.rb
CHANGED
@@ -23,6 +23,7 @@ module Hobo
|
|
23
23
|
Thread.current['Hobo.current_controller'] = nil # should avoid memory-leakage
|
24
24
|
end
|
25
25
|
@included_taglibs = []
|
26
|
+
rescue_from ActionController::RoutingError, :with => :not_found
|
26
27
|
end
|
27
28
|
Hobo::HoboHelper.add_to_controller(klass)
|
28
29
|
end
|
@@ -108,9 +109,10 @@ module Hobo
|
|
108
109
|
|
109
110
|
def render_tags(objects, tag, options={})
|
110
111
|
for_type = options.delete(:for_type)
|
112
|
+
base_tag = tag
|
111
113
|
|
112
114
|
results = objects.map do |o|
|
113
|
-
tag = tag_renderer.find_polymorphic_tag(
|
115
|
+
tag = tag_renderer.find_polymorphic_tag(base_tag, o.class) if for_type
|
114
116
|
tag_renderer.send(tag, options.merge(:with => o))
|
115
117
|
end.join
|
116
118
|
|
@@ -154,8 +156,14 @@ module Hobo
|
|
154
156
|
request.env['HTTP_CACHE_CONTROL'] =~ /max-age=\s*0/
|
155
157
|
end
|
156
158
|
|
157
|
-
def not_found
|
158
|
-
|
159
|
+
def not_found(error)
|
160
|
+
if "not_found_response".in?(self.class.superclass.instance_methods)
|
161
|
+
super
|
162
|
+
elsif render_tag("not-found-page", {}, :status => 404)
|
163
|
+
# cool
|
164
|
+
else
|
165
|
+
render(:text => ht(:"hobo.messages.not_found", :default=>["The page you requested cannot be found."]) , :status => 404)
|
166
|
+
end
|
159
167
|
end
|
160
168
|
|
161
169
|
end
|
data/lib/hobo/dryml/dryml_doc.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
# really what we want is a reference to the Initializer used in
|
2
|
+
# config/boot.rb. But since we can't monkey patch that file, we'll
|
3
|
+
# use a fake instead.
|
4
|
+
|
5
|
+
# this is used by the rapid_summary tag with_plugins
|
6
|
+
module Hobo
|
7
|
+
class FakeInitializer
|
8
|
+
attr_reader :configuration
|
9
|
+
|
10
|
+
def initialize(config = Rails.configuration)
|
11
|
+
@configuration = config
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/hobo/hobo_helper.rb
CHANGED
@@ -45,7 +45,7 @@ module Hobo
|
|
45
45
|
|
46
46
|
|
47
47
|
def subsite
|
48
|
-
params[:controller].match(/([^\/]+)\//)._?[1]
|
48
|
+
params[:controller]._?.match(/([^\/]+)\//)._?[1]
|
49
49
|
end
|
50
50
|
|
51
51
|
|
@@ -192,12 +192,20 @@ module Hobo
|
|
192
192
|
|
193
193
|
|
194
194
|
def first_item?
|
195
|
-
|
195
|
+
if scope.repeat_collection.respond_to? :each_pair
|
196
|
+
this == scope.repeat_collection.first.try.last
|
197
|
+
else
|
198
|
+
this == scope.repeat_collection.first
|
199
|
+
end
|
196
200
|
end
|
197
201
|
|
198
202
|
|
199
203
|
def last_item?
|
200
|
-
|
204
|
+
if scope.repeat_collection.respond_to? :each_pair
|
205
|
+
this == scope.repeat_collection.last.try.last
|
206
|
+
else
|
207
|
+
this == scope.repeat_collection.last
|
208
|
+
end
|
201
209
|
end
|
202
210
|
|
203
211
|
|
@@ -476,12 +484,16 @@ module Hobo
|
|
476
484
|
|
477
485
|
# --- ViewHint Helpers --- #
|
478
486
|
|
479
|
-
def this_field_name
|
480
|
-
this_parent.class.try.
|
487
|
+
def this_field_name
|
488
|
+
key = "#{this_parent.class.try.name.underscore}.#{this_field.to_s}"
|
489
|
+
default = this_parent.class.try.view_hints.try.field_name(this_field) || this_field
|
490
|
+
I18n.t(key, :default => default, :scope => [:activerecord, :attributes], :count => 1)
|
481
491
|
end
|
482
492
|
|
483
493
|
def this_field_help
|
484
|
-
this_parent.class.try.
|
494
|
+
key = "#{this_parent.class.try.name.pluralize.underscore}.hints.#{this_field.to_s}"
|
495
|
+
default = this_parent.class.try.view_hints.try.field_help[this_field.to_sym] || ""
|
496
|
+
I18n.t(key,:default=>default)
|
485
497
|
end
|
486
498
|
|
487
499
|
|
@@ -499,6 +511,82 @@ module Hobo
|
|
499
511
|
logger.debug("###################\n")
|
500
512
|
args.first unless args.empty?
|
501
513
|
end
|
514
|
+
|
515
|
+
# --- Translation Helper --- #
|
516
|
+
#
|
517
|
+
# Uses RoR native I18n.translate.
|
518
|
+
#
|
519
|
+
# Adds some conventions for easier hobo translation.
|
520
|
+
# 1. Assumes the first part of the key to be a model name (e.g.: users.index.title -> user)
|
521
|
+
# 2. Tries to translate the model by lookup for: (e.g.: user-> activerecord.models.user)
|
522
|
+
# 3. Adds a default fallback to the beginning of the fallback chain
|
523
|
+
# by replacing the first part of the key with "hobo" and using the translated model name
|
524
|
+
# as additional attribute. This allows us to have default translations
|
525
|
+
# (e.g.: hobo.index.title: "{{model}} Index")
|
526
|
+
#
|
527
|
+
# Is also used as a tag in the dryml-view files. The syntax is:
|
528
|
+
# <ht key="my.app">My Application</ht>
|
529
|
+
# --> Will lookup the "my.app"-key for your locale and replaces the "My Application" content
|
530
|
+
# if found.
|
531
|
+
#
|
532
|
+
# <ht key="my" app="Program">My Application</ht>
|
533
|
+
# --> Will look up both the "my"- and "app"-key for your locale, and replaces the
|
534
|
+
# "My Application" with the "my"-key contents (interpolated using the "app"-key.
|
535
|
+
# sample.en.yml-file:
|
536
|
+
# "no":
|
537
|
+
# my: "Mitt {{app}}"
|
538
|
+
# The output should be: Mitt Program
|
539
|
+
#
|
540
|
+
# Otherwise with features as the ht method, step 1, 2 and 3 above.
|
541
|
+
def ht(key, options={})
|
542
|
+
|
543
|
+
# Check if called as a tag, i.e. like this <ht></ht>
|
544
|
+
if (key.class == Hash)
|
545
|
+
if key.has_key?(:default) && !key[:default].blank?
|
546
|
+
logger.warn "hobo-i18n: 'default' should not be used as an attribute on the ht-tag. If used, then you need to make sure that the tags inner-contents are not used. These are normally treated as defaults automatically, but if there is a default attribute then that inner-content will be hidden from this method - and will not be replaced with the translation found."
|
547
|
+
end
|
548
|
+
defaults = options[:default];
|
549
|
+
# Swap key and options, remove options[:key]
|
550
|
+
options = key
|
551
|
+
key = options.delete(:key) # returns value for options[:key] as well as deleting it
|
552
|
+
# Set options[:default] to complete the tag-argument-conversion process.
|
553
|
+
options[:default] = (defaults.class == Proc) ? [defaults.call(options)] : (options[:default].blank? ? [] : [options[:default]])
|
554
|
+
else
|
555
|
+
# Not called as a tag. Prepare options[:default].
|
556
|
+
if options[:default].blank?
|
557
|
+
options[:default]=[]
|
558
|
+
elsif options[:default].class != Array
|
559
|
+
options[:default] = [options[:default]]
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
# assume the first part of the key to be the model
|
564
|
+
keys = key.to_s.split(".")
|
565
|
+
if keys.length > 1
|
566
|
+
model = keys.shift()
|
567
|
+
subkey = keys.join(".")
|
568
|
+
else
|
569
|
+
subkey = key
|
570
|
+
end
|
571
|
+
|
572
|
+
# add :"hobo.#{key}" as the first fallback
|
573
|
+
options[:default].unshift("hobo.#{subkey}".to_sym)
|
574
|
+
|
575
|
+
# translate the model
|
576
|
+
unless model.blank?
|
577
|
+
translated_model = I18n.translate( "activerecord.models.#{model.singularize.underscore}", :default=>model).titleize
|
578
|
+
options[:model] = translated_model
|
579
|
+
end
|
580
|
+
|
581
|
+
begin
|
582
|
+
key_prefix = "<span class='translation-key'>#{key}</span>" if HOBO_SHOW_LOCALE_KEYS
|
583
|
+
rescue
|
584
|
+
puts "Set HOBO_SHOW_LOCALE_KEYS=true in your environment to get all locale keys displayed"
|
585
|
+
end
|
586
|
+
|
587
|
+
logger.info "..translate(#{key}, #{options.inspect}) to #{I18n.locale}"
|
588
|
+
I18n.translate(key.to_sym, options)+(key_prefix ? key_prefix:"")
|
589
|
+
end
|
502
590
|
|
503
591
|
end
|
504
592
|
|
data/lib/hobo/lifecycles.rb
CHANGED
@@ -20,7 +20,9 @@ module Hobo
|
|
20
20
|
:key_timestamp_field => :key_timestamp,
|
21
21
|
:key_timeout => 999.years)
|
22
22
|
|
23
|
-
|
23
|
+
# use const_defined so that subclasses can define lifecycles
|
24
|
+
# TODO: figure out how to merge with parent, if desired
|
25
|
+
if self.const_defined?(:Lifecycle)
|
24
26
|
lifecycle = self::Lifecycle
|
25
27
|
else
|
26
28
|
# First call
|
@@ -35,6 +37,10 @@ module Hobo
|
|
35
37
|
|
36
38
|
default = lifecycle.default_state ? { :default => lifecycle.default_state.name.to_s } : {}
|
37
39
|
declare_field(options[:state_field], :string, default)
|
40
|
+
unless options[:index] == false
|
41
|
+
index_options = { :name => options[:index] } unless options[:index] == true
|
42
|
+
index(options[:state_field], index_options || {})
|
43
|
+
end
|
38
44
|
never_show options[:state_field]
|
39
45
|
attr_protected options[:state_field]
|
40
46
|
|
@@ -76,7 +82,16 @@ module Hobo
|
|
76
82
|
|
77
83
|
|
78
84
|
def lifecycle
|
79
|
-
@lifecycle ||= self.class::Lifecycle
|
85
|
+
@lifecycle ||= if defined? self.class::Lifecycle
|
86
|
+
self.class::Lifecycle.new(self)
|
87
|
+
else
|
88
|
+
# search through superclasses
|
89
|
+
current = self.class.superclass
|
90
|
+
until (defined?(current::Lifecycle) || current.nil? || !current.respond_to?(:lifecycle)) do
|
91
|
+
current = current.superclass
|
92
|
+
end
|
93
|
+
current.class::Lifecycle.new(self) if defined? current::Lifecycle
|
94
|
+
end
|
80
95
|
end
|
81
96
|
|
82
97
|
end
|
@@ -20,11 +20,19 @@ module Hobo
|
|
20
20
|
|
21
21
|
|
22
22
|
def extract_attributes(attributes)
|
23
|
-
|
24
|
-
|
23
|
+
model = lifecycle.model
|
24
|
+
params = options.fetch(:params, [])
|
25
|
+
allowed = params.dup
|
26
|
+
params.each do |p|
|
27
|
+
if (refl = model.reflections[p]) && refl.macro == :belongs_to
|
28
|
+
allowed << refl.primary_key_name.to_s
|
29
|
+
allowed << refl.options[:foreign_type] if refl.options[:polymorphic]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
attributes & allowed
|
25
33
|
end
|
26
|
-
|
27
|
-
|
34
|
+
|
35
|
+
|
28
36
|
def change_state(record)
|
29
37
|
record.lifecycle.become(get_state(record, end_state))
|
30
38
|
end
|
data/lib/hobo/model.rb
CHANGED
@@ -85,6 +85,7 @@ module Hobo
|
|
85
85
|
@models_loaded = true
|
86
86
|
end
|
87
87
|
|
88
|
+
@model_names ||= Set.new
|
88
89
|
# ...but only return the ones that registered themselves
|
89
90
|
@model_names.map do |name|
|
90
91
|
name.safe_constantize || (@model_names.delete name; nil)
|
@@ -137,8 +138,18 @@ module Hobo
|
|
137
138
|
require 'active_record/viewhints_validations_interceptor'
|
138
139
|
include Hobo::ViewHintsValidationsInterceptor
|
139
140
|
|
141
|
+
# TODO: should this be an inheriting_cattr_accessor as well? Probably.
|
140
142
|
attr_accessor :creator_attribute
|
141
|
-
|
143
|
+
inheriting_cattr_accessor :name_attribute => Proc.new { |c|
|
144
|
+
names = c.columns.*.name + c.public_instance_methods
|
145
|
+
NAME_FIELD_GUESS.detect {|f| f.in? names }
|
146
|
+
}
|
147
|
+
|
148
|
+
inheriting_cattr_accessor :primary_content_attribute => Proc.new { |c|
|
149
|
+
names = c.columns.*.name + c.public_instance_methods
|
150
|
+
PRIMARY_CONTENT_GUESS.detect {|f| f.in? names }
|
151
|
+
}
|
152
|
+
|
142
153
|
|
143
154
|
def named(*args)
|
144
155
|
raise NoNameError, "Model #{name} has no name attribute" unless name_attribute
|
@@ -157,21 +168,6 @@ module Hobo
|
|
157
168
|
end
|
158
169
|
|
159
170
|
|
160
|
-
def name_attribute
|
161
|
-
@name_attribute ||= begin
|
162
|
-
names = columns.*.name + public_instance_methods
|
163
|
-
NAME_FIELD_GUESS.detect {|f| f.in? names }
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
|
168
|
-
def primary_content_attribute
|
169
|
-
@primary_content_attribute ||= begin
|
170
|
-
names = columns.*.name + public_instance_methods
|
171
|
-
PRIMARY_CONTENT_GUESS.detect {|f| f.in? names }
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
171
|
def dependent_collections
|
176
172
|
reflections.values.select do |refl|
|
177
173
|
refl.macro == :has_many && refl.options[:dependent]
|
@@ -203,6 +199,9 @@ module Hobo
|
|
203
199
|
belongs_to_without_test_methods(name, options, &block)
|
204
200
|
refl = reflections[name]
|
205
201
|
if options[:polymorphic]
|
202
|
+
# TODO: the class lookup in _is? below is incomplete; a polymorphic association to an STI base class
|
203
|
+
# will fail to match an object of a derived type
|
204
|
+
# (ie X belongs_to Y (polymorphic), Z is a subclass of Y; @x.y_is?(some_z) will never pass)
|
206
205
|
class_eval %{
|
207
206
|
def #{name}_is?(target)
|
208
207
|
target.class.name == self.#{refl.options[:foreign_type]} && target.id == self.#{refl.primary_key_name}
|
@@ -214,7 +213,7 @@ module Hobo
|
|
214
213
|
else
|
215
214
|
class_eval %{
|
216
215
|
def #{name}_is?(target)
|
217
|
-
target.class
|
216
|
+
target.class <= ::#{refl.klass.name} && target.id == self.#{refl.primary_key_name}
|
218
217
|
end
|
219
218
|
def #{name}_changed?
|
220
219
|
#{refl.primary_key_name}_changed?
|
@@ -345,7 +344,7 @@ module Hobo
|
|
345
344
|
|
346
345
|
refl.klass.reflections.values.find do |r|
|
347
346
|
r.macro.in?(reverse_macros) &&
|
348
|
-
r.klass
|
347
|
+
r.klass >= self &&
|
349
348
|
!r.options[:conditions] &&
|
350
349
|
r.primary_key_name == refl.primary_key_name
|
351
350
|
end
|
@@ -434,14 +433,18 @@ module Hobo
|
|
434
433
|
attr = self.class.creator_attribute
|
435
434
|
return unless attr
|
436
435
|
|
437
|
-
|
438
|
-
|
436
|
+
attr_type = self.class.creator_type
|
437
|
+
|
438
|
+
# Is creator an instance, a string field or an association?
|
439
|
+
if !attr_type.is_a?(Class)
|
440
|
+
# attr_type is an instance - typically AssociationReflection for a polymorphic association
|
441
|
+
self.send("#{attr}=", user)
|
442
|
+
elsif self.class.attr_type(attr)._? <= String
|
439
443
|
# Set it to the name of the current user
|
440
444
|
self.send("#{attr}=", user.to_s) unless user.guest?
|
441
445
|
else
|
442
446
|
# Assume user is a user object, but don't set if we've got a type mismatch
|
443
|
-
|
444
|
-
self.send("#{attr}=", user) if t.nil? || user.is_a?(t)
|
447
|
+
self.send("#{attr}=", user) if attr_type.nil? || user.is_a?(attr_type)
|
445
448
|
end
|
446
449
|
end
|
447
450
|
|
@@ -383,7 +383,7 @@ module Hobo
|
|
383
383
|
(!destroyed && object_url(@this)) ||
|
384
384
|
|
385
385
|
# Then the show page of the 'owning' object if there is one
|
386
|
-
|
386
|
+
object_url(owning_object) ||
|
387
387
|
|
388
388
|
# Last try - the index page for this model
|
389
389
|
object_url(@this.class) ||
|
@@ -391,6 +391,11 @@ module Hobo
|
|
391
391
|
# Give up
|
392
392
|
home_page
|
393
393
|
end
|
394
|
+
|
395
|
+
def owning_object
|
396
|
+
method = @this.class.dependent_on.detect {|m| !@this.send(m).nil?}
|
397
|
+
method ? @this.send(method) : nil
|
398
|
+
end
|
394
399
|
|
395
400
|
|
396
401
|
def url_for_page_path
|
@@ -457,9 +462,9 @@ module Hobo
|
|
457
462
|
|
458
463
|
def find_owner_and_association(owner_association)
|
459
464
|
refl = model.reflections[owner_association]
|
460
|
-
|
461
|
-
id = params["#{
|
462
|
-
owner = klass.find(id)
|
465
|
+
owner_name = refl.macro == :has_many ? owner_association.to_s.singularize : owner_association
|
466
|
+
id = params["#{owner_name}_id"]
|
467
|
+
owner = refl.klass.find(id)
|
463
468
|
instance_variable_set("@#{owner_association}", owner)
|
464
469
|
[owner, owner.send(model.reverse_reflection(owner_association).name)]
|
465
470
|
end
|
@@ -486,7 +491,7 @@ module Hobo
|
|
486
491
|
|
487
492
|
def hobo_show(*args, &b)
|
488
493
|
options = args.extract_options!
|
489
|
-
self.this ||= find_instance(options)
|
494
|
+
self.this ||= args.first || find_instance(options)
|
490
495
|
response_block(&b)
|
491
496
|
end
|
492
497
|
|
@@ -544,7 +549,7 @@ module Hobo
|
|
544
549
|
|
545
550
|
|
546
551
|
def create_response(new_action, options={}, &b)
|
547
|
-
flash_notice "The #{@this.class.name.titleize.downcase} was created successfully" if valid?
|
552
|
+
flash_notice (ht( :"#{@this.class.name.pluralize.underscore}.messages.create.success", :default=>["The #{@this.class.name.titleize.downcase} was created successfully"])) if valid?
|
548
553
|
|
549
554
|
response_block(&b) or
|
550
555
|
if valid?
|
@@ -554,10 +559,12 @@ module Hobo
|
|
554
559
|
end
|
555
560
|
else
|
556
561
|
respond_to do |wants|
|
562
|
+
# errors is used by the translation helper, ht, below.
|
563
|
+
errors = this.errors.full_messages.join("\n")
|
557
564
|
wants.html { re_render_form(new_action) }
|
558
565
|
wants.js { render(:status => 500,
|
559
|
-
:text => ("Couldn't create the #{this.class.name.titleize.downcase}.\n"
|
560
|
-
|
566
|
+
:text => ht( :"#{this.class.name.pluralize.underscore}.messages.create.error", :errors=>errors,:default=>["Couldn't create the #{this.class.name.titleize.downcase}.\n #{errors}"])
|
567
|
+
)}
|
561
568
|
end
|
562
569
|
end
|
563
570
|
end
|
@@ -567,7 +574,7 @@ module Hobo
|
|
567
574
|
options = args.extract_options!
|
568
575
|
|
569
576
|
self.this ||= args.first || find_instance
|
570
|
-
changes = options[:attributes] || attribute_parameters or raise RuntimeError, "No update specified in params"
|
577
|
+
changes = options[:attributes] || attribute_parameters or raise RuntimeError, ht(:"hobo.messages.update.no_attribute_error", :default=>["No update specified in params"])
|
571
578
|
this.user_update_attributes(current_user, changes)
|
572
579
|
|
573
580
|
# Ensure current_user isn't out of date
|
@@ -579,7 +586,8 @@ module Hobo
|
|
579
586
|
|
580
587
|
|
581
588
|
def update_response(in_place_edit_field=nil, options={}, &b)
|
582
|
-
|
589
|
+
|
590
|
+
flash_notice (ht(:"#{@this.class.name.pluralize.underscore}.messages.update.success", :default=>["Changes to the #{@this.class.name.titleize.downcase} were saved"])) if valid?
|
583
591
|
|
584
592
|
response_block(&b) or
|
585
593
|
if valid?
|
@@ -602,10 +610,12 @@ module Hobo
|
|
602
610
|
end
|
603
611
|
else
|
604
612
|
respond_to do |wants|
|
613
|
+
# errors is used by the translation helper, ht, below.
|
614
|
+
errors = @this.errors.full_messages.join("\n")
|
605
615
|
wants.html { re_render_form(:edit) }
|
606
616
|
wants.js { render(:status => 500,
|
607
|
-
:text => ("There was a problem with that change.\n"
|
608
|
-
|
617
|
+
:text => ht(:"#{@this.class.name.pluralize.underscore}.messages.update.error",:default=>["There was a problem with that change.\n#{errors}"], :errors=>errors)
|
618
|
+
) }
|
609
619
|
end
|
610
620
|
end
|
611
621
|
end
|
@@ -615,7 +625,7 @@ module Hobo
|
|
615
625
|
options = args.extract_options!
|
616
626
|
self.this ||= args.first || find_instance
|
617
627
|
this.user_destroy(current_user)
|
618
|
-
flash_notice "The #{model.name.titleize.downcase} was deleted"
|
628
|
+
flash_notice ht( :"#{model.name.pluralize.underscore}.messages.destroy.success", :default=>["The #{model.name.titleize.downcase} was deleted"])
|
619
629
|
destroy_response(options, &b)
|
620
630
|
end
|
621
631
|
|
@@ -652,10 +662,12 @@ module Hobo
|
|
652
662
|
else
|
653
663
|
this.exempt_from_edit_checks = true
|
654
664
|
respond_to do |wants|
|
665
|
+
# errors is used by the translation helper, ht, below.
|
666
|
+
errors = this.errors.full_messages.join("\n")
|
655
667
|
wants.html { re_render_form(name) }
|
656
668
|
wants.js { render(:status => 500,
|
657
|
-
:text => ("Couldn't do creator #{name}.\n"
|
658
|
-
|
669
|
+
:text => ht(:"#{@this.class.name.pluralize.underscore}.messages.creator.error", :default=>["Couldn't do creator #{name}.\n#{errors}"], :name=>name, :errors=>errors)
|
670
|
+
)}
|
659
671
|
end
|
660
672
|
end
|
661
673
|
end
|
@@ -663,12 +675,13 @@ module Hobo
|
|
663
675
|
|
664
676
|
def prepare_transition(name, options)
|
665
677
|
key = options.delete(:key) || params[:key]
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
678
|
+
|
679
|
+
# we don't use find_instance here, as it fails for key_holder transitions on objects that Guest can't view
|
680
|
+
record = model.find(params[:id])
|
681
|
+
record.exempt_from_edit_checks = true
|
682
|
+
record.lifecycle.provided_key = key
|
683
|
+
self.this = record
|
684
|
+
|
672
685
|
this.lifecycle.find_transition(name, current_user) or raise Hobo::PermissionDeniedError
|
673
686
|
end
|
674
687
|
|
@@ -691,10 +704,12 @@ module Hobo
|
|
691
704
|
end
|
692
705
|
else
|
693
706
|
respond_to do |wants|
|
707
|
+
# errors is used by the translation helper, ht, below.
|
708
|
+
errors = this.errors.full_messages.join("\n")
|
694
709
|
wants.html { re_render_form(name) }
|
695
710
|
wants.js { render(:status => 500,
|
696
|
-
:text => ("Couldn't do transition #{name}.\n"
|
697
|
-
|
711
|
+
:text => ht(:"#{@this.class.name.pluralize.underscore}.messages.transition.error", :default=>["Couldn't do transition #{name}.\n#{errors}"], :name=>name, :errors=>errors)
|
712
|
+
)}
|
698
713
|
end
|
699
714
|
end
|
700
715
|
end
|
@@ -748,28 +763,17 @@ module Hobo
|
|
748
763
|
if render_tag("permission-denied-page", { }, :status => 403)
|
749
764
|
# job done
|
750
765
|
else
|
751
|
-
render :text => "Permission Denied", :status => 403
|
766
|
+
render :text => ht(:"hobo.messages.permission_denied", :default=>["Permission Denied"]), :status => 403
|
752
767
|
end
|
753
768
|
end
|
754
769
|
wants.js do
|
755
|
-
render :text => "Permission Denied", :status => 403
|
770
|
+
render :text => ht(:"hobo.messages.permission_denied", :default=>["Permission Denied"]), :status => 403
|
756
771
|
end
|
757
772
|
end
|
758
773
|
end
|
759
774
|
end
|
760
775
|
|
761
776
|
|
762
|
-
def not_found(error)
|
763
|
-
if "not_found_response".in?(self.class.superclass.instance_methods)
|
764
|
-
super
|
765
|
-
elsif render_tag("not-found-page", {}, :status => 404)
|
766
|
-
# cool
|
767
|
-
else
|
768
|
-
render(:text => "The page you requested cannot be found.", :status => 404)
|
769
|
-
end
|
770
|
-
end
|
771
|
-
|
772
|
-
|
773
777
|
def this
|
774
778
|
@this ||= (instance_variable_get("@#{model.name.underscore}") ||
|
775
779
|
instance_variable_get("@#{model.name.underscore.pluralize}"))
|
@@ -794,7 +798,8 @@ module Hobo
|
|
794
798
|
def render_with_hobo_model(*args, &block)
|
795
799
|
options = args.extract_options!
|
796
800
|
self.this = options[:object] if options[:object]
|
797
|
-
this
|
801
|
+
# this causes more problems than it solves, and Tom says it's not supposed to be here
|
802
|
+
# this.user_view(current_user) if this && this.respond_to?(:user_view)
|
798
803
|
render_without_hobo_model(*args + [options], &block)
|
799
804
|
end
|
800
805
|
|