hobo 0.9.0 → 0.9.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.txt +132 -0
- data/Rakefile +18 -22
- data/bin/hobo +14 -13
- data/doctest/scopes.rdoctest +1 -0
- data/dryml_generators/rapid/forms.dryml.erb +1 -1
- data/dryml_generators/rapid/pages.dryml.erb +24 -24
- data/lib/hobo.rb +3 -3
- data/lib/hobo/accessible_associations.rb +10 -3
- data/lib/hobo/controller.rb +2 -1
- data/lib/hobo/dryml.rb +7 -2
- data/lib/hobo/dryml/dryml_builder.rb +1 -4
- data/lib/hobo/dryml/dryml_generator.rb +5 -3
- data/lib/hobo/dryml/taglib.rb +3 -8
- data/lib/hobo/dryml/template.rb +3 -10
- data/lib/hobo/dryml/template_handler.rb +3 -2
- data/lib/hobo/hobo_helper.rb +5 -83
- data/lib/hobo/lifecycles.rb +9 -5
- data/lib/hobo/lifecycles/actions.rb +5 -5
- data/lib/hobo/lifecycles/lifecycle.rb +6 -2
- data/lib/hobo/model.rb +14 -36
- data/lib/hobo/model_controller.rb +28 -15
- data/lib/hobo/model_router.rb +1 -1
- data/lib/hobo/permissions.rb +55 -5
- data/lib/hobo/permissions/associations.rb +13 -5
- data/lib/hobo/rapid_helper.rb +4 -10
- data/lib/hobo/scopes/automatic_scopes.rb +9 -1
- data/lib/hobo/translations.rb +88 -0
- data/lib/hobo/user.rb +1 -2
- data/lib/hobo/user_controller.rb +31 -9
- data/lib/hobo/view_hints.rb +38 -6
- data/rails_generators/hobo_model/templates/hints.rb +4 -1
- data/rails_generators/hobo_model_controller/hobo_model_controller_generator.rb +1 -1
- data/rails_generators/hobo_rapid/hobo_rapid_generator.rb +2 -1
- data/rails_generators/hobo_rapid/templates/hobo-rapid.js +9 -0
- data/rails_generators/hobo_rapid/templates/ie7-recalc.js +166 -2
- data/rails_generators/hobo_user_model/templates/model.rb +1 -3
- data/taglibs/rapid.dryml +2 -1
- data/taglibs/rapid_core.dryml +7 -5
- data/taglibs/rapid_editing.dryml +14 -10
- data/taglibs/rapid_forms.dryml +7 -5
- data/taglibs/rapid_generics.dryml +1 -1
- data/taglibs/rapid_lifecycles.dryml +3 -2
- data/taglibs/rapid_pages.dryml +1 -1
- data/taglibs/rapid_support.dryml +1 -1
- data/tasks/hobo_tasks.rake +10 -0
- metadata +7 -7
- data/lib/hobo/bundle.rb +0 -330
data/lib/hobo/model.rb
CHANGED
@@ -24,6 +24,7 @@ module Hobo
|
|
24
24
|
include Hobo::Lifecycles::ModelExtensions
|
25
25
|
include Hobo::FindFor
|
26
26
|
include Hobo::AccessibleAssociations
|
27
|
+
include Hobo::Translations
|
27
28
|
end
|
28
29
|
|
29
30
|
class << base
|
@@ -35,14 +36,14 @@ module Hobo
|
|
35
36
|
|
36
37
|
def inherited(klass)
|
37
38
|
super
|
38
|
-
fields do
|
39
|
+
fields(false) do
|
39
40
|
Hobo.register_model(klass)
|
40
41
|
field(klass.inheritance_column, :string)
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
|
-
base.fields # force hobofields to load
|
46
|
+
base.fields(false) # force hobofields to load
|
46
47
|
|
47
48
|
included_in_class_callbacks(base)
|
48
49
|
end
|
@@ -121,7 +122,7 @@ module Hobo
|
|
121
122
|
ActiveRecord::Base.class_eval do
|
122
123
|
def self.hobo_model
|
123
124
|
include Hobo::Model
|
124
|
-
fields # force hobofields to load
|
125
|
+
fields(false) # force hobofields to load
|
125
126
|
end
|
126
127
|
def self.hobo_user_model
|
127
128
|
include Hobo::Model
|
@@ -141,12 +142,12 @@ module Hobo
|
|
141
142
|
# TODO: should this be an inheriting_cattr_accessor as well? Probably.
|
142
143
|
attr_accessor :creator_attribute
|
143
144
|
inheriting_cattr_accessor :name_attribute => Proc.new { |c|
|
144
|
-
names = c.columns.*.name + c.public_instance_methods
|
145
|
+
names = c.columns.*.name + c.public_instance_methods.*.to_s
|
145
146
|
NAME_FIELD_GUESS.detect {|f| f.in? names }
|
146
147
|
}
|
147
148
|
|
148
149
|
inheriting_cattr_accessor :primary_content_attribute => Proc.new { |c|
|
149
|
-
names = c.columns.*.name + c.public_instance_methods
|
150
|
+
names = c.columns.*.name + c.public_instance_methods.*.to_s
|
150
151
|
PRIMARY_CONTENT_GUESS.detect {|f| f.in? names }
|
151
152
|
}
|
152
153
|
|
@@ -168,25 +169,6 @@ module Hobo
|
|
168
169
|
end
|
169
170
|
|
170
171
|
|
171
|
-
def dependent_collections
|
172
|
-
reflections.values.select do |refl|
|
173
|
-
refl.macro == :has_many && refl.options[:dependent]
|
174
|
-
end.*.name
|
175
|
-
end
|
176
|
-
|
177
|
-
|
178
|
-
def dependent_on
|
179
|
-
reflections.values.select do |refl|
|
180
|
-
refl.macro == :belongs_to && (rev = reverse_reflection(refl.name) and rev.options[:dependent])
|
181
|
-
end.*.name
|
182
|
-
end
|
183
|
-
|
184
|
-
|
185
|
-
def default_dependent_on
|
186
|
-
dependent_on.first
|
187
|
-
end
|
188
|
-
|
189
|
-
|
190
172
|
private
|
191
173
|
|
192
174
|
|
@@ -273,14 +255,18 @@ module Hobo
|
|
273
255
|
|
274
256
|
def find(*args, &b)
|
275
257
|
options = args.extract_options!
|
276
|
-
if options[:order] == :default
|
258
|
+
if options[:order] == :default || (options[:order].blank? && !scoped?(:find, :order))
|
259
|
+
# TODO: decide if this is correct. AR is no help, as passing :order to a scoped proxy
|
260
|
+
# MERGES the order, but nesting two scopes with :order completely ignores the
|
261
|
+
# first scope's order.
|
262
|
+
# Are we more like default_scope, or more like passing :order => model.default_order?
|
277
263
|
options = if default_order.blank?
|
278
264
|
options.except :order
|
279
265
|
else
|
280
266
|
options.merge(:order => if default_order[/(\.|\(|,| )/]
|
281
267
|
default_order
|
282
268
|
else
|
283
|
-
"#{
|
269
|
+
"#{quoted_table_name}.#{default_order}"
|
284
270
|
end)
|
285
271
|
end
|
286
272
|
end
|
@@ -297,11 +283,6 @@ module Hobo
|
|
297
283
|
end
|
298
284
|
|
299
285
|
|
300
|
-
def all(options={})
|
301
|
-
find(:all, options.reverse_merge(:order => :default))
|
302
|
-
end
|
303
|
-
|
304
|
-
|
305
286
|
def creator_type
|
306
287
|
attr_type(creator_attribute)
|
307
288
|
end
|
@@ -329,6 +310,7 @@ module Hobo
|
|
329
310
|
refl.klass.reflections.values.find do |r|
|
330
311
|
r.macro == :has_many &&
|
331
312
|
!r.options[:conditions] &&
|
313
|
+
!r.options[:scope] &&
|
332
314
|
r.through_reflection == other_to_join &&
|
333
315
|
r.source_reflection == join_to_self
|
334
316
|
end
|
@@ -346,6 +328,7 @@ module Hobo
|
|
346
328
|
r.macro.in?(reverse_macros) &&
|
347
329
|
r.klass >= self &&
|
348
330
|
!r.options[:conditions] &&
|
331
|
+
!r.options[:scope] &&
|
349
332
|
r.primary_key_name == refl.primary_key_name
|
350
333
|
end
|
351
334
|
end
|
@@ -410,11 +393,6 @@ module Hobo
|
|
410
393
|
end
|
411
394
|
|
412
395
|
|
413
|
-
def dependent_on
|
414
|
-
self.class.dependent_on.map { |assoc| send(assoc) }
|
415
|
-
end
|
416
|
-
|
417
|
-
|
418
396
|
def attributes_with_hobo_type_conversion=(attributes, guard_protected_attributes=true)
|
419
397
|
converted = attributes.map_hash { |k, v| convert_type_for_mass_assignment(self.class.attr_type(k), v) }
|
420
398
|
send(:attributes_without_hobo_type_conversion=, converted, guard_protected_attributes)
|
@@ -166,7 +166,7 @@ module Hobo
|
|
166
166
|
|
167
167
|
|
168
168
|
def def_auto_action(name, &block)
|
169
|
-
define_method name, &block if
|
169
|
+
define_method name, &block if !method_defined?(name) && include_action?(name)
|
170
170
|
end
|
171
171
|
|
172
172
|
|
@@ -259,7 +259,7 @@ module Hobo
|
|
259
259
|
|
260
260
|
def auto_actions_for(owner, actions)
|
261
261
|
name = model.reflections[owner].macro == :has_many ? owner.to_s.singularize : owner
|
262
|
-
|
262
|
+
|
263
263
|
owner_actions[owner] ||= []
|
264
264
|
Array(actions).each do |action|
|
265
265
|
case action
|
@@ -296,7 +296,7 @@ module Hobo
|
|
296
296
|
|
297
297
|
|
298
298
|
def available_auto_write_actions
|
299
|
-
if "position_column"
|
299
|
+
if model.method_defined?("position_column")
|
300
300
|
WRITE_ONLY_ACTIONS + [:reorder]
|
301
301
|
else
|
302
302
|
WRITE_ONLY_ACTIONS
|
@@ -393,7 +393,7 @@ module Hobo
|
|
393
393
|
end
|
394
394
|
|
395
395
|
def owning_object
|
396
|
-
method = @this.class.
|
396
|
+
method = @this.class.view_hints.parent
|
397
397
|
method ? @this.send(method) : nil
|
398
398
|
end
|
399
399
|
|
@@ -461,14 +461,17 @@ module Hobo
|
|
461
461
|
|
462
462
|
|
463
463
|
def find_owner_and_association(owner_association)
|
464
|
+
owner_name = name_of_auto_action_for(owner_association)
|
464
465
|
refl = model.reflections[owner_association]
|
465
|
-
owner_name = refl.macro == :has_many ? owner_association.to_s.singularize : owner_association
|
466
466
|
id = params["#{owner_name}_id"]
|
467
467
|
owner = refl.klass.find(id)
|
468
468
|
instance_variable_set("@#{owner_association}", owner)
|
469
469
|
[owner, owner.send(model.reverse_reflection(owner_association).name)]
|
470
470
|
end
|
471
471
|
|
472
|
+
def name_of_auto_action_for(owner_association)
|
473
|
+
model.reflections[owner_association].macro == :has_many ? owner_association.to_s.singularize : owner_association
|
474
|
+
end
|
472
475
|
|
473
476
|
# --- Action implementations --- #
|
474
477
|
|
@@ -511,18 +514,28 @@ module Hobo
|
|
511
514
|
|
512
515
|
def hobo_create(*args, &b)
|
513
516
|
options = args.extract_options!
|
514
|
-
|
515
|
-
this
|
517
|
+
attributes = options[:attributes] || attribute_parameters || {}
|
518
|
+
if self.this ||= args.first
|
519
|
+
this.user_update_attributes(current_user, attributes)
|
520
|
+
else
|
521
|
+
self.this = new_for_create(attributes)
|
522
|
+
this.save
|
523
|
+
end
|
516
524
|
create_response(:new, options, &b)
|
517
525
|
end
|
518
526
|
|
519
527
|
|
520
|
-
def hobo_create_for(
|
528
|
+
def hobo_create_for(owner_association, *args, &b)
|
521
529
|
options = args.extract_options!
|
522
|
-
owner, association = find_owner_and_association(
|
523
|
-
|
524
|
-
this
|
525
|
-
|
530
|
+
owner, association = find_owner_and_association(owner_association)
|
531
|
+
attributes = options[:attributes] || attribute_parameters || {}
|
532
|
+
if self.this ||= args.first
|
533
|
+
this.user_update_attributes(current_user, attributes)
|
534
|
+
else
|
535
|
+
self.this = association.new(attributes)
|
536
|
+
this.save
|
537
|
+
end
|
538
|
+
create_response(:"new_for_#{name_of_auto_action_for(owner_association)}", options, &b)
|
526
539
|
end
|
527
540
|
|
528
541
|
|
@@ -531,10 +544,10 @@ module Hobo
|
|
531
544
|
end
|
532
545
|
|
533
546
|
|
534
|
-
def new_for_create
|
547
|
+
def new_for_create(attributes = {})
|
535
548
|
type_param = subtype_for_create
|
536
549
|
create_model = type_param ? type_param.constantize : model
|
537
|
-
create_model.user_new(current_user)
|
550
|
+
create_model.user_new(current_user, attributes)
|
538
551
|
end
|
539
552
|
|
540
553
|
|
@@ -755,7 +768,7 @@ module Hobo
|
|
755
768
|
self.this = true # Otherwise this gets sent user_view
|
756
769
|
logger.info "Hobo: Permission Denied!"
|
757
770
|
@permission_error = error
|
758
|
-
if
|
771
|
+
if self.class.superclass.method_defined?("permission_denied")
|
759
772
|
super
|
760
773
|
else
|
761
774
|
respond_to do |wants|
|
data/lib/hobo/model_router.rb
CHANGED
@@ -248,7 +248,7 @@ module Hobo
|
|
248
248
|
|
249
249
|
|
250
250
|
def named_route(name, route, options={})
|
251
|
-
if controller.
|
251
|
+
if controller.public_method_defined?(options[:action])
|
252
252
|
options.reverse_merge!(:controller => route_with_subsite(plural))
|
253
253
|
name = name_with_subsite(name)
|
254
254
|
route = route_with_subsite(route)
|
data/lib/hobo/permissions.rb
CHANGED
@@ -13,7 +13,12 @@ module Hobo
|
|
13
13
|
alias_method_chain :create, :hobo_permission_check
|
14
14
|
alias_method_chain :update, :hobo_permission_check
|
15
15
|
alias_method_chain :destroy, :hobo_permission_check
|
16
|
-
|
16
|
+
class << self
|
17
|
+
alias_method_chain :has_many, :hobo_permission_check
|
18
|
+
alias_method_chain :has_one, :hobo_permission_check
|
19
|
+
alias_method_chain :belongs_to, :hobo_permission_check
|
20
|
+
end
|
21
|
+
|
17
22
|
attr_accessor :acting_user, :origin, :origin_attribute
|
18
23
|
|
19
24
|
bool_attr_accessor :exempt_from_edit_checks
|
@@ -25,9 +30,9 @@ module Hobo
|
|
25
30
|
def self.find_aliased_name(klass, method_name)
|
26
31
|
# The method +method_name+ will have been aliased. We jump through some hoops to figure out
|
27
32
|
# what it's new name is
|
28
|
-
method_name = method_name.
|
33
|
+
method_name = method_name.to_sym
|
29
34
|
method = klass.instance_method method_name
|
30
|
-
methods = klass.private_instance_methods + klass.instance_methods
|
35
|
+
methods = (klass.private_instance_methods + klass.instance_methods).*.to_sym
|
31
36
|
new_name = methods.select {|m| klass.instance_method(m) == method }.find { |m| m != method_name }
|
32
37
|
end
|
33
38
|
|
@@ -75,7 +80,52 @@ module Hobo
|
|
75
80
|
def viewable_by?(user, attribute=nil)
|
76
81
|
new.viewable_by?(user, attribute)
|
77
82
|
end
|
83
|
+
|
84
|
+
# ensure active_user gets passed down to :dependent => destroy
|
85
|
+
# associations (Ticket #528)
|
78
86
|
|
87
|
+
def has_many_with_hobo_permission_check(association_id, options = {}, &extension)
|
88
|
+
has_many_without_hobo_permission_check(association_id, options, &extension)
|
89
|
+
reflection = reflections[association_id]
|
90
|
+
if reflection.options[:dependent]==:destroy
|
91
|
+
#overriding dynamic method created in ActiveRecord::Associations#configure_dependency_for_has_many
|
92
|
+
method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym
|
93
|
+
define_method(method_name) do
|
94
|
+
send(reflection.name).each { |r| r.is_a?(Hobo::Model) ? r.user_destroy(acting_user) : r.destroy }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def has_one_with_hobo_permission_check(association_id, options = {}, &extension)
|
100
|
+
has_one_without_hobo_permission_check(association_id, options, &extension)
|
101
|
+
reflection = reflections[association_id]
|
102
|
+
if reflection.options[:dependent]==:destroy
|
103
|
+
#overriding dynamic method created in ActiveRecord::Associations#configure_dependency_for_has_many
|
104
|
+
method_name = "has_one_dependent_destroy_for_#{reflection.name}".to_sym
|
105
|
+
define_method(method_name) do
|
106
|
+
association = send(reflection.name)
|
107
|
+
unless association.nil?
|
108
|
+
association.is_a?(Hobo::Model) ? association.user_destroy(active_user) : association.destroy
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def belongs_to_with_hobo_permission_check(association_id, options = {}, &extension)
|
115
|
+
belongs_to_without_hobo_permission_check(association_id, options, &extension)
|
116
|
+
reflection = reflections[association_id]
|
117
|
+
if reflection.options[:dependent]==:destroy
|
118
|
+
#overriding dynamic method created in ActiveRecord::Associations#configure_dependency_for_has_many
|
119
|
+
method_name = "belongs_to_dependent_destroy_for_#{reflection.name}".to_sym
|
120
|
+
define_method(method_name) do
|
121
|
+
association = send(reflection.name)
|
122
|
+
unless association.nil?
|
123
|
+
association.is_a?(Hobo::Model) ? association.user_destroy(active_user) : association.destroy
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
79
129
|
end
|
80
130
|
|
81
131
|
|
@@ -123,8 +173,8 @@ module Hobo
|
|
123
173
|
result
|
124
174
|
end
|
125
175
|
|
126
|
-
def user_save(user)
|
127
|
-
with_acting_user(user) { save }
|
176
|
+
def user_save(user, validate = true)
|
177
|
+
with_acting_user(user) { save(validate) }
|
128
178
|
end
|
129
179
|
|
130
180
|
def user_save!(user)
|
@@ -45,12 +45,20 @@ module Hobo
|
|
45
45
|
end
|
46
46
|
|
47
47
|
|
48
|
-
def insert_record(record)
|
48
|
+
def insert_record(record, force = false, validate = true)
|
49
49
|
set_belongs_to_association_for(record)
|
50
50
|
if (user = acting_user) && record.is_a?(Hobo::Model)
|
51
|
-
|
51
|
+
if force
|
52
|
+
record.user_save!(user)
|
53
|
+
else
|
54
|
+
record.user_save(user, validate)
|
55
|
+
end
|
52
56
|
else
|
53
|
-
|
57
|
+
if force
|
58
|
+
record.save!
|
59
|
+
else
|
60
|
+
record.save(validate)
|
61
|
+
end
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
@@ -99,13 +107,13 @@ module Hobo
|
|
99
107
|
end
|
100
108
|
|
101
109
|
|
102
|
-
def insert_record(record, force=true)
|
110
|
+
def insert_record(record, force=true, validate=true)
|
103
111
|
user = acting_user if record.is_a?(Hobo::Model)
|
104
112
|
if record.new_record?
|
105
113
|
if force
|
106
114
|
user ? record.user_save!(user) : record.save!
|
107
115
|
else
|
108
|
-
return false unless (user ? record.user_save(user) : record.save)
|
116
|
+
return false unless (user ? record.user_save(user, validate) : record.save(validate))
|
109
117
|
end
|
110
118
|
end
|
111
119
|
klass = @reflection.through_reflection.klass
|
data/lib/hobo/rapid_helper.rb
CHANGED
@@ -92,13 +92,16 @@ module Hobo::RapidHelper
|
|
92
92
|
|
93
93
|
|
94
94
|
|
95
|
-
def in_place_editor(attributes)
|
95
|
+
def in_place_editor(attributes, this=nil)
|
96
96
|
blank_message = attributes.delete(:blank_message) || "(click to edit)"
|
97
97
|
|
98
98
|
attributes = add_classes(attributes, "in-place-edit", model_id_class(this_parent, this_field))
|
99
99
|
attributes.update(:hobo_blank_message => blank_message,
|
100
100
|
:if_blank => blank_message,
|
101
101
|
:no_wrapper => false)
|
102
|
+
|
103
|
+
edit_text = this._?.to_s
|
104
|
+
attributes.update(:hobo_edit_text => edit_text) unless edit_text.nil?
|
102
105
|
|
103
106
|
update = attributes.delete(:update)
|
104
107
|
attributes[:hobo_update] = update if update
|
@@ -122,15 +125,6 @@ module Hobo::RapidHelper
|
|
122
125
|
end
|
123
126
|
|
124
127
|
|
125
|
-
def primary_collection_name(object=this)
|
126
|
-
dependent_collection_names = object.class.reflections.values.select do |refl|
|
127
|
-
refl.macro == :has_many && refl.options[:dependent]
|
128
|
-
end.*.name
|
129
|
-
|
130
|
-
(dependent_collection_names - through_collection_names(object)).first
|
131
|
-
end
|
132
|
-
|
133
|
-
|
134
128
|
def non_through_collections(object=this)
|
135
129
|
names = object.class.reflections.values.select do |refl|
|
136
130
|
refl.macro == :has_many
|
@@ -347,7 +347,15 @@ module Hobo
|
|
347
347
|
|
348
348
|
|
349
349
|
def def_scope(options={}, &block)
|
350
|
-
|
350
|
+
_name = name.to_sym
|
351
|
+
@klass.named_scope(_name, block || options)
|
352
|
+
# this is tricky; ordinarily, we'd worry about subclasses that haven't yet been loaded.
|
353
|
+
# HOWEVER, they will pick up the scope setting via read_inheritable_attribute when they do
|
354
|
+
# load, so only the currently existing subclasses need to be fixed up.
|
355
|
+
_scope = @klass.scopes[_name]
|
356
|
+
@klass.send(:subclasses).each do |k|
|
357
|
+
k.scopes[_name] = _scope
|
358
|
+
end
|
351
359
|
end
|
352
360
|
|
353
361
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Hobo
|
2
|
+
|
3
|
+
module Translations
|
4
|
+
|
5
|
+
# --- Translation Helper --- #
|
6
|
+
#
|
7
|
+
# Uses RoR native I18n.translate.
|
8
|
+
#
|
9
|
+
# Adds some conventions for easier hobo translation.
|
10
|
+
# 1. Assumes the first part of the key to be a model name (e.g.: users.index.title -> user)
|
11
|
+
# 2. Tries to translate the model by lookup for: (e.g.: user-> activerecord.models.user)
|
12
|
+
# 3. Adds a default fallback to the beginning of the fallback chain
|
13
|
+
# by replacing the first part of the key with "hobo" and using the translated model name
|
14
|
+
# as additional attribute. This allows us to have default translations
|
15
|
+
# (e.g.: hobo.index.title: "{{model}} Index")
|
16
|
+
#
|
17
|
+
# Is also used as a tag in the dryml-view files. The syntax is:
|
18
|
+
# <ht key="my.app">My Application</ht>
|
19
|
+
# --> Will lookup the "my.app"-key for your locale and replaces the "My Application" content
|
20
|
+
# if found.
|
21
|
+
#
|
22
|
+
# <ht key="my" app="Program">My Application</ht>
|
23
|
+
# --> Will look up both the "my"- and "app"-key for your locale, and replaces the
|
24
|
+
# "My Application" with the "my"-key contents (interpolated using the "app"-key.
|
25
|
+
# sample.en.yml-file:
|
26
|
+
# "no":
|
27
|
+
# my: "Mitt {{app}}"
|
28
|
+
# The output should be: Mitt Program
|
29
|
+
#
|
30
|
+
# Otherwise with features as the ht method, step 1, 2 and 3 above.
|
31
|
+
def self.ht(key, options={})
|
32
|
+
|
33
|
+
# Check if called as a tag, i.e. like this <ht></ht>
|
34
|
+
if (key.class == Hash)
|
35
|
+
if key.has_key?(:default) && !key[:default].blank?
|
36
|
+
Rails.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."
|
37
|
+
end
|
38
|
+
defaults = options[:default];
|
39
|
+
# Swap key and options, remove options[:key]
|
40
|
+
options = key
|
41
|
+
key = options.delete(:key) # returns value for options[:key] as well as deleting it
|
42
|
+
# Set options[:default] to complete the tag-argument-conversion process.
|
43
|
+
options[:default] = (defaults.class == Proc) ? [defaults.call(options)] : (options[:default].blank? ? [] : [options[:default]])
|
44
|
+
else
|
45
|
+
# Not called as a tag. Prepare options[:default].
|
46
|
+
if options[:default].nil?
|
47
|
+
options[:default]=[]
|
48
|
+
elsif options[:default].class != Array
|
49
|
+
options[:default] = [options[:default]]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# assume the first part of the key to be the model
|
54
|
+
keys = key.to_s.split(".")
|
55
|
+
if keys.length > 1
|
56
|
+
model = keys.shift()
|
57
|
+
subkey = keys.join(".")
|
58
|
+
else
|
59
|
+
subkey = key
|
60
|
+
end
|
61
|
+
|
62
|
+
# add :"hobo.#{key}" as the first fallback
|
63
|
+
options[:default].unshift("hobo.#{subkey}".to_sym)
|
64
|
+
|
65
|
+
# translate the model
|
66
|
+
unless model.blank?
|
67
|
+
translated_model = I18n.translate( "activerecord.models.#{model.singularize.underscore}", :default=>model).titleize
|
68
|
+
options[:model] = translated_model
|
69
|
+
end
|
70
|
+
|
71
|
+
key_prefix = "<span class='translation-key'>#{key}</span>" if defined?(HOBO_SHOW_LOCALE_KEYS) && HOBO_SHOW_LOCALE_KEYS
|
72
|
+
|
73
|
+
Rails.logger.info "..translate(#{key}, #{options.inspect}) to #{I18n.locale}" if defined?(HOBO_VERBOSE_TRANSLATIONS)
|
74
|
+
|
75
|
+
I18n.translate(key.to_sym, options)+(key_prefix ? key_prefix:"")
|
76
|
+
end
|
77
|
+
|
78
|
+
# if somebody includes us, give them ht as an instance method
|
79
|
+
def self.included(base)
|
80
|
+
translation_class = self
|
81
|
+
base.class_eval do
|
82
|
+
define_method :ht do |*args|
|
83
|
+
translation_class.ht(*args)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|