hobo 0.7.5 → 0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/{hobo_files/plugin/CHANGES.txt → CHANGES.txt} +391 -0
- data/Manifest +146 -0
- data/{hobo_files/plugin/README → README} +0 -0
- data/bin/hobo +13 -26
- data/dryml_generators/rapid/cards.dryml.erb +55 -0
- data/dryml_generators/rapid/forms.dryml.erb +43 -0
- data/dryml_generators/rapid/pages.dryml.erb +284 -0
- data/hobo.gemspec +168 -0
- data/init.rb +9 -0
- data/lib/action_view_extensions/helpers/tag_helper.rb +7 -0
- data/lib/active_record/association_collection.rb +54 -0
- data/{hobo_files/plugin/lib → lib}/active_record/association_proxy.rb +12 -4
- data/{hobo_files/plugin/lib → lib}/active_record/association_reflection.rb +7 -1
- data/{hobo_files/plugin/lib → lib}/extensions/test_case.rb +17 -17
- data/{hobo_files/plugin/lib → lib}/hobo.rb +193 -100
- data/{hobo_files/plugin/lib → lib}/hobo/authentication_support.rb +8 -8
- data/{hobo_files/plugin/lib → lib}/hobo/bundle.rb +90 -89
- data/{hobo_files/plugin/lib → lib}/hobo/composite_model.rb +21 -21
- data/{hobo_files/plugin/lib → lib}/hobo/controller.rb +38 -25
- data/{hobo_files/plugin/lib → lib}/hobo/dev_controller.rb +10 -6
- data/lib/hobo/dryml.rb +167 -0
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/dryml_builder.rb +28 -25
- data/lib/hobo/dryml/dryml_generator.rb +210 -0
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/dryml_support_controller.rb +1 -1
- data/lib/hobo/dryml/parser.rb +3 -0
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/parser/attribute.rb +6 -6
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/parser/base_parser.rb +16 -16
- data/lib/hobo/dryml/parser/document.rb +57 -0
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/parser/element.rb +7 -7
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/parser/elements.rb +9 -9
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/parser/source.rb +3 -3
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/parser/text.rb +3 -3
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/parser/tree_parser.rb +3 -3
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/part_context.rb +26 -26
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/scoped_variables.rb +15 -15
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/tag_parameters.rb +10 -10
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/taglib.rb +43 -37
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/template.rb +290 -208
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/template_environment.rb +173 -115
- data/{hobo_files/plugin/lib → lib}/hobo/dryml/template_handler.rb +19 -24
- data/lib/hobo/find_for.rb +95 -0
- data/{hobo_files/plugin/lib → lib}/hobo/generator.rb +2 -1
- data/{hobo_files/plugin/lib → lib}/hobo/guest.rb +12 -4
- data/{hobo_files/plugin/lib → lib}/hobo/hobo_helper.rb +146 -117
- data/lib/hobo/include_in_save.rb +43 -0
- data/lib/hobo/lifecycles.rb +94 -0
- data/lib/hobo/lifecycles/actions.rb +73 -0
- data/lib/hobo/lifecycles/creator.rb +76 -0
- data/lib/hobo/lifecycles/lifecycle.rb +205 -0
- data/lib/hobo/lifecycles/state.rb +23 -0
- data/lib/hobo/lifecycles/transition.rb +66 -0
- data/{hobo_files/plugin/lib → lib}/hobo/model.rb +306 -217
- data/{hobo_files/plugin/lib → lib}/hobo/model_controller.rb +342 -213
- data/{hobo_files/plugin/lib → lib}/hobo/model_router.rb +151 -120
- data/{hobo_files/plugin/lib → lib}/hobo/model_support.rb +9 -9
- data/{hobo_files/plugin/lib → lib}/hobo/rapid_helper.rb +30 -23
- data/{hobo_files/plugin/lib → lib}/hobo/scopes.rb +22 -68
- data/{hobo_files/plugin/lib → lib}/hobo/scopes/apply_scopes.rb +5 -5
- data/lib/hobo/scopes/association_proxy_extensions.rb +47 -0
- data/{hobo_files/plugin/lib → lib}/hobo/scopes/automatic_scopes.rb +104 -79
- data/lib/hobo/scopes/named_scope_extensions.rb +27 -0
- data/{hobo_files/plugin/lib → lib}/hobo/static_tags +1 -11
- data/{hobo_files/plugin/lib → lib}/hobo/undefined.rb +1 -1
- data/{hobo_files/plugin/lib → lib}/hobo/undefined_access_error.rb +0 -0
- data/{hobo_files/plugin/lib → lib}/hobo/user.rb +27 -25
- data/{hobo_files/plugin/lib → lib}/hobo/user_controller.rb +80 -34
- data/{hobo_files/plugin/generators → rails_generators}/hobo/hobo_generator.rb +7 -7
- data/rails_generators/hobo/templates/application.css +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo/templates/application.dryml +0 -2
- data/{hobo_files/plugin/generators → rails_generators}/hobo/templates/dryml-support.js +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo/templates/guest.rb +0 -0
- data/rails_generators/hobo/templates/initializer.rb +9 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_front_controller/USAGE +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_front_controller/hobo_front_controller_generator.rb +1 -3
- data/{hobo_files/plugin/generators → rails_generators}/hobo_front_controller/templates/controller.rb +1 -1
- data/{hobo_files/plugin/generators → rails_generators}/hobo_front_controller/templates/functional_test.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_front_controller/templates/helper.rb +0 -0
- data/rails_generators/hobo_front_controller/templates/index.dryml +25 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model/USAGE +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model/hobo_model_generator.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model/templates/fixtures.yml +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model/templates/model.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model/templates/unit_test.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_controller/USAGE +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_controller/hobo_model_controller_generator.rb +0 -7
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_controller/templates/controller.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_controller/templates/functional_test.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_controller/templates/helper.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_resource/hobo_model_resource_generator.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_resource/templates/controller.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_resource/templates/functional_test.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_model_resource/templates/helper.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/hobo_rapid_generator.rb +21 -11
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/IE7.js +1 -1
- data/rails_generators/hobo_rapid/templates/blank.gif +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/hobo-rapid.css +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/hobo-rapid.js +175 -104
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/lowpro.js +0 -0
- data/rails_generators/hobo_rapid/templates/nicEditorIcons.gif +0 -0
- data/rails_generators/hobo_rapid/templates/nicedit.js +91 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/reset.css +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/themes/clean/public/images/fieldbg.gif +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/themes/clean/public/images/pencil.png +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/themes/clean/public/images/small_close.png +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/themes/clean/public/images/spinner.gif +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +80 -71
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +6 -1
- data/{hobo_files/plugin/generators → rails_generators}/hobo_rapid/templates/themes/clean/views/clean.dryml +4 -4
- data/rails_generators/hobo_subsite/hobo_subsite_generator.rb +73 -0
- data/rails_generators/hobo_subsite/templates/application.dryml +1 -0
- data/rails_generators/hobo_subsite/templates/controller.rb +5 -0
- data/rails_generators/hobo_subsite/templates/site_taglib.dryml +13 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_controller/USAGE +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_controller/hobo_user_controller_generator.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_controller/templates/controller.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_controller/templates/functional_test.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_controller/templates/helper.rb +0 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_model/USAGE +0 -0
- data/rails_generators/hobo_user_model/hobo_user_model_generator.rb +30 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_model/templates/fixtures.yml +0 -0
- data/rails_generators/hobo_user_model/templates/forgot_password.erb +10 -0
- data/rails_generators/hobo_user_model/templates/mailer.rb +14 -0
- data/rails_generators/hobo_user_model/templates/model.rb +55 -0
- data/{hobo_files/plugin/generators → rails_generators}/hobo_user_model/templates/unit_test.rb +0 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/{hobo_files/plugin/taglibs → taglibs}/core.dryml +6 -7
- data/{hobo_files/plugin/taglibs → taglibs}/rapid.dryml +36 -67
- data/{hobo_files/plugin/taglibs → taglibs}/rapid_document_tags.dryml +7 -24
- data/{hobo_files/plugin/taglibs → taglibs}/rapid_editing.dryml +51 -50
- data/{hobo_files/plugin/taglibs → taglibs}/rapid_forms.dryml +62 -56
- data/taglibs/rapid_generics.dryml +33 -0
- data/taglibs/rapid_lifecycles.dryml +43 -0
- data/{hobo_files/plugin/taglibs → taglibs}/rapid_navigation.dryml +23 -23
- data/taglibs/rapid_pages.dryml +183 -0
- data/{hobo_files/plugin/taglibs → taglibs}/rapid_plus.dryml +30 -5
- data/{hobo_files/plugin/taglibs → taglibs}/rapid_support.dryml +3 -4
- data/taglibs/rapid_user_pages.dryml +179 -0
- data/{hobo_files/plugin/tasks → tasks}/environments.rake +0 -0
- data/{hobo_files/plugin/tasks → tasks}/fix_dryml.rake +0 -0
- data/{hobo_files/plugin/tasks → tasks}/generate_tag_reference.rb +21 -22
- data/tasks/hobo_tasks.rake +32 -0
- data/test/test_generator_helper.rb +29 -0
- data/test/test_helper.rb +1 -0
- data/test/test_hobo_model_controller_generator.rb +56 -0
- data/{hobo_files/plugin/uninstall.rb → uninstall.rb} +0 -0
- metadata +240 -225
- data/README.txt +0 -18
- data/hobo_files/plugin/LICENSE.txt +0 -22
- data/hobo_files/plugin/Rakefile +0 -96
- data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +0 -24
- data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +0 -19
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/banner.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-bodytop.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-corner-01.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-corner-02.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-corner-03.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-corner-04.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-shadow-bottom.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-shadow-left.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-shadow-right.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg-shadow-top.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header-blue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header-dblue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header-green.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header-purple.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header-red.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/logo.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/plus.png +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/spinner.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt-list-img-dblue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt-list-img-green.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt-list-img-purple.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt-list-img-red.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-corner-01.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-corner-02.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-corner-03.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-corner-04.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-shadow-bottom.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-shadow-left.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-shadow-right.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window-shadow-top.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +0 -400
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +0 -96
- data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +0 -25
- data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +0 -56
- data/hobo_files/plugin/init.rb +0 -101
- data/hobo_files/plugin/lib/action_view_extensions/base.rb +0 -15
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +0 -55
- data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +0 -20
- data/hobo_files/plugin/lib/hobo/dryml.rb +0 -165
- data/hobo_files/plugin/lib/hobo/dryml/parser/document.rb +0 -53
- data/hobo_files/plugin/lib/hobo/scopes/association_proxy_extensions.rb +0 -33
- data/hobo_files/plugin/lib/hobo/scopes/defined_scope_proxy_extender.rb +0 -90
- data/hobo_files/plugin/lib/hobo/scopes/scope_reflection.rb +0 -18
- data/hobo_files/plugin/lib/hobo/scopes/scoped_proxy.rb +0 -55
- data/hobo_files/plugin/taglib-docs/core.markdown +0 -165
- data/hobo_files/plugin/taglib-docs/rapid.markdown +0 -677
- data/hobo_files/plugin/taglib-docs/rapid_document_tags.markdown +0 -240
- data/hobo_files/plugin/taglib-docs/rapid_editing.markdown +0 -418
- data/hobo_files/plugin/taglib-docs/rapid_forms.markdown +0 -562
- data/hobo_files/plugin/taglib-docs/rapid_generics.markdown +0 -187
- data/hobo_files/plugin/taglib-docs/rapid_navigation.markdown +0 -214
- data/hobo_files/plugin/taglib-docs/rapid_pages.markdown +0 -530
- data/hobo_files/plugin/taglib-docs/rapid_plus.markdown +0 -65
- data/hobo_files/plugin/taglib-docs/rapid_support.markdown +0 -50
- data/hobo_files/plugin/taglib-docs/rapid_user_pages.markdown +0 -129
- data/hobo_files/plugin/taglibs/rapid_generics.dryml +0 -117
- data/hobo_files/plugin/taglibs/rapid_pages.dryml +0 -359
- data/hobo_files/plugin/taglibs/rapid_user_pages.dryml +0 -104
- data/hobo_files/plugin/tasks/dump_fixtures.rake +0 -70
- data/hobo_files/plugin/tasks/hobo_tasks.rake +0 -17
@@ -0,0 +1,23 @@
|
|
1
|
+
module Hobo
|
2
|
+
|
3
|
+
module Lifecycles
|
4
|
+
|
5
|
+
class State < Struct.new(:name, :on_enter, :transitions_in, :transitions_out)
|
6
|
+
|
7
|
+
include Actions
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
self.transitions_in = []
|
12
|
+
self.transitions_out = []
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def activate!(record)
|
17
|
+
fire_event(record, on_enter)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Hobo
|
2
|
+
|
3
|
+
module Lifecycles
|
4
|
+
|
5
|
+
class Transition < Struct.new(:lifecycle, :name, :who, :start_states, :end_state, :on_transition, :options)
|
6
|
+
|
7
|
+
include Actions
|
8
|
+
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
start_states.each do |from|
|
13
|
+
state = lifecycle.states[from.to_s]
|
14
|
+
raise ArgumentError, "No such state '#{from}' in #{'name'} transition (#{lifecycle.model.name})" unless state
|
15
|
+
state.transitions_out << self
|
16
|
+
end
|
17
|
+
unless end_state.to_s == "destroy"
|
18
|
+
state = lifecycle.states[end_state.to_s]
|
19
|
+
raise ArgumentError, "No such state '#{end_state}' in '#{name}' transition (#{lifecycle.model.name})" unless state
|
20
|
+
state.transitions_in << self
|
21
|
+
end
|
22
|
+
lifecycle.transitions << self
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def allowed?(record, user, attributes=nil)
|
27
|
+
prepare_and_check!(record, user, attributes) && true
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def extract_attributes(attributes)
|
32
|
+
update_attributes = options.fetch(:update, [])
|
33
|
+
attributes & update_attributes
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def run!(record, user, attributes)
|
38
|
+
if prepare_and_check!(record, user, attributes)
|
39
|
+
fire_event(record, on_transition)
|
40
|
+
record.become end_state
|
41
|
+
else
|
42
|
+
raise Hobo::Model::PermissionDeniedError
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def set_or_check_who_with_key!(record, user)
|
48
|
+
if who == :with_key
|
49
|
+
record.lifecycle.valid_key? or raise LifecycleKeyError
|
50
|
+
else
|
51
|
+
set_or_check_who_without_key!(record, user)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
alias_method_chain :set_or_check_who!, :key
|
55
|
+
|
56
|
+
|
57
|
+
def parameters
|
58
|
+
options[:update] || []
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -1,36 +1,44 @@
|
|
1
1
|
module Hobo
|
2
2
|
|
3
3
|
module Model
|
4
|
-
|
4
|
+
|
5
5
|
class PermissionDeniedError < RuntimeError; end
|
6
6
|
class NoNameError < RuntimeError; end
|
7
|
-
|
7
|
+
|
8
8
|
NAME_FIELD_GUESS = %w(name title)
|
9
9
|
PRIMARY_CONTENT_GUESS = %w(description body content profile)
|
10
10
|
SEARCH_COLUMNS_GUESS = %w(name title body content profile)
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
|
13
13
|
def self.included(base)
|
14
14
|
base.extend(ClassMethods)
|
15
|
-
|
15
|
+
|
16
16
|
included_in_class_callbacks(base)
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
register_model(base)
|
19
|
+
|
20
20
|
patch_will_paginate
|
21
21
|
|
22
22
|
base.class_eval do
|
23
23
|
inheriting_cattr_reader :default_order
|
24
24
|
alias_method_chain :attributes=, :hobo_type_conversion
|
25
|
+
|
26
|
+
attr_accessor :acting_user, :origin, :origin_attribute
|
27
|
+
|
28
|
+
bool_attr_accessor :exempt_from_edit_checks
|
29
|
+
|
30
|
+
include Hobo::Lifecycles::ModelExtensions
|
31
|
+
include Hobo::FindFor
|
32
|
+
include Hobo::IncludeInSave
|
25
33
|
end
|
26
|
-
|
34
|
+
|
27
35
|
class << base
|
28
|
-
alias_method_chain :
|
29
|
-
alias_method_chain :
|
30
|
-
alias_method_chain :
|
31
|
-
|
36
|
+
alias_method_chain :belongs_to, :creator_metadata
|
37
|
+
alias_method_chain :belongs_to, :target_is
|
38
|
+
alias_method_chain :attr_accessor, :creator_metadata
|
39
|
+
|
32
40
|
alias_method_chain :has_one, :new_method
|
33
|
-
|
41
|
+
|
34
42
|
def inherited(klass)
|
35
43
|
super
|
36
44
|
fields do
|
@@ -40,15 +48,16 @@ module Hobo
|
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
51
|
+
base.fields # force hobofields to load
|
43
52
|
end
|
44
|
-
|
53
|
+
|
45
54
|
def self.patch_will_paginate
|
46
55
|
if defined?(WillPaginate) && !WillPaginate::Collection.respond_to?(:member_class)
|
47
|
-
|
56
|
+
|
48
57
|
WillPaginate::Collection.class_eval do
|
49
58
|
attr_accessor :member_class, :origin, :origin_attribute
|
50
59
|
end
|
51
|
-
|
60
|
+
|
52
61
|
WillPaginate::Finder::ClassMethods.class_eval do
|
53
62
|
def paginate_with_hobo_metadata(*args, &block)
|
54
63
|
returning paginate_without_hobo_metadata(*args, &block) do |collection|
|
@@ -58,134 +67,200 @@ module Hobo
|
|
58
67
|
end
|
59
68
|
end
|
60
69
|
alias_method_chain :paginate, :hobo_metadata
|
61
|
-
|
70
|
+
|
62
71
|
end
|
63
|
-
|
72
|
+
|
64
73
|
end
|
65
74
|
end
|
66
|
-
|
67
75
|
|
76
|
+
|
77
|
+
def self.register_model(model)
|
78
|
+
@model_names ||= Set.new
|
79
|
+
@model_names << model.name
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def self.all_models
|
84
|
+
# Load every controller in app/controllers...
|
85
|
+
unless @models_loaded
|
86
|
+
Dir.entries("#{RAILS_ROOT}/app/models/").each do |f|
|
87
|
+
f =~ /^[a-zA-Z_][a-zA-Z0-9_]*\.rb$/ and f.sub(/.rb$/, '').camelize.constantize
|
88
|
+
end
|
89
|
+
@models_loaded = true
|
90
|
+
end
|
91
|
+
|
92
|
+
# ...but only return the ones that registered themselves
|
93
|
+
@model_names.*.constantize
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def self.enable
|
98
|
+
ActiveRecord::Base.class_eval do
|
99
|
+
def self.hobo_model
|
100
|
+
include Hobo::Model
|
101
|
+
fields # force hobofields to load
|
102
|
+
end
|
103
|
+
|
104
|
+
alias_method :has_hobo_method?, :respond_to_without_attributes?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
68
109
|
module ClassMethods
|
69
|
-
|
110
|
+
|
70
111
|
# include methods also shared by CompositeModel
|
71
112
|
#include ModelSupport::ClassMethods
|
72
|
-
|
113
|
+
|
73
114
|
attr_accessor :creator_attribute
|
74
115
|
attr_writer :name_attribute, :primary_content_attribute
|
75
|
-
|
116
|
+
|
76
117
|
def named(*args)
|
77
118
|
raise NoNameError, "Model #{name} has no name attribute" unless name_attribute
|
78
119
|
send("find_by_#{name_attribute}", *args)
|
79
120
|
end
|
80
|
-
|
81
|
-
|
121
|
+
|
122
|
+
|
82
123
|
def field_added(name, type, args, options)
|
83
124
|
self.name_attribute = name.to_sym if options.delete(:name)
|
84
125
|
self.primary_content_attribute = name.to_sym if options.delete(:primary_content)
|
85
126
|
self.creator_attribute = name.to_sym if options.delete(:creator)
|
86
127
|
validate = options.delete(:validate) {true}
|
87
|
-
|
128
|
+
|
88
129
|
#FIXME - this should be in Hobo::User
|
89
130
|
send(:login_attribute=, name.to_sym, validate) if options.delete(:login) && respond_to?(:login_attribute=)
|
90
131
|
end
|
91
|
-
|
92
|
-
|
132
|
+
|
133
|
+
|
93
134
|
def user_find(user, *args)
|
94
135
|
record = find(*args)
|
95
136
|
raise PermissionDeniedError unless Hobo.can_view?(user, record)
|
96
137
|
record
|
97
138
|
end
|
98
|
-
|
99
|
-
|
139
|
+
|
140
|
+
|
100
141
|
def user_new(user, attributes={})
|
101
|
-
record = new(attributes)
|
102
|
-
record.user_changes(user)
|
142
|
+
record = new(attributes) {|r| r.acting_user = user; yield if block_given? }
|
143
|
+
allowed = record.user_changes(user)
|
144
|
+
record.acting_user = nil
|
145
|
+
allowed && record
|
103
146
|
end
|
104
|
-
|
105
|
-
|
147
|
+
|
148
|
+
|
106
149
|
def user_new!(user, attributes={})
|
107
150
|
user_new(user, attributes) or raise PermissionDeniedError
|
108
151
|
end
|
109
|
-
|
110
|
-
|
152
|
+
|
153
|
+
|
111
154
|
def user_create(user, attributes={})
|
112
155
|
record = new(attributes)
|
113
156
|
record.user_save_changes(user)
|
114
157
|
record
|
115
158
|
end
|
116
|
-
|
117
|
-
|
159
|
+
|
160
|
+
|
118
161
|
def user_can_create?(user, attributes={})
|
119
162
|
record = new(attributes)
|
120
163
|
record.user_changes(user)
|
121
164
|
end
|
122
|
-
|
123
|
-
|
165
|
+
|
166
|
+
|
124
167
|
def user_update(user, id, attributes={})
|
125
168
|
find(id).user_save_changes(user, attributes)
|
126
169
|
end
|
127
|
-
|
128
|
-
|
170
|
+
|
171
|
+
|
129
172
|
def name_attribute
|
130
173
|
@name_attribute ||= begin
|
131
|
-
|
132
|
-
NAME_FIELD_GUESS.detect {|f| f.in?
|
174
|
+
names = columns.*.name + public_instance_methods
|
175
|
+
NAME_FIELD_GUESS.detect {|f| f.in? names }
|
133
176
|
end
|
134
177
|
end
|
135
|
-
|
178
|
+
|
136
179
|
|
137
180
|
def primary_content_attribute
|
138
181
|
@primary_content_attribute ||= begin
|
139
|
-
|
140
|
-
PRIMARY_CONTENT_GUESS.detect {|f| f.in?
|
182
|
+
names = columns.*.name + public_instance_methods
|
183
|
+
PRIMARY_CONTENT_GUESS.detect {|f| f.in? names }
|
141
184
|
end
|
142
185
|
end
|
143
|
-
|
186
|
+
|
144
187
|
def dependent_collections
|
145
|
-
reflections.values.select do |refl|
|
188
|
+
reflections.values.select do |refl|
|
146
189
|
refl.macro == :has_many && refl.options[:dependent]
|
147
190
|
end.*.name
|
148
191
|
end
|
149
|
-
|
150
|
-
|
192
|
+
|
193
|
+
|
151
194
|
def dependent_on
|
152
|
-
reflections.values.select do |refl|
|
195
|
+
reflections.values.select do |refl|
|
153
196
|
refl.macro == :belongs_to && (rev = reverse_reflection(refl.name) and rev.options[:dependent])
|
154
197
|
end.*.name
|
155
198
|
end
|
156
|
-
|
157
|
-
|
199
|
+
|
200
|
+
|
158
201
|
def default_dependent_on
|
159
202
|
dependent_on.first
|
160
203
|
end
|
161
|
-
|
162
|
-
|
204
|
+
|
205
|
+
|
163
206
|
private
|
164
|
-
|
165
|
-
|
207
|
+
|
208
|
+
|
166
209
|
def belongs_to_with_creator_metadata(name, options={}, &block)
|
167
210
|
self.creator_attribute = name.to_sym if options.delete(:creator)
|
168
211
|
belongs_to_without_creator_metadata(name, options, &block)
|
169
212
|
end
|
170
|
-
|
171
|
-
|
213
|
+
|
214
|
+
def belongs_to_with_target_is(name, options={}, &block)
|
215
|
+
belongs_to_without_target_is(name, options, &block)
|
216
|
+
refl = reflections[name]
|
217
|
+
if options[:polymorphic]
|
218
|
+
class_eval %{
|
219
|
+
def #{name}_is?(target)
|
220
|
+
target.id == self.#{refl.primary_key_name} && target.class.name == self.#{refl.options[:foreign_type]}
|
221
|
+
end
|
222
|
+
}
|
223
|
+
else
|
224
|
+
class_eval %{
|
225
|
+
def #{name}_is?(target)
|
226
|
+
target.id == self.#{refl.primary_key_name}
|
227
|
+
end
|
228
|
+
}
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
def attr_accessor_with_creator_metadata(*args)
|
234
|
+
options = args.extract_options!
|
235
|
+
if options.delete(:creator)
|
236
|
+
if args.length == 1
|
237
|
+
self.creator_attribute = args.first.to_sym
|
238
|
+
else
|
239
|
+
raise ArgumentError, "trying to set :creator => true on multiple attributes"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
args << options unless options.empty?
|
243
|
+
attr_accessor_without_creator_metadata(*args)
|
244
|
+
end
|
245
|
+
|
246
|
+
|
172
247
|
def has_one_with_new_method(name, options={}, &block)
|
173
248
|
has_one_without_new_method(name, options)
|
174
249
|
class_eval "def new_#{name}(attributes={}); build_#{name}(attributes, false); end"
|
175
250
|
end
|
176
|
-
|
177
|
-
|
251
|
+
|
252
|
+
|
178
253
|
def set_default_order(order)
|
179
254
|
@default_order = order
|
180
255
|
end
|
181
|
-
|
256
|
+
|
182
257
|
|
183
258
|
def never_show(*fields)
|
184
259
|
@hobo_never_show ||= []
|
185
260
|
@hobo_never_show.concat(fields.*.to_sym)
|
186
261
|
end
|
187
262
|
|
188
|
-
|
263
|
+
|
189
264
|
def set_search_columns(*columns)
|
190
265
|
class_eval %{
|
191
266
|
def self.search_columns
|
@@ -193,15 +268,15 @@ module Hobo
|
|
193
268
|
end
|
194
269
|
}
|
195
270
|
end
|
196
|
-
|
197
|
-
|
271
|
+
|
272
|
+
|
198
273
|
public
|
199
274
|
|
200
|
-
|
275
|
+
|
201
276
|
def never_show?(field)
|
202
277
|
(@hobo_never_show && field.to_sym.in?(@hobo_never_show)) || (superclass < Hobo::Model && superclass.never_show?(field))
|
203
278
|
end
|
204
|
-
|
279
|
+
|
205
280
|
|
206
281
|
def find(*args, &b)
|
207
282
|
options = args.extract_options!
|
@@ -216,29 +291,36 @@ module Hobo
|
|
216
291
|
result.member_class = self if result.is_a?(Array)
|
217
292
|
result
|
218
293
|
end
|
219
|
-
|
220
294
|
|
295
|
+
|
296
|
+
def find_by_sql(*args)
|
297
|
+
result = super
|
298
|
+
result.member_class = self # find_by_sql always returns array
|
299
|
+
result
|
300
|
+
end
|
301
|
+
|
302
|
+
|
221
303
|
def all(options={})
|
222
304
|
find(:all, options.reverse_merge(:order => :default))
|
223
305
|
end
|
224
|
-
|
225
|
-
|
306
|
+
|
307
|
+
|
226
308
|
def creator_type
|
227
|
-
|
309
|
+
attr_type(creator_attribute)
|
228
310
|
end
|
229
311
|
|
230
|
-
|
312
|
+
|
231
313
|
def search_columns
|
232
|
-
|
233
|
-
SEARCH_COLUMNS_GUESS.select{|c| c.in?(
|
314
|
+
column_names = columns.*.name
|
315
|
+
SEARCH_COLUMNS_GUESS.select{|c| c.in?(column_names) }
|
234
316
|
end
|
235
|
-
|
236
|
-
|
317
|
+
|
318
|
+
|
237
319
|
# FIXME: This should really be a method on AssociationReflection
|
238
320
|
def reverse_reflection(association_name)
|
239
|
-
refl = reflections[association_name]
|
321
|
+
refl = reflections[association_name.to_sym] or raise "No reverse reflection for #{name}.#{association_name}"
|
240
322
|
return nil if refl.options[:conditions] || refl.options[:polymorphic]
|
241
|
-
|
323
|
+
|
242
324
|
reverse_macro = if refl.macro == :has_many
|
243
325
|
:belongs_to
|
244
326
|
elsif refl.macro == :belongs_to
|
@@ -251,12 +333,12 @@ module Hobo
|
|
251
333
|
r.primary_key_name == refl.primary_key_name
|
252
334
|
end
|
253
335
|
end
|
254
|
-
|
255
|
-
|
336
|
+
|
337
|
+
|
256
338
|
def has_inheritance_column?
|
257
339
|
columns_hash.include?(inheritance_column)
|
258
340
|
end
|
259
|
-
|
341
|
+
|
260
342
|
|
261
343
|
def method_missing(name, *args, &block)
|
262
344
|
name = name.to_s
|
@@ -264,148 +346,155 @@ module Hobo
|
|
264
346
|
# FIXME: Do we need this now?
|
265
347
|
call_method_chain(name, args, &block)
|
266
348
|
elsif create_automatic_scope(name)
|
267
|
-
send(name, *args, &block)
|
349
|
+
send(name.to_sym, *args, &block)
|
268
350
|
else
|
269
351
|
super(name.to_sym, *args, &block)
|
270
352
|
end
|
271
353
|
end
|
272
354
|
|
273
|
-
|
355
|
+
|
356
|
+
def respond_to?(method)
|
357
|
+
super || create_automatic_scope(method)
|
358
|
+
end
|
359
|
+
|
360
|
+
|
274
361
|
def call_method_chain(chain, args, &block)
|
275
362
|
parts = chain.split(".")
|
276
363
|
s = parts[0..-2].inject(self) { |m, scope| m.send(scope) }
|
277
364
|
s.send(parts.last, *args)
|
278
365
|
end
|
279
|
-
|
280
|
-
|
366
|
+
|
367
|
+
|
281
368
|
def to_url_path
|
282
369
|
"#{name.underscore.pluralize}"
|
283
370
|
end
|
284
|
-
|
285
|
-
|
371
|
+
|
372
|
+
|
286
373
|
def typed_id
|
287
374
|
HoboFields.to_name(self) || name.underscore.gsub("/", "__")
|
288
375
|
end
|
289
|
-
|
290
|
-
|
291
|
-
def manage_join_records(association)
|
292
|
-
|
293
|
-
method = "manage_join_records_for_#{association}"
|
294
|
-
after_save method
|
295
|
-
class_eval %{
|
296
|
-
def #{method}
|
297
|
-
assigned = #{association}.dup
|
298
|
-
current = #{association}.reload
|
299
|
-
|
300
|
-
through = #{association}.proxy_reflection.through_reflection
|
301
|
-
source = #{association}.proxy_reflection.source_reflection
|
302
|
-
|
303
|
-
to_delete = current - assigned
|
304
|
-
to_add = assigned - current
|
305
|
-
through.klass.delete_all(["\#{through.primary_key_name} = ? and \#{source.primary_key_name} in (?)",
|
306
|
-
self.id, to_delete.*.id]) if to_delete.any?
|
307
|
-
to_add.each { |record| #{association} << record }
|
308
|
-
end
|
309
|
-
}
|
310
|
-
end
|
311
|
-
|
312
|
-
def has_many_with_join_record_management(name, options={}, &b)
|
313
|
-
manage = options.delete(:managed)
|
314
|
-
returning (has_many_without_join_record_management(name, options, &b)) do
|
315
|
-
manage_join_records(name) if manage
|
316
|
-
end
|
317
|
-
end
|
376
|
+
|
318
377
|
|
319
378
|
end # --- of ClassMethods --- #
|
320
|
-
|
321
|
-
|
379
|
+
|
380
|
+
|
322
381
|
include Scopes
|
323
|
-
|
324
|
-
|
382
|
+
|
325
383
|
def to_url_path
|
326
384
|
"#{self.class.to_url_path}/#{to_param}" unless new_record?
|
327
385
|
end
|
328
386
|
|
329
387
|
|
330
|
-
def
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
388
|
+
def to_param
|
389
|
+
name_attr = self.class.name_attribute
|
390
|
+
if name_attr
|
391
|
+
readable = send(name_attr).to_s.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/-+$/, '').gsub(/^-+$/, '').split('-')[0..5].join('-')
|
392
|
+
@to_param ||= "#{id}-#{readable}"
|
335
393
|
else
|
336
|
-
|
337
|
-
|
338
|
-
# with the changes so we clear them
|
339
|
-
clear_aggregation_cache
|
340
|
-
clear_association_cache
|
341
|
-
|
342
|
-
self.attributes = changes
|
343
|
-
|
344
|
-
Hobo.can_update?(user, original, self)
|
345
|
-
end
|
394
|
+
id
|
395
|
+
end
|
346
396
|
end
|
347
|
-
|
348
|
-
|
397
|
+
|
398
|
+
|
399
|
+
def with_acting_user(user)
|
400
|
+
old = acting_user
|
401
|
+
self.acting_user = user
|
402
|
+
result = yield
|
403
|
+
self.acting_user = old
|
404
|
+
result
|
405
|
+
end
|
406
|
+
|
407
|
+
|
408
|
+
def user_changes(user, changes={})
|
409
|
+
with_acting_user user do
|
410
|
+
if new_record?
|
411
|
+
self.attributes = changes
|
412
|
+
set_creator(user)
|
413
|
+
Hobo.can_create?(user, self)
|
414
|
+
else
|
415
|
+
original = duplicate
|
416
|
+
# 'duplicate' can cause these to be set, but they can conflict
|
417
|
+
# with the changes so we clear them
|
418
|
+
clear_aggregation_cache
|
419
|
+
clear_association_cache
|
420
|
+
|
421
|
+
self.attributes = changes
|
422
|
+
|
423
|
+
Hobo.can_update?(user, original, self)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
|
349
429
|
def user_changes!(user, changes={})
|
350
430
|
user_changes(user, changes) or raise PermissionDeniedError
|
351
431
|
end
|
352
|
-
|
353
|
-
|
432
|
+
|
433
|
+
|
354
434
|
def user_can_create?(user, attributes={})
|
355
435
|
raise ArgumentError, "Called #user_can_create? on existing record" unless new_record?
|
356
436
|
user_changes(user, attributes)
|
357
437
|
end
|
358
|
-
|
438
|
+
|
359
439
|
|
360
440
|
def user_save_changes(user, changes={})
|
361
|
-
|
362
|
-
|
441
|
+
with_acting_user user do
|
442
|
+
user_changes!(user, changes)
|
443
|
+
save
|
444
|
+
end
|
363
445
|
end
|
364
|
-
|
446
|
+
|
447
|
+
|
448
|
+
def user_save(user)
|
449
|
+
user_save_changes(user)
|
450
|
+
end
|
451
|
+
|
365
452
|
|
366
453
|
def user_view(user, field=nil)
|
367
454
|
raise PermissionDeniedError, self.inspect unless Hobo.can_view?(user, self, field)
|
368
455
|
end
|
369
|
-
|
370
|
-
|
456
|
+
|
457
|
+
|
371
458
|
def user_destroy(user)
|
372
|
-
|
373
|
-
|
459
|
+
with_acting_user user do
|
460
|
+
raise PermissionDeniedError unless Hobo.can_delete?(user, self)
|
461
|
+
destroy
|
462
|
+
end
|
374
463
|
end
|
375
|
-
|
376
|
-
|
464
|
+
|
465
|
+
|
377
466
|
def dependent_on
|
378
467
|
self.class.dependent_on.map { |assoc| send(assoc) }
|
379
468
|
end
|
380
|
-
|
381
|
-
|
469
|
+
|
470
|
+
|
382
471
|
def attributes_with_hobo_type_conversion=(attributes, guard_protected_attributes=true)
|
383
472
|
converted = attributes.map_hash { |k, v| convert_type_for_mass_assignment(self.class.attr_type(k), v) }
|
384
473
|
send(:attributes_without_hobo_type_conversion=, converted, guard_protected_attributes)
|
385
474
|
end
|
386
|
-
|
387
475
|
|
388
|
-
|
476
|
+
|
389
477
|
def set_creator(user)
|
390
478
|
set_creator!(user) unless get_creator
|
391
479
|
end
|
392
|
-
|
393
|
-
|
480
|
+
|
481
|
+
|
394
482
|
def set_creator!(user)
|
395
483
|
attr = self.class.creator_attribute
|
396
484
|
return unless attr
|
397
|
-
|
485
|
+
|
398
486
|
# Is creator a string field or an association?
|
399
|
-
if self.class.
|
400
|
-
#
|
401
|
-
self.send("#{attr}=", user) if (t = self.class.creator_type) && user.is_a?(t)
|
402
|
-
else
|
403
|
-
# Assume it's a string field -- set it to the name of the current user
|
487
|
+
if self.class.attr_type(attr)._? <= String
|
488
|
+
# Set it to the name of the current user
|
404
489
|
self.send("#{attr}=", user.to_s) unless user.guest?
|
490
|
+
else
|
491
|
+
# Assume user is a user object, but don't set if we've got a type mismatch
|
492
|
+
t = self.class.creator_type
|
493
|
+
self.send("#{attr}=", user) if t.nil? || user.is_a?(t)
|
405
494
|
end
|
406
495
|
end
|
407
|
-
|
408
|
-
|
496
|
+
|
497
|
+
|
409
498
|
# We deliberately give this method an unconventional name to avoid
|
410
499
|
# polluting the application namespace too badly
|
411
500
|
def get_creator
|
@@ -418,7 +507,7 @@ module Hobo
|
|
418
507
|
copy.copy_instance_variables_from(self, ["@attributes_cache"])
|
419
508
|
copy.instance_variable_set("@attributes", @attributes.dup)
|
420
509
|
copy.instance_variable_set("@new_record", nil) unless new_record?
|
421
|
-
|
510
|
+
|
422
511
|
# Shallow copy of belongs_to associations
|
423
512
|
for refl in self.class.reflections.values
|
424
513
|
if refl.macro == :belongs_to and (target = self.send(refl.name))
|
@@ -433,31 +522,31 @@ module Hobo
|
|
433
522
|
|
434
523
|
def same_fields?(other, *fields)
|
435
524
|
return true if other.nil?
|
436
|
-
|
525
|
+
|
437
526
|
fields = fields.flatten
|
438
527
|
fields.all?{|f| self.send(f) == other.send(f)}
|
439
528
|
end
|
440
|
-
|
441
|
-
|
529
|
+
|
530
|
+
|
442
531
|
def only_changed_fields?(other, *changed_fields)
|
443
532
|
return true if other.nil?
|
444
|
-
|
533
|
+
|
445
534
|
changed_fields = changed_fields.flatten.*.to_s
|
446
535
|
all_cols = self.class.columns.*.name - []
|
447
536
|
all_cols.all?{|c| c.in?(changed_fields) || self.send(c) == other.send(c) }
|
448
537
|
end
|
449
|
-
|
450
|
-
|
538
|
+
|
539
|
+
|
451
540
|
def compose_with(object, use=nil)
|
452
541
|
CompositeModel.new_for([self, object])
|
453
542
|
end
|
454
|
-
|
543
|
+
|
455
544
|
|
456
545
|
def typed_id
|
457
|
-
"#{self.class.name.underscore}_#{self.id}" if id
|
546
|
+
"#{self.class.name.underscore}_#{self.id}" if id
|
458
547
|
end
|
459
548
|
|
460
|
-
|
549
|
+
|
461
550
|
def to_s
|
462
551
|
if self.class.name_attribute
|
463
552
|
send self.class.name_attribute
|
@@ -465,23 +554,26 @@ module Hobo
|
|
465
554
|
"#{self.class.name.titleize} #{id}"
|
466
555
|
end
|
467
556
|
end
|
468
|
-
|
469
|
-
|
557
|
+
|
558
|
+
|
470
559
|
private
|
471
|
-
|
472
|
-
|
560
|
+
|
561
|
+
|
473
562
|
def parse_datetime(s)
|
474
563
|
defined?(Chronic) ? Chronic.parse(s) : Time.parse(s)
|
475
564
|
end
|
476
565
|
|
477
|
-
|
566
|
+
|
478
567
|
def convert_type_for_mass_assignment(field_type, value)
|
479
|
-
if field_type.is_a?(ActiveRecord::
|
480
|
-
|
481
|
-
|
568
|
+
if field_type.is_a?(Class) && field_type < ActiveRecord::Base
|
569
|
+
convert_record_reference_for_mass_assignment(field_type, value)
|
570
|
+
|
571
|
+
elsif field_type.is_a?(ActiveRecord::Reflection::AssociationReflection)
|
572
|
+
convert_collection_for_mass_assignment(field_type, value)
|
573
|
+
|
482
574
|
elsif !field_type.is_a?(Class)
|
483
575
|
value
|
484
|
-
|
576
|
+
|
485
577
|
elsif field_type <= Date
|
486
578
|
if value.is_a? Hash
|
487
579
|
Date.new(*(%w{year month day}.map{|s| value[s].to_i}))
|
@@ -491,8 +583,8 @@ module Hobo
|
|
491
583
|
else
|
492
584
|
value
|
493
585
|
end
|
494
|
-
|
495
|
-
elsif field_type <= Time
|
586
|
+
|
587
|
+
elsif field_type <= Time || field_type <= ActiveSupport::TimeWithZone
|
496
588
|
if value.is_a? Hash
|
497
589
|
Time.local(*(%w{year month day hour minute}.map{|s| value[s].to_i}))
|
498
590
|
elsif value.is_a? String
|
@@ -500,52 +592,49 @@ module Hobo
|
|
500
592
|
else
|
501
593
|
value
|
502
594
|
end
|
503
|
-
|
595
|
+
|
504
596
|
elsif field_type <= Hobo::Boolean
|
505
597
|
(value.is_a?(String) && value.strip.downcase.in?(['0', 'false']) || value.blank?) ? false : true
|
506
|
-
|
598
|
+
|
507
599
|
else
|
508
|
-
#
|
600
|
+
# no conversion
|
509
601
|
value
|
510
602
|
end
|
511
603
|
end
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
else
|
520
|
-
reflection.klass.named(value)
|
521
|
-
end
|
522
|
-
else
|
523
|
-
value
|
524
|
-
end
|
525
|
-
elsif reflection.macro == :has_many
|
526
|
-
if reflection.klass.try.name_attribute
|
527
|
-
value.map do |x|
|
528
|
-
if x.is_a?(String)
|
529
|
-
reflection.klass.named(x) unless x.blank?
|
530
|
-
else
|
531
|
-
x
|
532
|
-
end
|
533
|
-
end.compact
|
604
|
+
|
605
|
+
|
606
|
+
def convert_record_reference_for_mass_assignment(klass, value)
|
607
|
+
if value.is_a?(String)
|
608
|
+
if value.starts_with?('@')
|
609
|
+
# TODO: This @foo_1 feature is rarely (never?) used - get rid of it
|
610
|
+
Hobo.object_from_dom_id(value[1..-1])
|
534
611
|
else
|
535
|
-
value
|
612
|
+
klass.named(value)
|
536
613
|
end
|
537
|
-
|
538
614
|
else
|
539
|
-
# unknown kind of accociation - no conversion
|
540
615
|
value
|
541
616
|
end
|
542
617
|
end
|
543
|
-
|
618
|
+
|
619
|
+
|
620
|
+
def convert_collection_for_mass_assignment(reflection, value)
|
621
|
+
klass = reflection.safe_class
|
622
|
+
if klass.try.name_attribute && value.is_a?(Array)
|
623
|
+
value.map do |x|
|
624
|
+
if x.is_a?(String)
|
625
|
+
klass.named(x) unless x.blank?
|
626
|
+
else
|
627
|
+
x
|
628
|
+
end
|
629
|
+
end.compact
|
630
|
+
else
|
631
|
+
value
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
544
635
|
end
|
545
|
-
|
636
|
+
|
546
637
|
end
|
547
638
|
|
548
639
|
|
549
|
-
|
550
|
-
alias_method :has_hobo_method?, :respond_to_without_attributes?
|
551
|
-
end
|
640
|
+
Hobo::Model.enable if defined? ActiveRecord
|