incline 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +186 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +208 -0
- data/Rakefile +37 -0
- data/app/assets/fonts/incline/.keep +0 -0
- data/app/assets/images/incline/.keep +0 -0
- data/app/assets/images/incline/barcode-B.svg +181 -0
- data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
- data/app/assets/javascripts/incline/application.js +30 -0
- data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
- data/app/assets/javascripts/incline/datatables.js +22193 -0
- data/app/assets/javascripts/incline/escapeHtml.js +10 -0
- data/app/assets/javascripts/incline/inline_actions.js +479 -0
- data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
- data/app/assets/javascripts/incline/jquery.number.js +764 -0
- data/app/assets/javascripts/incline/regexMask.js +27 -0
- data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
- data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
- data/app/assets/stylesheets/incline/application.css +18 -0
- data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
- data/app/assets/stylesheets/incline/custom.scss +279 -0
- data/app/assets/stylesheets/incline/datatables.css +494 -0
- data/app/assets/stylesheets/incline/datepicker3.css +790 -0
- data/app/assets/stylesheets/incline/select2.css +484 -0
- data/app/controllers/incline/access_groups_controller.rb +127 -0
- data/app/controllers/incline/access_test_controller.rb +30 -0
- data/app/controllers/incline/account_activations_controller.rb +28 -0
- data/app/controllers/incline/application_controller.rb +11 -0
- data/app/controllers/incline/contact_controller.rb +34 -0
- data/app/controllers/incline/password_resets_controller.rb +113 -0
- data/app/controllers/incline/security_controller.rb +100 -0
- data/app/controllers/incline/sessions_controller.rb +50 -0
- data/app/controllers/incline/users_controller.rb +304 -0
- data/app/controllers/incline/welcome_controller.rb +19 -0
- data/app/helpers/incline/.keep +0 -0
- data/app/mailers/incline/application_mailer_base.rb +11 -0
- data/app/mailers/incline/contact_form.rb +19 -0
- data/app/mailers/incline/user_mailer.rb +45 -0
- data/app/models/incline/access_group.rb +121 -0
- data/app/models/incline/access_group_group_member.rb +12 -0
- data/app/models/incline/access_group_user_member.rb +10 -0
- data/app/models/incline/action_group.rb +12 -0
- data/app/models/incline/action_security.rb +222 -0
- data/app/models/incline/contact_message.rb +37 -0
- data/app/models/incline/disable_info.rb +20 -0
- data/app/models/incline/password_reset.rb +14 -0
- data/app/models/incline/password_reset_request.rb +14 -0
- data/app/models/incline/user.rb +437 -0
- data/app/models/incline/user_login_history.rb +30 -0
- data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
- data/app/views/incline/access_groups/_form.html.erb +19 -0
- data/app/views/incline/access_groups/_list.html.erb +60 -0
- data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
- data/app/views/incline/access_groups/edit.html.erb +2 -0
- data/app/views/incline/access_groups/index.html.erb +6 -0
- data/app/views/incline/access_groups/index.json.jbuilder +16 -0
- data/app/views/incline/access_groups/new.html.erb +2 -0
- data/app/views/incline/access_groups/show.html.erb +9 -0
- data/app/views/incline/access_groups/show.json.jbuilder +11 -0
- data/app/views/incline/contact/new.html.erb +22 -0
- data/app/views/incline/contact_form/contact.html.erb +16 -0
- data/app/views/incline/contact_form/contact.text.erb +13 -0
- data/app/views/incline/password_resets/edit.html.erb +16 -0
- data/app/views/incline/password_resets/new.html.erb +12 -0
- data/app/views/incline/security/_details.json.jbuilder +7 -0
- data/app/views/incline/security/_form.html.erb +20 -0
- data/app/views/incline/security/_list.html.erb +89 -0
- data/app/views/incline/security/_messages.json.jbuilder +6 -0
- data/app/views/incline/security/edit.html.erb +2 -0
- data/app/views/incline/security/index.html.erb +6 -0
- data/app/views/incline/security/index.json.jbuilder +16 -0
- data/app/views/incline/security/show.html.erb +31 -0
- data/app/views/incline/security/show.json.jbuilder +11 -0
- data/app/views/incline/sessions/new.html.erb +26 -0
- data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
- data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
- data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
- data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
- data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
- data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
- data/app/views/incline/users/_details.json.jbuilder +32 -0
- data/app/views/incline/users/_form.html.erb +21 -0
- data/app/views/incline/users/_list.html.erb +102 -0
- data/app/views/incline/users/_messages.json.jbuilder +6 -0
- data/app/views/incline/users/disable_confirm.html.erb +19 -0
- data/app/views/incline/users/edit.html.erb +5 -0
- data/app/views/incline/users/index.html.erb +6 -0
- data/app/views/incline/users/index.json.jbuilder +16 -0
- data/app/views/incline/users/new.html.erb +5 -0
- data/app/views/incline/users/show.html.erb +12 -0
- data/app/views/incline/users/show.json.jbuilder +11 -0
- data/app/views/incline/welcome/home.html.erb +5 -0
- data/app/views/layouts/application.html.erb +1 -0
- data/app/views/layouts/incline/_account_menu.html.erb +18 -0
- data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
- data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
- data/app/views/layouts/incline/_footer.html.erb +13 -0
- data/app/views/layouts/incline/_header.html.erb +21 -0
- data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
- data/app/views/layouts/incline/_incline_app.html.erb +25 -0
- data/app/views/layouts/incline/_messages.html.erb +3 -0
- data/app/views/layouts/incline/_shim.html.erb +3 -0
- data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
- data/app/views/layouts/incline/application.html.erb +1 -0
- data/app/views/layouts/mailer.html.erb +2 -0
- data/app/views/layouts/mailer.text.erb +2 -0
- data/bin/rails +12 -0
- data/bin/test_scaffold.sh +10 -0
- data/config/routes.rb +61 -0
- data/db/migrate/20170511230126_create_incline_users.rb +26 -0
- data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
- data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
- data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
- data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
- data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
- data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
- data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
- data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
- data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
- data/db/seeds.rb +81 -0
- data/exe/new_incline_app +42 -0
- data/lib/generators/incline/install_generator.rb +259 -0
- data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
- data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
- data/lib/generators/incline/templates/incline_application.css +17 -0
- data/lib/generators/incline/templates/incline_application.html.erb +1 -0
- data/lib/generators/incline/templates/incline_application.js +12 -0
- data/lib/generators/incline/templates/incline_database.yml +25 -0
- data/lib/generators/incline/templates/incline_email.yml +20 -0
- data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
- data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
- data/lib/generators/incline/templates/incline_users.yml +64 -0
- data/lib/generators/incline/templates/incline_version.rb +3 -0
- data/lib/incline/auth_engine_base.rb +52 -0
- data/lib/incline/data_tables_request.rb +336 -0
- data/lib/incline/date_time_formats.rb +6 -0
- data/lib/incline/engine.rb +212 -0
- data/lib/incline/errors.rb +15 -0
- data/lib/incline/extensions/action_controller_base.rb +526 -0
- data/lib/incline/extensions/action_mailer_base.rb +66 -0
- data/lib/incline/extensions/action_view_base.rb +489 -0
- data/lib/incline/extensions/active_record_base.rb +308 -0
- data/lib/incline/extensions/application.rb +137 -0
- data/lib/incline/extensions/application_configuration.rb +50 -0
- data/lib/incline/extensions/connection_adapter.rb +55 -0
- data/lib/incline/extensions/date_time_value.rb +123 -0
- data/lib/incline/extensions/date_value.rb +77 -0
- data/lib/incline/extensions/decimal_value.rb +55 -0
- data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
- data/lib/incline/extensions/float_value.rb +59 -0
- data/lib/incline/extensions/form_builder.rb +617 -0
- data/lib/incline/extensions/integer_value.rb +54 -0
- data/lib/incline/extensions/jbuilder_generator.rb +38 -0
- data/lib/incline/extensions/jbuilder_template.rb +39 -0
- data/lib/incline/extensions/main_app.rb +40 -0
- data/lib/incline/extensions/numeric.rb +63 -0
- data/lib/incline/extensions/object.rb +31 -0
- data/lib/incline/extensions/resource_route_generator.rb +53 -0
- data/lib/incline/extensions/session.rb +113 -0
- data/lib/incline/extensions/string.rb +50 -0
- data/lib/incline/extensions/test_case.rb +764 -0
- data/lib/incline/extensions/time_zone_converter.rb +40 -0
- data/lib/incline/global_status.rb +236 -0
- data/lib/incline/helpers/route_hash_formatter.rb +46 -0
- data/lib/incline/json_log_formatter.rb +96 -0
- data/lib/incline/json_logger.rb +17 -0
- data/lib/incline/log.rb +153 -0
- data/lib/incline/number_formats.rb +17 -0
- data/lib/incline/recaptcha.rb +346 -0
- data/lib/incline/user_manager.rb +212 -0
- data/lib/incline/validators/email_validator.rb +45 -0
- data/lib/incline/validators/ip_address_validator.rb +32 -0
- data/lib/incline/validators/recaptcha_validator.rb +37 -0
- data/lib/incline/validators/safe_name_validator.rb +31 -0
- data/lib/incline/version.rb +3 -0
- data/lib/incline/work_path.rb +75 -0
- data/lib/incline.rb +197 -0
- data/lib/tasks/incline_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +43 -0
- data/lib/templates/erb/scaffold/_list.html.erb +81 -0
- data/lib/templates/erb/scaffold/edit.html.erb +1 -0
- data/lib/templates/erb/scaffold/index.html.erb +6 -0
- data/lib/templates/erb/scaffold/new.html.erb +1 -0
- data/lib/templates/erb/scaffold/show.html.erb +34 -0
- data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
- data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
- data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
- data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
- data/test/controllers/incline/access_groups_controller_test.rb +65 -0
- data/test/controllers/incline/access_test_controller_test.rb +53 -0
- data/test/controllers/incline/contact_controller_test.rb +32 -0
- data/test/controllers/incline/security_controller_test.rb +39 -0
- data/test/controllers/incline/welcome_controller_test.rb +16 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +12 -0
- data/test/dummy/app/assets/stylesheets/application.css +17 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +1 -0
- data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
- data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config/application.rb +38 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +34 -0
- data/test/dummy/config/email.yml +24 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +45 -0
- data/test/dummy/config/environments/production.rb +85 -0
- data/test/dummy/config/environments/test.rb +44 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +6 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/schema.rb +108 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/extensions/action_controller_base_extensions_test.rb +21 -0
- data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
- data/test/extensions/action_view_base_extensions_test.rb +267 -0
- data/test/extensions/active_record_extensions_test.rb +173 -0
- data/test/extensions/application_configuration_extensions_test.rb +46 -0
- data/test/extensions/application_extensions_test.rb +23 -0
- data/test/extensions/connection_adapter_extensions_test.rb +54 -0
- data/test/extensions/date_time_value_extensions_test.rb +104 -0
- data/test/extensions/date_value_extensions_test.rb +102 -0
- data/test/extensions/decimal_value_extensions_test.rb +85 -0
- data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
- data/test/extensions/float_value_extensions_test.rb +78 -0
- data/test/extensions/form_builder_extensions_test.rb +28 -0
- data/test/extensions/integer_value_extensions_test.rb +78 -0
- data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
- data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
- data/test/extensions/main_app_extensions_test.rb +55 -0
- data/test/extensions/numeric_extensions_test.rb +76 -0
- data/test/extensions/object_extensions_test.rb +104 -0
- data/test/extensions/session_extensions_test.rb +69 -0
- data/test/extensions/string_extensions_test.rb +32 -0
- data/test/extensions/test_case_extensions_test.rb +538 -0
- data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
- data/test/fixtures/incline/access_group_group_members.yml +1 -0
- data/test/fixtures/incline/access_group_user_members.yml +1 -0
- data/test/fixtures/incline/access_groups.yml +13 -0
- data/test/fixtures/incline/action_groups.yml +6 -0
- data/test/fixtures/incline/action_securities.yml +18 -0
- data/test/fixtures/incline/user_login_histories.yml +1 -0
- data/test/fixtures/incline/users.yml +64 -0
- data/test/incline_test.rb +63 -0
- data/test/integration/incline/users_edit_test.rb +180 -0
- data/test/integration/incline/users_login_test.rb +105 -0
- data/test/integration/incline/users_signup_test.rb +147 -0
- data/test/integration/navigation_test.rb +11 -0
- data/test/lib/data_tables_request_test.rb +245 -0
- data/test/lib/date_time_formats_test.rb +111 -0
- data/test/lib/global_status_test.rb +89 -0
- data/test/lib/json_log_formatter_test.rb +43 -0
- data/test/lib/log_test.rb +36 -0
- data/test/lib/recaptcha_test.rb +75 -0
- data/test/lib/user_manager_test.rb +47 -0
- data/test/lib/work_path_test.rb +18 -0
- data/test/models/incline/access_group_group_member_test.rb +30 -0
- data/test/models/incline/access_group_test.rb +60 -0
- data/test/models/incline/access_group_user_member_test.rb +29 -0
- data/test/models/incline/action_group_test.rb +27 -0
- data/test/models/incline/action_security_test.rb +176 -0
- data/test/models/incline/contact_message_test.rb +66 -0
- data/test/models/incline/disable_info_test.rb +29 -0
- data/test/models/incline/password_reset_request_test.rb +35 -0
- data/test/models/incline/password_reset_test.rb +51 -0
- data/test/models/incline/user_login_history_test.rb +31 -0
- data/test/models/incline/user_test.rb +91 -0
- data/test/test_helper.rb +42 -0
- data/test/validators/email_validator_test.rb +102 -0
- data/test/validators/ip_address_validator_test.rb +107 -0
- data/test/validators/recaptcha_validator_test.rb +57 -0
- data/test/validators/safe_name_validator_test.rb +101 -0
- metadata +584 -0
@@ -0,0 +1,308 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Incline::Extensions
|
4
|
+
module ActiveRecordBase
|
5
|
+
|
6
|
+
def to_s # :nodoc:
|
7
|
+
if respond_to?(:name)
|
8
|
+
send :name
|
9
|
+
else
|
10
|
+
"ID = #{id}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect # :nodoc:
|
15
|
+
"#<#{self.class}:#{self.object_pointer} #{to_s}>"
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Tests for equality on ID if available.
|
20
|
+
def ==(other)
|
21
|
+
if self.class.attribute_names.include?('id')
|
22
|
+
if other.is_a?(::Numeric)
|
23
|
+
id == other
|
24
|
+
elsif other.class == self.class
|
25
|
+
id == other.id
|
26
|
+
else
|
27
|
+
false
|
28
|
+
end
|
29
|
+
else
|
30
|
+
self.inspect == other.inspect
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Compares by code, name, or to_s depending on if the code or name attributes are present.
|
36
|
+
def <=>(other)
|
37
|
+
m = self.class.default_sort_method
|
38
|
+
my_val = send(m)
|
39
|
+
|
40
|
+
# other can be a string or a model of the same type as this model.
|
41
|
+
other_val =
|
42
|
+
if other.is_a?(::String)
|
43
|
+
other
|
44
|
+
elsif other.class == self.class
|
45
|
+
other.send(m)
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
my_val <=> other_val
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Additional static methods for the ActiveRecord::Base class.
|
55
|
+
module ClassMethods
|
56
|
+
|
57
|
+
##
|
58
|
+
# Gets the default sort method for this model.
|
59
|
+
#
|
60
|
+
# In order of preference this will be 'code', 'name', or 'to_s'.
|
61
|
+
#
|
62
|
+
# Specifying a search_attribute before using this method will change this behavior.
|
63
|
+
#
|
64
|
+
# class MyModel
|
65
|
+
# attr_accessor :id, :name, :employee_id
|
66
|
+
# end
|
67
|
+
# MyModel.default_sort_method # 'name'
|
68
|
+
#
|
69
|
+
# class MyModel
|
70
|
+
# attr_accessor :id, :name, :employee_id
|
71
|
+
# search_attribute :employee_id
|
72
|
+
# end
|
73
|
+
# MyModel.default_sort_method # 'employee_id'
|
74
|
+
def default_sort_method
|
75
|
+
@default_sort_method ||= search_attributes.find{|a| attribute_names.include?(a)} || 'to_s'
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Specifies an attribute to search in the get_id, get, and [] methods.
|
80
|
+
#
|
81
|
+
# The default attributes to search are 'code' and 'name'. If you specify
|
82
|
+
# an additional attribute it will be prefixed to the list. This affects
|
83
|
+
# sorting behavior, but not necessarily the search behavior since if the 'code'
|
84
|
+
# or 'name' attributes are also present, they will be searched as well.
|
85
|
+
#
|
86
|
+
# class MyModel
|
87
|
+
# attr_accessor :id, :name, :employee_id
|
88
|
+
# search_attribute :employee_id
|
89
|
+
# end
|
90
|
+
def search_attribute(attrib)
|
91
|
+
unless attrib.blank?
|
92
|
+
attrib = attrib.to_s.strip
|
93
|
+
search_attributes.insert(0, attrib) unless search_attributes.include?(attrib)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Gets the ID(s) based on the specified value.
|
99
|
+
#
|
100
|
+
# If a valid model is provided, then the :id attribute is returned.
|
101
|
+
#
|
102
|
+
# An integer simply gets returned. No validation is done to ensure it is a valid ID.
|
103
|
+
# A string representing an integer gets converted and returned. No validation is done.
|
104
|
+
# get_id(1234) => 1234
|
105
|
+
# get_id('1234') => 1234
|
106
|
+
#
|
107
|
+
# All further searches are against lowercased :code or :name attributes if either is a valid attribute.
|
108
|
+
# You can use the search_attribute method to add another attribute to compare against.
|
109
|
+
#
|
110
|
+
# A symbol is converted to a string and a humanized string.
|
111
|
+
# get_id(:one_two_three) => searches for 'one_two_three' or 'one two three'.
|
112
|
+
#
|
113
|
+
# Strings are lowercased and compared against lowercased :code or :name if either of those is a valid attribute.
|
114
|
+
# get_id('Alpha Bravo') => searches for 'alpha bravo'
|
115
|
+
#
|
116
|
+
# If a string begins with a # and contains only numbers after that, then it will allow you to search for a
|
117
|
+
# non-ID field that only contains numbers. The value is searched as both the supplied value and only the numeric
|
118
|
+
# digits.
|
119
|
+
#
|
120
|
+
# get_id('#1234') => searches for '#1234' or '1234'
|
121
|
+
#
|
122
|
+
# Arrays are mapped as above.
|
123
|
+
#
|
124
|
+
# In all cases, if one result is found that value is returned, if more than one is found then an array is returned,
|
125
|
+
# and if no results are found, nil is returned. If the model does not include an :id attributes, then nil will
|
126
|
+
# always be returned because there can be no valid results.
|
127
|
+
#
|
128
|
+
# # Assuming this data set:
|
129
|
+
# # ID | NAME
|
130
|
+
# # -------|--------------------
|
131
|
+
# # 1 | Juliet
|
132
|
+
# # 2 | Romeo
|
133
|
+
# # 3 | 4321
|
134
|
+
# # 4 | 1234
|
135
|
+
#
|
136
|
+
# get_id(1,3,5,7,'Romeo','#1234') # returns [ 1, 3, 5, 7, 2, 4 ]
|
137
|
+
# # 1, 3, 5, & 7 are not verified, but :name is searched for "romeo", "#1234", and "1234" to add 2 & 4.
|
138
|
+
#
|
139
|
+
# get_id('#4321') # returns 3 since there is only one valid result.
|
140
|
+
#
|
141
|
+
def get_id(*value)
|
142
|
+
return nil if value.blank?
|
143
|
+
return nil unless attribute_names.include?('id')
|
144
|
+
|
145
|
+
value = value.first if value.count == 1
|
146
|
+
|
147
|
+
return value.map{|v| get_id(v)} if value.is_a?(::Array)
|
148
|
+
|
149
|
+
return value.id if value.class == self
|
150
|
+
return value if value.is_a?(::Integer)
|
151
|
+
return value.to_i if value.to_s =~ /\A\d+\z/
|
152
|
+
|
153
|
+
result = search_for(value).order(:id).pluck(:id).to_a
|
154
|
+
|
155
|
+
return nil if result.blank?
|
156
|
+
return result.first if result.count == 1
|
157
|
+
|
158
|
+
result
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Gets one or more items based on the value.
|
163
|
+
#
|
164
|
+
# Always returns an array of items or nil if no results were found.
|
165
|
+
#
|
166
|
+
# See #get_id for how the value is processed. The only difference is
|
167
|
+
# numeric IDs must be valid for the models to be returned.
|
168
|
+
#
|
169
|
+
# # Assuming this data set:
|
170
|
+
# # ID | NAME
|
171
|
+
# # -------|--------------------
|
172
|
+
# # 1 | Juliet
|
173
|
+
# # 2 | Romeo
|
174
|
+
# # 3 | 4321
|
175
|
+
# # 4 | 1234
|
176
|
+
#
|
177
|
+
# get(5) # returns nil
|
178
|
+
# get(1,3,5,7) # returns [ { 1 => Juliet }, { 3 => 4321 } ]
|
179
|
+
# get('Romeo') # returns [ { 2 => Romeo } ]
|
180
|
+
# get('#1234') # returns [ { 4 => 1234 } ]
|
181
|
+
#
|
182
|
+
def get(*value)
|
183
|
+
return nil if value.blank?
|
184
|
+
|
185
|
+
value = value.first if value.count == 1
|
186
|
+
|
187
|
+
return value if value.class == self
|
188
|
+
|
189
|
+
result = search_for(value)
|
190
|
+
first_sort = search_attributes.find{|a| attribute_names.include?(a)}
|
191
|
+
if first_sort
|
192
|
+
result = result.order(first_sort, :id)
|
193
|
+
else
|
194
|
+
result = result.order(:id)
|
195
|
+
end
|
196
|
+
result = result.to_a
|
197
|
+
return nil if result.blank?
|
198
|
+
result
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Gets one item based on the value.
|
203
|
+
#
|
204
|
+
# Always returns the first item found or nil if there were no matches.
|
205
|
+
#
|
206
|
+
# See #get_id for how the value is processed. The only difference is
|
207
|
+
# numeric IDs must be valid for the model to be returned.
|
208
|
+
#
|
209
|
+
# # Assuming this data set:
|
210
|
+
# # ID | NAME
|
211
|
+
# # -------|--------------------
|
212
|
+
# # 1 | Juliet
|
213
|
+
# # 2 | Romeo
|
214
|
+
# # 3 | 4321
|
215
|
+
# # 4 | 1234
|
216
|
+
#
|
217
|
+
# [5] # returns nil
|
218
|
+
# [1,3,5,7] # returns { 1 => Juliet }
|
219
|
+
# ['Romeo'] # returns { 2 => Romeo }
|
220
|
+
# ['#1234'] # returns { 4 => 1234 }
|
221
|
+
#
|
222
|
+
def [](*value)
|
223
|
+
get(*value)&.first
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def search_attributes
|
229
|
+
@search_attributes ||= %w(code name)
|
230
|
+
end
|
231
|
+
|
232
|
+
def search_for(values)
|
233
|
+
# make sure we have an array that we can safely modify.
|
234
|
+
values = values.is_a?(::Array) ? values.dup : [ values ]
|
235
|
+
values.reject!{|v| v.blank?}
|
236
|
+
values.flatten!
|
237
|
+
|
238
|
+
# return a query that will return no records.
|
239
|
+
return self.where('(1 = 0)') if values.blank?
|
240
|
+
|
241
|
+
# extract potential IDs.
|
242
|
+
ids = values
|
243
|
+
.select{|v| !v.is_a?(::Symbol) && v.to_s =~ /\A\d+\z/}
|
244
|
+
.map{|v| v.to_i}
|
245
|
+
|
246
|
+
# convert models to IDs to force reloading them.
|
247
|
+
ids += values
|
248
|
+
.select{|v| v.class == self}
|
249
|
+
.map{|v| v.id}
|
250
|
+
|
251
|
+
# only unique IDs are kept.
|
252
|
+
ids.uniq!
|
253
|
+
|
254
|
+
# and then extract string/symbol values for further searching.
|
255
|
+
# purely numeric values and blank values are discarded.
|
256
|
+
values = values
|
257
|
+
.select{|v| (v.is_a?(::String) && !v.blank? && !(v =~ /\A\d+\z/)) || (v.is_a?(::Symbol) && !v.to_s.blank?)}
|
258
|
+
.map{|v| (v.is_a?(::String) && v =~ /\A#\d+\z/) ? [ v, v[1..-1] ] : v}
|
259
|
+
.map{|v| v.is_a?(::Symbol) ? [ v.to_s.downcase, v.to_s.humanize.downcase ] : v.to_s.humanize.downcase}
|
260
|
+
.flatten
|
261
|
+
|
262
|
+
# only unique values are kept.
|
263
|
+
values.uniq!
|
264
|
+
|
265
|
+
# get the attributes to search.
|
266
|
+
attribs = search_attributes
|
267
|
+
.select{|attr| attribute_names.include?(attr)}
|
268
|
+
.map{|a| a.to_s.gsub("'", "''").gsub('"','""') }
|
269
|
+
|
270
|
+
# do a sanity check.
|
271
|
+
raise 'No valid values to search for.' if ids.blank? && values.blank?
|
272
|
+
raise 'No ID attribute to search.' unless ids.blank? || attribute_names.include?('id')
|
273
|
+
raise 'No attributes to search.' unless values.blank? || attribs.any?
|
274
|
+
|
275
|
+
filters = []
|
276
|
+
filter_values = []
|
277
|
+
tbl = table_name.to_s.gsub("'", "''").gsub('"','""')
|
278
|
+
|
279
|
+
# include the ID filters.
|
280
|
+
ids.each do |id|
|
281
|
+
filters << "(\"#{tbl}\".\"id\" = ?)"
|
282
|
+
filter_values << id
|
283
|
+
end
|
284
|
+
|
285
|
+
# include the value filters.
|
286
|
+
values.each do |value|
|
287
|
+
attribs.each do |attr|
|
288
|
+
filters << "(LOWER(\"#{tbl}\".\"#{attr}\") = ?)"
|
289
|
+
filter_values << value
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
filters = filters.join(' OR ')
|
294
|
+
|
295
|
+
self.where(filters, *filter_values)
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
def self.included(base)
|
301
|
+
base.class_eval do
|
302
|
+
extend ClassMethods
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
ActiveRecord::Base.include Incline::Extensions::ActiveRecordBase
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'cgi/util'
|
2
|
+
require 'yaml'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'rails'
|
5
|
+
|
6
|
+
module Incline::Extensions
|
7
|
+
##
|
8
|
+
# Adds some informational methods to the Application class.
|
9
|
+
module Application
|
10
|
+
|
11
|
+
##
|
12
|
+
# Is the rails server running?
|
13
|
+
def running?
|
14
|
+
path = File.join(Rails.root, 'tmp/pids/server.pid')
|
15
|
+
pid = File.exist?(path) ? File.read(path).to_i : -1
|
16
|
+
server_running = true
|
17
|
+
begin
|
18
|
+
Process.getpgid pid
|
19
|
+
rescue Errno::ESRCH
|
20
|
+
server_running = false
|
21
|
+
end
|
22
|
+
server_running
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Gets the application name.
|
27
|
+
#
|
28
|
+
# You should override this method in your +application.rb+ file to return the appropriate value.
|
29
|
+
def app_name
|
30
|
+
default_notify :app_name
|
31
|
+
'Incline'
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Gets the application instance name.
|
36
|
+
#
|
37
|
+
# This can be set by creating a +config/instance.yml+ configuration file and setting the 'name' property.
|
38
|
+
# The instance name is used to create unique cookies for each instance of an application.
|
39
|
+
# The default instance name is 'default'.
|
40
|
+
def app_instance_name
|
41
|
+
@app_instance_name ||=
|
42
|
+
begin
|
43
|
+
yaml = Rails.root.join('config','instance.yml')
|
44
|
+
if File.exist?(yaml)
|
45
|
+
yaml = (YAML.load_file(yaml) || {}).symbolize_keys
|
46
|
+
yaml[:name].blank? ? 'default' : yaml[:name]
|
47
|
+
else
|
48
|
+
'default'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Gets the application version.
|
55
|
+
#
|
56
|
+
# You should override this method in your +application.rb+ file to return the appropriate value.
|
57
|
+
def app_version
|
58
|
+
default_notify :app_version
|
59
|
+
'0.0.1'
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Gets the company owning the copyright to the application.
|
64
|
+
#
|
65
|
+
# You should override this method in your +application.rb+ file to return the appropriate value.
|
66
|
+
def app_company
|
67
|
+
default_notify :app_company
|
68
|
+
'BarkerEST'
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Gets the year of copyright ownership for the company.
|
73
|
+
#
|
74
|
+
# Defaults to the current year (at the time of execution).
|
75
|
+
def app_copyright_year
|
76
|
+
Time.now.year.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Gets the application name and version.
|
81
|
+
def app_info
|
82
|
+
"#{app_name} v#{app_version}"
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Gets the copyright statement for this application.
|
87
|
+
def app_copyright(html = true)
|
88
|
+
if html
|
89
|
+
"Copyright © #{CGI::escapeHTML app_copyright_year} #{CGI::escapeHTML app_company}".html_safe
|
90
|
+
else
|
91
|
+
"Copyright (C) #{app_copyright_year} #{app_company}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Is a restart currently pending.
|
97
|
+
def restart_pending?
|
98
|
+
return false unless File.exist?(restart_file)
|
99
|
+
request_time = File.mtime(restart_file)
|
100
|
+
request_time > Incline.start_time
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Updates the restart file to indicate we want to restart the web app.
|
105
|
+
def request_restart!
|
106
|
+
Incline::Log::info 'Requesting an application restart.'
|
107
|
+
FileUtils.touch restart_file
|
108
|
+
File.mtime restart_file
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Generates a cookie name using the application name and instance name.
|
113
|
+
def cookie_name(cookie)
|
114
|
+
"_incline_#{app_name.downcase.scan(/[a-z0-9]+/).join('_')}_#{app_instance_name.downcase.scan(/[a-z0-9]+/).join('_')}_#{cookie}"
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def default_notify(property)
|
121
|
+
@default_notify ||= {}
|
122
|
+
@default_notify[property] ||= 0
|
123
|
+
if @default_notify[property] == 0
|
124
|
+
@default_notify[property] = 1
|
125
|
+
Incline::Log::warn "Default \"#{property}\" is in use. Please define \"#{property}\" in your \"application.rb\" file."
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def restart_file
|
130
|
+
@restart_file ||= "#{self.config.root}/tmp/restart.txt"
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
Rails::Application.include Incline::Extensions::Application
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Incline::Extensions
|
4
|
+
##
|
5
|
+
# Creates a default database configuration to use when config/database.yml is not present.
|
6
|
+
module ApplicationConfiguration
|
7
|
+
|
8
|
+
##
|
9
|
+
# Override the +database_configuration+ method to return something in development mode if
|
10
|
+
# the +config/database.yml+ file is missing.
|
11
|
+
#
|
12
|
+
# A warning will be logged if the default configuration is used. In production mode, an
|
13
|
+
# exception will be bubbled up.
|
14
|
+
#
|
15
|
+
# The default configuration for test and development environments is to use a sqlite
|
16
|
+
# database in the db folder using the environment name (eg - db/development.sqlite).
|
17
|
+
#
|
18
|
+
# The primary purpose of this is to allow +rake+ and +rails+ actions that may not depend on the
|
19
|
+
# database configuration or may actually be used to generate the configuration file.
|
20
|
+
def self.included(base) #:nodoc:
|
21
|
+
base.class_eval do
|
22
|
+
alias :incline_appconfig_original_database_configuration :database_configuration
|
23
|
+
|
24
|
+
def database_configuration
|
25
|
+
begin
|
26
|
+
incline_appconfig_original_database_configuration
|
27
|
+
rescue
|
28
|
+
raise unless $!.inspect.include?('No such file -') && (!Rails.env.production?)
|
29
|
+
|
30
|
+
default = {
|
31
|
+
'adapter' => 'sqlite3',
|
32
|
+
'pool' => 5,
|
33
|
+
'timeout' => 5000
|
34
|
+
}
|
35
|
+
|
36
|
+
Incline::Log::warn "Providing default database configuration for #{Rails.env} environment."
|
37
|
+
|
38
|
+
{
|
39
|
+
'test' => default.merge('database' => 'db/test.sqlite'),
|
40
|
+
'development' => default.merge('database' => 'db/development.sqlite')
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Rails::Application::Configuration.include Incline::Extensions::ApplicationConfiguration
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Incline::Extensions
|
4
|
+
##
|
5
|
+
# Adds some extra functionality to database connections.
|
6
|
+
module ConnectionAdapter
|
7
|
+
|
8
|
+
##
|
9
|
+
# Searches the database to determine if an object with the specified name exists.
|
10
|
+
def object_exists?(object_name)
|
11
|
+
safe_name = "'#{object_name.gsub('\'','\'\'')}'"
|
12
|
+
|
13
|
+
sql =
|
14
|
+
case self.class.name
|
15
|
+
when 'ActiveRecord::ConnectionAdapters::SQLServerAdapter'
|
16
|
+
# use sysobjects table.
|
17
|
+
"SELECT COUNT(*) AS \"one\" FROM \"sysobjects\" WHERE \"name\"=#{safe_name}"
|
18
|
+
when 'ActiveRecord::ConnectionAdapters::SQLite3Adapter'
|
19
|
+
# use sqlite_master table.
|
20
|
+
"SELECT COUNT(*) AS \"one\" FROM \"sqlite_master\" WHERE (\"type\"='table' OR \"type\"='view') AND (\"name\"=#{safe_name})"
|
21
|
+
else
|
22
|
+
# query the information_schema TABLES and ROUTINES views.
|
23
|
+
"SELECT SUM(Z.\"one\") AS \"one\" FROM (SELECT COUNT(*) AS \"one\" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=#{safe_name} UNION SELECT COUNT(*) AS \"one\" FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME=#{safe_name}) AS Z"
|
24
|
+
end
|
25
|
+
|
26
|
+
result = exec_query(sql).first
|
27
|
+
|
28
|
+
result && result['one'] >= 1
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Executes a stored procedure.
|
33
|
+
#
|
34
|
+
# For MS SQL Server, this will return the return value from the procedure.
|
35
|
+
# For other providers, this is the same as +execute+.
|
36
|
+
def exec_sp(stmt)
|
37
|
+
case self.class.name
|
38
|
+
when 'ActiveRecord::ConnectionAdapters::SQLServerAdapter'
|
39
|
+
rex = /^exec(?:ute)?\s+[\["]?(?<PROC>[a-z][a-z0-9_]*)[\]"]?(?<ARGS>\s.*)?$/i
|
40
|
+
match = rex.match(stmt)
|
41
|
+
if match
|
42
|
+
exec_query("DECLARE @SP__RET INTEGER; EXECUTE @SP__RET=[#{match['PROC']}]#{match['ARGS']}; SELECT @SP__RET AS [RET]").first['RET']
|
43
|
+
else
|
44
|
+
execute stmt
|
45
|
+
end
|
46
|
+
else
|
47
|
+
execute stmt
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.include Incline::Extensions::ConnectionAdapter
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'incline/date_time_formats'
|
2
|
+
require 'incline/extensions/time_zone_converter'
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
module Incline::Extensions
|
6
|
+
|
7
|
+
##
|
8
|
+
# Patches the ActiveRecord DateTime value to accept more date formats.
|
9
|
+
#
|
10
|
+
# Specifically this will allow ActiveRecord models to receive dates in US format or ISO format.
|
11
|
+
module DateTimeValue
|
12
|
+
|
13
|
+
##
|
14
|
+
# Patches the ActiveRecord DateTime value type.
|
15
|
+
def self.included(base)
|
16
|
+
base.class_eval do
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
undef cast_value
|
21
|
+
|
22
|
+
def cast_value(string)
|
23
|
+
return nil if string.blank?
|
24
|
+
return string if string.is_a?(::Time)
|
25
|
+
|
26
|
+
if string.is_a?(::String)
|
27
|
+
|
28
|
+
begin
|
29
|
+
# if it matches either of our formats, we can try using it.
|
30
|
+
if (match = (Incline::DateTimeFormats::US_DATE_FORMAT.match(string) || Incline::DateTimeFormats::ALMOST_ISO_DATE_FORMAT.match(string)))
|
31
|
+
|
32
|
+
year = match['YEAR'].to_s.to_i
|
33
|
+
year += 2000 if year < 50
|
34
|
+
year += 1900 if year < 100
|
35
|
+
month = match['MONTH'].to_s.to_i
|
36
|
+
mday = match['DAY'].to_s.to_i
|
37
|
+
|
38
|
+
# ensure the date portion is valid.
|
39
|
+
dt =
|
40
|
+
begin
|
41
|
+
Time.utc(year, month, mday)
|
42
|
+
rescue
|
43
|
+
raise "Invalid date (#{$!.message})."
|
44
|
+
end
|
45
|
+
|
46
|
+
raise 'Invalid date (day of month is invalid for month).' unless dt.year == year && dt.month == month && dt.mday == mday
|
47
|
+
|
48
|
+
hour = match['HOUR'].to_s.to_i
|
49
|
+
minute = match['MINUTE'].to_s.to_i
|
50
|
+
second = match['SECOND'].to_s.to_i
|
51
|
+
|
52
|
+
# make sure the fraction is 6 chars in length, then convert to microseconds.
|
53
|
+
micros = match['FRACTION'].to_s[0...6].ljust(6,'0').to_i
|
54
|
+
|
55
|
+
if match.names.include?('AMPM')
|
56
|
+
if match['AMPM'].to_s.upcase == 'P' && hour < 12
|
57
|
+
hour += 12
|
58
|
+
elsif match['AMPM'].to_s.upcase == 'A' && hour == 12
|
59
|
+
hour = 0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
raise 'Invalid time (hour must be 0 to 24).' unless (0..24) === hour
|
64
|
+
raise 'Invalid time (minute must be 0 to 59).' unless (0...60) === minute
|
65
|
+
raise 'Invalid time (second must be 0 to 59).' unless (0...60) === second
|
66
|
+
raise 'Invalid time (minute and second must be 0 if hour is 24).' if hour == 24 && (minute != 0 || second != 0)
|
67
|
+
|
68
|
+
if hour == 24
|
69
|
+
dt += 86400
|
70
|
+
year = dt.year
|
71
|
+
month = dt.month
|
72
|
+
mday = dt.mday
|
73
|
+
hour = 0
|
74
|
+
end
|
75
|
+
|
76
|
+
# compute the tz offset in seconds.
|
77
|
+
offset =
|
78
|
+
if match.names.include?('TZ')
|
79
|
+
if match['TZ']
|
80
|
+
tz = match['TZ'].to_s.gsub(':','').upcase
|
81
|
+
if %w(Z +0000 -0000).include?(tz)
|
82
|
+
0
|
83
|
+
else
|
84
|
+
(tz[0] == '-' ? -1 : 1) * ((tz[1..2].to_i * 3600) + (tz[3..4].to_i * 60))
|
85
|
+
end
|
86
|
+
else
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
else
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# use the new_time method to honor the ActiveRecord::Base.default_timezone
|
94
|
+
new_time(year, month, mday, hour, minute, second, micros, offset)
|
95
|
+
else
|
96
|
+
# use the fallback if it doesn't match our formats.
|
97
|
+
fallback_string_to_time(string)
|
98
|
+
end
|
99
|
+
rescue
|
100
|
+
Incline::Log::warn "Failed to parse #{string.inspect}: #{$!.message}"
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
elsif string.respond_to?(:to_time)
|
105
|
+
begin
|
106
|
+
string.to_time
|
107
|
+
rescue
|
108
|
+
Incline::Log::warn "Failed to convert #{string.inspect} to time: #{$!.message}"
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
else
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
ActiveRecord::Type::DateTime.include Incline::Extensions::DateTimeValue
|
123
|
+
|