hobo 0.9.0 → 0.9.100
Sign up to get free protection for your applications and to get access to all the features.
- 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.rb
CHANGED
@@ -16,7 +16,7 @@ class HoboError < RuntimeError; end
|
|
16
16
|
|
17
17
|
module Hobo
|
18
18
|
|
19
|
-
VERSION = "0.9.
|
19
|
+
VERSION = "0.9.100"
|
20
20
|
|
21
21
|
class PermissionDeniedError < RuntimeError; end
|
22
22
|
|
@@ -105,13 +105,13 @@ module Hobo
|
|
105
105
|
Array(path)
|
106
106
|
end
|
107
107
|
|
108
|
-
|
108
|
+
parent = nil
|
109
109
|
path.each do |field|
|
110
110
|
return nil if object.nil?
|
111
111
|
parent = object
|
112
112
|
object = get_field(parent, field)
|
113
113
|
end
|
114
|
-
[parent,
|
114
|
+
[parent, path.last, object]
|
115
115
|
end
|
116
116
|
|
117
117
|
|
@@ -42,8 +42,15 @@ module Hobo
|
|
42
42
|
|
43
43
|
record = yield id
|
44
44
|
record.attributes = hash
|
45
|
-
|
46
|
-
|
45
|
+
if owner.new_record? && record.new_record?
|
46
|
+
# work around
|
47
|
+
# https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/3510-has_many-build-does-not-set-reverse-reflection
|
48
|
+
# https://hobo.lighthouseapp.com/projects/8324/tickets/447-validation-problems-with-has_many-accessible-true
|
49
|
+
method = "#{owner.class.reverse_reflection(association_name).name}=".to_sym
|
50
|
+
record.send(method, owner) if record.respond_to? method
|
51
|
+
else
|
52
|
+
owner.include_in_save(association_name, record)
|
53
|
+
end
|
47
54
|
else
|
48
55
|
# It's already a record
|
49
56
|
record = record_hash_or_string
|
@@ -87,7 +94,7 @@ module Hobo
|
|
87
94
|
|
88
95
|
classy_module(AccessibleAssociations) do
|
89
96
|
|
90
|
-
include IncludeInSave
|
97
|
+
include Hobo::IncludeInSave
|
91
98
|
|
92
99
|
# --- has_many mass assignment support --- #
|
93
100
|
|
data/lib/hobo/controller.rb
CHANGED
@@ -14,6 +14,7 @@ module Hobo
|
|
14
14
|
|
15
15
|
def included_in_class(klass)
|
16
16
|
klass.extend(ClassMethods)
|
17
|
+
klass.send(:include, Hobo::Translations)
|
17
18
|
klass.class_eval do
|
18
19
|
before_filter :login_from_cookie
|
19
20
|
alias_method_chain :redirect_to, :object_url
|
@@ -157,7 +158,7 @@ module Hobo
|
|
157
158
|
end
|
158
159
|
|
159
160
|
def not_found(error)
|
160
|
-
if
|
161
|
+
if self.class.superclass.method_defined?("not_found_response")
|
161
162
|
super
|
162
163
|
elsif render_tag("not-found-page", {}, :status => 404)
|
163
164
|
# cool
|
data/lib/hobo/dryml.rb
CHANGED
@@ -24,9 +24,9 @@ module Hobo
|
|
24
24
|
CORE_TAGLIB = { :src => "core", :plugin => "hobo" }
|
25
25
|
|
26
26
|
DEFAULT_IMPORTS = (if defined?(ApplicationHelper)
|
27
|
-
[Hobo::HoboHelper, ApplicationHelper]
|
27
|
+
[Hobo::HoboHelper, Hobo::Translations, ApplicationHelper]
|
28
28
|
else
|
29
|
-
[Hobo::HoboHelper]
|
29
|
+
[Hobo::HoboHelper, Hobo::Translations]
|
30
30
|
end)
|
31
31
|
|
32
32
|
@renderer_classes = {}
|
@@ -38,6 +38,11 @@ module Hobo
|
|
38
38
|
|
39
39
|
def enable
|
40
40
|
ActionView::Template.register_template_handler("dryml", Hobo::Dryml::TemplateHandler)
|
41
|
+
if ActionView::Template.respond_to? :exempt_from_layout
|
42
|
+
ActionView::Template.exempt_from_layout('dryml')
|
43
|
+
elsif
|
44
|
+
ActionView::Base.exempt_from_layout('dryml')
|
45
|
+
end
|
41
46
|
DrymlGenerator.enable
|
42
47
|
end
|
43
48
|
|
@@ -61,7 +61,7 @@ module Hobo::Dryml
|
|
61
61
|
def erb_process(erb_src, method_def=false)
|
62
62
|
trim_mode = ActionView::TemplateHandlers::ERB.erb_trim_mode
|
63
63
|
erb = ERB.new(erb_src, nil, trim_mode, "output_buffer")
|
64
|
-
src = erb.src
|
64
|
+
src = erb.src.split(';')[1..-2].join(';')
|
65
65
|
|
66
66
|
if method_def
|
67
67
|
src.sub /^\s*def.*?\(.*?\)/, '\0 __in_erb_template=true; '
|
@@ -118,9 +118,6 @@ module Hobo::Dryml
|
|
118
118
|
template_dir = File.dirname(template_path)
|
119
119
|
options = options.merge(:template_dir => template_dir)
|
120
120
|
|
121
|
-
# Pass on the current bundle, if there is one, to the sub-taglib
|
122
|
-
options[:bundle] = template.bundle.name unless template.bundle.nil? || options[:bundle] || options[:plugin]
|
123
|
-
|
124
121
|
taglib = Taglib.get(options)
|
125
122
|
taglib.import_into(@environment, options[:as])
|
126
123
|
end
|
@@ -75,6 +75,9 @@ module Hobo
|
|
75
75
|
|
76
76
|
|
77
77
|
def run
|
78
|
+
# Ensure all view hints loaded before running
|
79
|
+
Hobo::Model.all_models.*.view_hints
|
80
|
+
|
78
81
|
[nil, *Hobo.subsites].each { |s| run_for_subsite(s) }
|
79
82
|
end
|
80
83
|
|
@@ -156,11 +159,10 @@ module Hobo
|
|
156
159
|
|
157
160
|
|
158
161
|
def model_name(*options)
|
159
|
-
name = model.view_hints.model_name
|
160
|
-
name = name.pluralize if :plural.in?(options)
|
161
|
-
name = name.titleize if :title.in?(options)
|
162
|
+
name = :plural.in?(options) ? model.view_hints.model_name_plural : model.view_hints.model_name
|
162
163
|
name = name.titleize.downcase if :lowercase.in?(options)
|
163
164
|
name = name.underscore.gsub('_', '-').gsub('/', '--') if :dashed.in?(options)
|
165
|
+
name = name.camelize if :camel.in?(options)
|
164
166
|
name
|
165
167
|
end
|
166
168
|
|
data/lib/hobo/dryml/taglib.rb
CHANGED
@@ -14,8 +14,7 @@ module Hobo
|
|
14
14
|
if taglib
|
15
15
|
taglib.reload
|
16
16
|
else
|
17
|
-
|
18
|
-
taglib = Taglib.new(src_file, bundle)
|
17
|
+
taglib = Taglib.new(src_file)
|
19
18
|
@cache[src_file] = taglib
|
20
19
|
end
|
21
20
|
taglib
|
@@ -33,9 +32,6 @@ module Hobo
|
|
33
32
|
"#{HOBO_ROOT}/taglibs"
|
34
33
|
elsif plugin
|
35
34
|
"#{RAILS_ROOT}/vendor/plugins/#{plugin}/taglibs"
|
36
|
-
elsif (bundle_name = options[:bundle])
|
37
|
-
bundle = Bundle.bundles[bundle_name] or raise ArgumentError, "No such bundle: #{options[:bundle]}"
|
38
|
-
"#{RAILS_ROOT}/vendor/plugins/#{bundle.plugin}/taglibs"
|
39
35
|
elsif options[:src] =~ /\//
|
40
36
|
"#{RAILS_ROOT}/app/views"
|
41
37
|
elsif options[:template_dir] =~ /^#{HOBO_ROOT}/
|
@@ -52,9 +48,8 @@ module Hobo
|
|
52
48
|
|
53
49
|
end
|
54
50
|
|
55
|
-
def initialize(src_file
|
51
|
+
def initialize(src_file)
|
56
52
|
@src_file = src_file
|
57
|
-
@bundle = bundle
|
58
53
|
load
|
59
54
|
end
|
60
55
|
|
@@ -92,7 +87,7 @@ module Hobo
|
|
92
87
|
end
|
93
88
|
|
94
89
|
end
|
95
|
-
template = Template.new(File.read(@src_file), @module, @src_file
|
90
|
+
template = Template.new(File.read(@src_file), @module, @src_file)
|
96
91
|
template.compile([], [])
|
97
92
|
@last_load_time = File.mtime(@src_file)
|
98
93
|
end
|
data/lib/hobo/dryml/template.rb
CHANGED
@@ -33,11 +33,10 @@ module Hobo::Dryml
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def initialize(src, environment, template_path
|
36
|
+
def initialize(src, environment, template_path)
|
37
37
|
@src = src
|
38
38
|
@environment = environment # a class or a module
|
39
39
|
@template_path = template_path.sub(%r(^#{Regexp.escape(RAILS_ROOT)}/), "")
|
40
|
-
@bundle = bundle
|
41
40
|
|
42
41
|
@builder = Template.build_cache[@template_path] || DRYMLBuilder.new(self)
|
43
42
|
@builder.set_environment(environment)
|
@@ -45,7 +44,7 @@ module Hobo::Dryml
|
|
45
44
|
@last_element = nil
|
46
45
|
end
|
47
46
|
|
48
|
-
attr_reader :tags, :template_path
|
47
|
+
attr_reader :tags, :template_path
|
49
48
|
|
50
49
|
def compile(local_names=[], auto_taglibs=[])
|
51
50
|
now = Time.now
|
@@ -178,7 +177,7 @@ module Hobo::Dryml
|
|
178
177
|
require_toplevel(el)
|
179
178
|
require_attribute(el, "as", /^#{DRYML_NAME}$/, true)
|
180
179
|
options = {}
|
181
|
-
%w(src module plugin
|
180
|
+
%w(src module plugin as).each do |attr|
|
182
181
|
options[attr.to_sym] = el.attributes[attr] if el.attributes[attr]
|
183
182
|
end
|
184
183
|
@builder.add_build_instruction(:include, options)
|
@@ -261,8 +260,6 @@ module Hobo::Dryml
|
|
261
260
|
klass = HoboFields.to_class(for_type) or
|
262
261
|
dryml_exception("No such type in polymorphic tag definition: '#{for_type}'", el)
|
263
262
|
klass.name
|
264
|
-
elsif for_type =~ /^_.*_$/
|
265
|
-
rename_class(for_type)
|
266
263
|
else
|
267
264
|
for_type
|
268
265
|
end.underscore.gsub('/', '__')
|
@@ -994,10 +991,6 @@ module Hobo::Dryml
|
|
994
991
|
"#{name}_#{@gensym_counter}"
|
995
992
|
end
|
996
993
|
|
997
|
-
def rename_class(name)
|
998
|
-
@bundle && name.starts_with?("_") ? @bundle.send(name) : name
|
999
|
-
end
|
1000
|
-
|
1001
994
|
def include_source_metadata
|
1002
995
|
# disabled for now -- we're still getting broken rendering with this feature on
|
1003
996
|
return false
|
@@ -17,7 +17,8 @@ module Hobo::Dryml
|
|
17
17
|
|
18
18
|
def render_for_rails22(template, view, local_assigns)
|
19
19
|
renderer = Hobo::Dryml.page_renderer_for_template(view, local_assigns.keys, template)
|
20
|
-
this =
|
20
|
+
this = view.controller.send(:dryml_context) || local_assigns[:this]
|
21
|
+
@view._?.instance_variable_set("@this", this)
|
21
22
|
s = renderer.render_page(this, local_assigns)
|
22
23
|
|
23
24
|
# Important to strip whitespace, or the browser hangs around for ages (FF2)
|
@@ -177,7 +178,7 @@ module ActionView
|
|
177
178
|
end
|
178
179
|
end
|
179
180
|
|
180
|
-
if
|
181
|
+
if method_defined? "find_template"
|
181
182
|
# only rails 2.3 has this function
|
182
183
|
alias_method_chain :find_template, :dryml
|
183
184
|
end
|
data/lib/hobo/hobo_helper.rb
CHANGED
@@ -143,7 +143,7 @@ module Hobo
|
|
143
143
|
|
144
144
|
def type_id(type=nil)
|
145
145
|
type ||= (this.is_a?(Class) && this) || this_type || this.class
|
146
|
-
HoboFields.to_name(type) || type.name.underscore.gsub("/", "__")
|
146
|
+
HoboFields.to_name(type) || type.name.to_s.underscore.gsub("/", "__")
|
147
147
|
end
|
148
148
|
|
149
149
|
|
@@ -485,15 +485,13 @@ module Hobo
|
|
485
485
|
# --- ViewHint Helpers --- #
|
486
486
|
|
487
487
|
def this_field_name
|
488
|
-
|
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)
|
488
|
+
this_parent.class.try.view_hints.try.field_name(this_field) || this_field
|
491
489
|
end
|
492
490
|
|
493
491
|
def this_field_help
|
494
|
-
key = "#{this_parent.class.try.name.
|
492
|
+
key = "#{this_parent.class.try.name.tableize}.hints.#{this_field.to_s}"
|
495
493
|
default = this_parent.class.try.view_hints.try.field_help[this_field.to_sym] || ""
|
496
|
-
|
494
|
+
Hobo::Translations.ht(key, :default=>default)
|
497
495
|
end
|
498
496
|
|
499
497
|
|
@@ -510,83 +508,7 @@ module Hobo
|
|
510
508
|
logger.debug("DRYML THIS = #{this.typed_id rescue this.inspect}")
|
511
509
|
logger.debug("###################\n")
|
512
510
|
args.first unless args.empty?
|
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
|
511
|
+
end
|
590
512
|
|
591
513
|
end
|
592
514
|
|
data/lib/hobo/lifecycles.rb
CHANGED
@@ -30,13 +30,17 @@ module Hobo
|
|
30
30
|
module_eval "class ::#{name}::Lifecycle < Hobo::Lifecycles::Lifecycle; end"
|
31
31
|
lifecycle = self::Lifecycle
|
32
32
|
lifecycle.init(self, options)
|
33
|
+
|
34
|
+
module_eval "class ::#{name}::LifecycleStateField < HoboFields::LifecycleState; end"
|
35
|
+
state_field_class = self::LifecycleStateField
|
36
|
+
state_field_class.table_name = name.tableize
|
33
37
|
end
|
34
38
|
|
35
|
-
dsl = DeclarationDSL.new(lifecycle)
|
39
|
+
dsl = Hobo::Lifecycles::DeclarationDSL.new(lifecycle)
|
36
40
|
dsl.instance_eval(&block)
|
37
41
|
|
38
42
|
default = lifecycle.default_state ? { :default => lifecycle.default_state.name.to_s } : {}
|
39
|
-
declare_field(options[:state_field],
|
43
|
+
declare_field(options[:state_field], state_field_class, default)
|
40
44
|
unless options[:index] == false
|
41
45
|
index_options = { :name => options[:index] } unless options[:index] == true
|
42
46
|
index(options[:state_field], index_options || {})
|
@@ -82,15 +86,15 @@ module Hobo
|
|
82
86
|
|
83
87
|
|
84
88
|
def lifecycle
|
85
|
-
@lifecycle ||= if
|
89
|
+
@lifecycle ||= if self.class.const_defined?(:Lifecycle)
|
86
90
|
self.class::Lifecycle.new(self)
|
87
91
|
else
|
88
92
|
# search through superclasses
|
89
93
|
current = self.class.superclass
|
90
|
-
until (
|
94
|
+
until (current.const_defined?(:Lifecycle) || current.nil? || !current.respond_to?(:lifecycle)) do
|
91
95
|
current = current.superclass
|
92
96
|
end
|
93
|
-
current
|
97
|
+
current::Lifecycle.new(self) if current.const_defined?(:Lifecycle)
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
@@ -15,11 +15,8 @@ module Hobo
|
|
15
15
|
return true if available_to.nil? # available_to not specified (these steps are not published)
|
16
16
|
acting_user_is?(available_to, record)
|
17
17
|
end
|
18
|
-
|
19
|
-
|
20
|
-
def acting_user_is?(who, record)
|
21
|
-
user = record.acting_user
|
22
18
|
|
19
|
+
def publishable_by(user, who, record)
|
23
20
|
case who
|
24
21
|
when :all
|
25
22
|
true
|
@@ -32,7 +29,7 @@ module Hobo
|
|
32
29
|
|
33
30
|
when Array
|
34
31
|
# recursively apply the same test to every item in the array
|
35
|
-
who.detect { |w|
|
32
|
+
who.detect { |w| publishable_by(user, w, record) }
|
36
33
|
|
37
34
|
else
|
38
35
|
refl = record.class.reflections[who]
|
@@ -53,6 +50,9 @@ module Hobo
|
|
53
50
|
end
|
54
51
|
end
|
55
52
|
|
53
|
+
def acting_user_is?(who, record)
|
54
|
+
publishable_by(record.acting_user, who, record)
|
55
|
+
end
|
56
56
|
|
57
57
|
def run_hook(record, hook, *args)
|
58
58
|
case hook
|
@@ -159,7 +159,7 @@ module Hobo
|
|
159
159
|
state ? state.transitions_out : []
|
160
160
|
end
|
161
161
|
|
162
|
-
|
162
|
+
# see also publishable_transitions_for
|
163
163
|
def available_transitions_for(user, name=nil)
|
164
164
|
name = name.to_sym if name
|
165
165
|
matches = available_transitions
|
@@ -169,6 +169,10 @@ module Hobo
|
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
+
def publishable_transitions_for(user)
|
173
|
+
available_transitions_for(user).select {|t| t.publishable_by(user, t.available_to, record)}
|
174
|
+
end
|
175
|
+
|
172
176
|
|
173
177
|
def become(state_name, validate=true)
|
174
178
|
state_name = state_name.to_sym
|
@@ -180,7 +184,7 @@ module Hobo
|
|
180
184
|
else
|
181
185
|
s = self.class.states[state_name]
|
182
186
|
raise ArgumentError, "No such state '#{state_name}' for #{record.class.name}" unless s
|
183
|
-
|
187
|
+
|
184
188
|
if record.save(validate)
|
185
189
|
s.activate! record
|
186
190
|
self.active_step = nil # That's the end of this step
|