incline 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +186 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +208 -0
  7. data/Rakefile +37 -0
  8. data/app/assets/fonts/incline/.keep +0 -0
  9. data/app/assets/images/incline/.keep +0 -0
  10. data/app/assets/images/incline/barcode-B.svg +181 -0
  11. data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
  12. data/app/assets/javascripts/incline/application.js +30 -0
  13. data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
  14. data/app/assets/javascripts/incline/datatables.js +22193 -0
  15. data/app/assets/javascripts/incline/escapeHtml.js +10 -0
  16. data/app/assets/javascripts/incline/inline_actions.js +479 -0
  17. data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
  18. data/app/assets/javascripts/incline/jquery.number.js +764 -0
  19. data/app/assets/javascripts/incline/regexMask.js +27 -0
  20. data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
  21. data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
  22. data/app/assets/stylesheets/incline/application.css +18 -0
  23. data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
  24. data/app/assets/stylesheets/incline/custom.scss +279 -0
  25. data/app/assets/stylesheets/incline/datatables.css +494 -0
  26. data/app/assets/stylesheets/incline/datepicker3.css +790 -0
  27. data/app/assets/stylesheets/incline/select2.css +484 -0
  28. data/app/controllers/incline/access_groups_controller.rb +127 -0
  29. data/app/controllers/incline/access_test_controller.rb +30 -0
  30. data/app/controllers/incline/account_activations_controller.rb +28 -0
  31. data/app/controllers/incline/application_controller.rb +11 -0
  32. data/app/controllers/incline/contact_controller.rb +34 -0
  33. data/app/controllers/incline/password_resets_controller.rb +113 -0
  34. data/app/controllers/incline/security_controller.rb +100 -0
  35. data/app/controllers/incline/sessions_controller.rb +50 -0
  36. data/app/controllers/incline/users_controller.rb +304 -0
  37. data/app/controllers/incline/welcome_controller.rb +19 -0
  38. data/app/helpers/incline/.keep +0 -0
  39. data/app/mailers/incline/application_mailer_base.rb +11 -0
  40. data/app/mailers/incline/contact_form.rb +19 -0
  41. data/app/mailers/incline/user_mailer.rb +45 -0
  42. data/app/models/incline/access_group.rb +121 -0
  43. data/app/models/incline/access_group_group_member.rb +12 -0
  44. data/app/models/incline/access_group_user_member.rb +10 -0
  45. data/app/models/incline/action_group.rb +12 -0
  46. data/app/models/incline/action_security.rb +222 -0
  47. data/app/models/incline/contact_message.rb +37 -0
  48. data/app/models/incline/disable_info.rb +20 -0
  49. data/app/models/incline/password_reset.rb +14 -0
  50. data/app/models/incline/password_reset_request.rb +14 -0
  51. data/app/models/incline/user.rb +437 -0
  52. data/app/models/incline/user_login_history.rb +30 -0
  53. data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
  54. data/app/views/incline/access_groups/_form.html.erb +19 -0
  55. data/app/views/incline/access_groups/_list.html.erb +60 -0
  56. data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
  57. data/app/views/incline/access_groups/edit.html.erb +2 -0
  58. data/app/views/incline/access_groups/index.html.erb +6 -0
  59. data/app/views/incline/access_groups/index.json.jbuilder +16 -0
  60. data/app/views/incline/access_groups/new.html.erb +2 -0
  61. data/app/views/incline/access_groups/show.html.erb +9 -0
  62. data/app/views/incline/access_groups/show.json.jbuilder +11 -0
  63. data/app/views/incline/contact/new.html.erb +22 -0
  64. data/app/views/incline/contact_form/contact.html.erb +16 -0
  65. data/app/views/incline/contact_form/contact.text.erb +13 -0
  66. data/app/views/incline/password_resets/edit.html.erb +16 -0
  67. data/app/views/incline/password_resets/new.html.erb +12 -0
  68. data/app/views/incline/security/_details.json.jbuilder +7 -0
  69. data/app/views/incline/security/_form.html.erb +20 -0
  70. data/app/views/incline/security/_list.html.erb +89 -0
  71. data/app/views/incline/security/_messages.json.jbuilder +6 -0
  72. data/app/views/incline/security/edit.html.erb +2 -0
  73. data/app/views/incline/security/index.html.erb +6 -0
  74. data/app/views/incline/security/index.json.jbuilder +16 -0
  75. data/app/views/incline/security/show.html.erb +31 -0
  76. data/app/views/incline/security/show.json.jbuilder +11 -0
  77. data/app/views/incline/sessions/new.html.erb +26 -0
  78. data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
  79. data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
  80. data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
  81. data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
  82. data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
  83. data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
  84. data/app/views/incline/users/_details.json.jbuilder +32 -0
  85. data/app/views/incline/users/_form.html.erb +21 -0
  86. data/app/views/incline/users/_list.html.erb +102 -0
  87. data/app/views/incline/users/_messages.json.jbuilder +6 -0
  88. data/app/views/incline/users/disable_confirm.html.erb +19 -0
  89. data/app/views/incline/users/edit.html.erb +5 -0
  90. data/app/views/incline/users/index.html.erb +6 -0
  91. data/app/views/incline/users/index.json.jbuilder +16 -0
  92. data/app/views/incline/users/new.html.erb +5 -0
  93. data/app/views/incline/users/show.html.erb +12 -0
  94. data/app/views/incline/users/show.json.jbuilder +11 -0
  95. data/app/views/incline/welcome/home.html.erb +5 -0
  96. data/app/views/layouts/application.html.erb +1 -0
  97. data/app/views/layouts/incline/_account_menu.html.erb +18 -0
  98. data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  99. data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  100. data/app/views/layouts/incline/_footer.html.erb +13 -0
  101. data/app/views/layouts/incline/_header.html.erb +21 -0
  102. data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
  103. data/app/views/layouts/incline/_incline_app.html.erb +25 -0
  104. data/app/views/layouts/incline/_messages.html.erb +3 -0
  105. data/app/views/layouts/incline/_shim.html.erb +3 -0
  106. data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
  107. data/app/views/layouts/incline/application.html.erb +1 -0
  108. data/app/views/layouts/mailer.html.erb +2 -0
  109. data/app/views/layouts/mailer.text.erb +2 -0
  110. data/bin/rails +12 -0
  111. data/bin/test_scaffold.sh +10 -0
  112. data/config/routes.rb +61 -0
  113. data/db/migrate/20170511230126_create_incline_users.rb +26 -0
  114. data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
  115. data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
  116. data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
  117. data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
  118. data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
  119. data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
  120. data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
  121. data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
  122. data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
  123. data/db/seeds.rb +81 -0
  124. data/exe/new_incline_app +42 -0
  125. data/lib/generators/incline/install_generator.rb +259 -0
  126. data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
  127. data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
  128. data/lib/generators/incline/templates/incline_application.css +17 -0
  129. data/lib/generators/incline/templates/incline_application.html.erb +1 -0
  130. data/lib/generators/incline/templates/incline_application.js +12 -0
  131. data/lib/generators/incline/templates/incline_database.yml +25 -0
  132. data/lib/generators/incline/templates/incline_email.yml +20 -0
  133. data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
  134. data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
  135. data/lib/generators/incline/templates/incline_users.yml +64 -0
  136. data/lib/generators/incline/templates/incline_version.rb +3 -0
  137. data/lib/incline/auth_engine_base.rb +52 -0
  138. data/lib/incline/data_tables_request.rb +336 -0
  139. data/lib/incline/date_time_formats.rb +6 -0
  140. data/lib/incline/engine.rb +212 -0
  141. data/lib/incline/errors.rb +15 -0
  142. data/lib/incline/extensions/action_controller_base.rb +526 -0
  143. data/lib/incline/extensions/action_mailer_base.rb +66 -0
  144. data/lib/incline/extensions/action_view_base.rb +489 -0
  145. data/lib/incline/extensions/active_record_base.rb +308 -0
  146. data/lib/incline/extensions/application.rb +137 -0
  147. data/lib/incline/extensions/application_configuration.rb +50 -0
  148. data/lib/incline/extensions/connection_adapter.rb +55 -0
  149. data/lib/incline/extensions/date_time_value.rb +123 -0
  150. data/lib/incline/extensions/date_value.rb +77 -0
  151. data/lib/incline/extensions/decimal_value.rb +55 -0
  152. data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
  153. data/lib/incline/extensions/float_value.rb +59 -0
  154. data/lib/incline/extensions/form_builder.rb +617 -0
  155. data/lib/incline/extensions/integer_value.rb +54 -0
  156. data/lib/incline/extensions/jbuilder_generator.rb +38 -0
  157. data/lib/incline/extensions/jbuilder_template.rb +39 -0
  158. data/lib/incline/extensions/main_app.rb +40 -0
  159. data/lib/incline/extensions/numeric.rb +63 -0
  160. data/lib/incline/extensions/object.rb +31 -0
  161. data/lib/incline/extensions/resource_route_generator.rb +53 -0
  162. data/lib/incline/extensions/session.rb +113 -0
  163. data/lib/incline/extensions/string.rb +50 -0
  164. data/lib/incline/extensions/test_case.rb +764 -0
  165. data/lib/incline/extensions/time_zone_converter.rb +40 -0
  166. data/lib/incline/global_status.rb +236 -0
  167. data/lib/incline/helpers/route_hash_formatter.rb +46 -0
  168. data/lib/incline/json_log_formatter.rb +96 -0
  169. data/lib/incline/json_logger.rb +17 -0
  170. data/lib/incline/log.rb +153 -0
  171. data/lib/incline/number_formats.rb +17 -0
  172. data/lib/incline/recaptcha.rb +346 -0
  173. data/lib/incline/user_manager.rb +212 -0
  174. data/lib/incline/validators/email_validator.rb +45 -0
  175. data/lib/incline/validators/ip_address_validator.rb +32 -0
  176. data/lib/incline/validators/recaptcha_validator.rb +37 -0
  177. data/lib/incline/validators/safe_name_validator.rb +31 -0
  178. data/lib/incline/version.rb +3 -0
  179. data/lib/incline/work_path.rb +75 -0
  180. data/lib/incline.rb +197 -0
  181. data/lib/tasks/incline_tasks.rake +4 -0
  182. data/lib/templates/erb/scaffold/_form.html.erb +43 -0
  183. data/lib/templates/erb/scaffold/_list.html.erb +81 -0
  184. data/lib/templates/erb/scaffold/edit.html.erb +1 -0
  185. data/lib/templates/erb/scaffold/index.html.erb +6 -0
  186. data/lib/templates/erb/scaffold/new.html.erb +1 -0
  187. data/lib/templates/erb/scaffold/show.html.erb +34 -0
  188. data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
  189. data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
  190. data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
  191. data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
  192. data/test/controllers/incline/access_groups_controller_test.rb +65 -0
  193. data/test/controllers/incline/access_test_controller_test.rb +53 -0
  194. data/test/controllers/incline/contact_controller_test.rb +32 -0
  195. data/test/controllers/incline/security_controller_test.rb +39 -0
  196. data/test/controllers/incline/welcome_controller_test.rb +16 -0
  197. data/test/dummy/README.rdoc +28 -0
  198. data/test/dummy/Rakefile +6 -0
  199. data/test/dummy/app/assets/images/.keep +0 -0
  200. data/test/dummy/app/assets/javascripts/application.js +12 -0
  201. data/test/dummy/app/assets/stylesheets/application.css +17 -0
  202. data/test/dummy/app/controllers/application_controller.rb +5 -0
  203. data/test/dummy/app/controllers/concerns/.keep +0 -0
  204. data/test/dummy/app/helpers/application_helper.rb +2 -0
  205. data/test/dummy/app/mailers/.keep +0 -0
  206. data/test/dummy/app/models/.keep +0 -0
  207. data/test/dummy/app/models/concerns/.keep +0 -0
  208. data/test/dummy/app/views/layouts/application.html.erb +1 -0
  209. data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  210. data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  211. data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
  212. data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
  213. data/test/dummy/bin/bundle +3 -0
  214. data/test/dummy/bin/rails +4 -0
  215. data/test/dummy/bin/rake +4 -0
  216. data/test/dummy/bin/setup +29 -0
  217. data/test/dummy/config/application.rb +38 -0
  218. data/test/dummy/config/boot.rb +5 -0
  219. data/test/dummy/config/database.yml +34 -0
  220. data/test/dummy/config/email.yml +24 -0
  221. data/test/dummy/config/environment.rb +5 -0
  222. data/test/dummy/config/environments/development.rb +45 -0
  223. data/test/dummy/config/environments/production.rb +85 -0
  224. data/test/dummy/config/environments/test.rb +44 -0
  225. data/test/dummy/config/initializers/assets.rb +11 -0
  226. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  227. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  228. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  229. data/test/dummy/config/initializers/inflections.rb +16 -0
  230. data/test/dummy/config/initializers/mime_types.rb +4 -0
  231. data/test/dummy/config/initializers/session_store.rb +3 -0
  232. data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  233. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  234. data/test/dummy/config/locales/en.yml +23 -0
  235. data/test/dummy/config/routes.rb +6 -0
  236. data/test/dummy/config.ru +4 -0
  237. data/test/dummy/db/schema.rb +108 -0
  238. data/test/dummy/lib/assets/.keep +0 -0
  239. data/test/dummy/log/.keep +0 -0
  240. data/test/dummy/public/404.html +67 -0
  241. data/test/dummy/public/422.html +67 -0
  242. data/test/dummy/public/500.html +66 -0
  243. data/test/dummy/public/favicon.ico +0 -0
  244. data/test/extensions/action_controller_base_extensions_test.rb +21 -0
  245. data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
  246. data/test/extensions/action_view_base_extensions_test.rb +267 -0
  247. data/test/extensions/active_record_extensions_test.rb +173 -0
  248. data/test/extensions/application_configuration_extensions_test.rb +46 -0
  249. data/test/extensions/application_extensions_test.rb +23 -0
  250. data/test/extensions/connection_adapter_extensions_test.rb +54 -0
  251. data/test/extensions/date_time_value_extensions_test.rb +104 -0
  252. data/test/extensions/date_value_extensions_test.rb +102 -0
  253. data/test/extensions/decimal_value_extensions_test.rb +85 -0
  254. data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
  255. data/test/extensions/float_value_extensions_test.rb +78 -0
  256. data/test/extensions/form_builder_extensions_test.rb +28 -0
  257. data/test/extensions/integer_value_extensions_test.rb +78 -0
  258. data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
  259. data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
  260. data/test/extensions/main_app_extensions_test.rb +55 -0
  261. data/test/extensions/numeric_extensions_test.rb +76 -0
  262. data/test/extensions/object_extensions_test.rb +104 -0
  263. data/test/extensions/session_extensions_test.rb +69 -0
  264. data/test/extensions/string_extensions_test.rb +32 -0
  265. data/test/extensions/test_case_extensions_test.rb +538 -0
  266. data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
  267. data/test/fixtures/incline/access_group_group_members.yml +1 -0
  268. data/test/fixtures/incline/access_group_user_members.yml +1 -0
  269. data/test/fixtures/incline/access_groups.yml +13 -0
  270. data/test/fixtures/incline/action_groups.yml +6 -0
  271. data/test/fixtures/incline/action_securities.yml +18 -0
  272. data/test/fixtures/incline/user_login_histories.yml +1 -0
  273. data/test/fixtures/incline/users.yml +64 -0
  274. data/test/incline_test.rb +63 -0
  275. data/test/integration/incline/users_edit_test.rb +180 -0
  276. data/test/integration/incline/users_login_test.rb +105 -0
  277. data/test/integration/incline/users_signup_test.rb +147 -0
  278. data/test/integration/navigation_test.rb +11 -0
  279. data/test/lib/data_tables_request_test.rb +245 -0
  280. data/test/lib/date_time_formats_test.rb +111 -0
  281. data/test/lib/global_status_test.rb +89 -0
  282. data/test/lib/json_log_formatter_test.rb +43 -0
  283. data/test/lib/log_test.rb +36 -0
  284. data/test/lib/recaptcha_test.rb +75 -0
  285. data/test/lib/user_manager_test.rb +47 -0
  286. data/test/lib/work_path_test.rb +18 -0
  287. data/test/models/incline/access_group_group_member_test.rb +30 -0
  288. data/test/models/incline/access_group_test.rb +60 -0
  289. data/test/models/incline/access_group_user_member_test.rb +29 -0
  290. data/test/models/incline/action_group_test.rb +27 -0
  291. data/test/models/incline/action_security_test.rb +176 -0
  292. data/test/models/incline/contact_message_test.rb +66 -0
  293. data/test/models/incline/disable_info_test.rb +29 -0
  294. data/test/models/incline/password_reset_request_test.rb +35 -0
  295. data/test/models/incline/password_reset_test.rb +51 -0
  296. data/test/models/incline/user_login_history_test.rb +31 -0
  297. data/test/models/incline/user_test.rb +91 -0
  298. data/test/test_helper.rb +42 -0
  299. data/test/validators/email_validator_test.rb +102 -0
  300. data/test/validators/ip_address_validator_test.rb +107 -0
  301. data/test/validators/recaptcha_validator_test.rb +57 -0
  302. data/test/validators/safe_name_validator_test.rb +101 -0
  303. 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 &copy; #{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
+