eac_rails_utils 0.8.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -0
  3. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper.rb +8 -1
  4. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder.rb +12 -2
  5. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/association_select_field.rb +5 -2
  6. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/common_text_fields.rb +4 -3
  7. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/currency_field.rb +14 -12
  8. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/date_field.rb +3 -1
  9. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/fields_for.rb +3 -1
  10. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/file_field.rb +2 -1
  11. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/radio_select_field.rb +5 -2
  12. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/searchable_association_field.rb +7 -3
  13. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/select_field.rb +3 -1
  14. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/time_field.rb +2 -1
  15. data/{lib/eac → app/helpers/eac_rails_utils}/common_form_helper/form_builder/year_month_field.rb +2 -1
  16. data/app/helpers/eac_rails_utils/data_table_helper.rb +13 -0
  17. data/{lib/eac → app/helpers/eac_rails_utils}/data_table_helper/column.rb +6 -3
  18. data/{lib/eac → app/helpers/eac_rails_utils}/data_table_helper/data_table.rb +13 -11
  19. data/{lib/eac → app/helpers/eac_rails_utils}/data_table_helper/setup.rb +3 -2
  20. data/app/helpers/eac_rails_utils/formatter_helper.rb +2 -0
  21. data/app/helpers/eac_rails_utils/links_helper.rb +12 -2
  22. data/{lib/eac → app/helpers/eac_rails_utils}/menus_helper.rb +10 -2
  23. data/{lib/eac → app/helpers/eac_rails_utils}/menus_helper/bootstrap_gui_builder.rb +8 -5
  24. data/{lib/eac → app/helpers/eac_rails_utils}/menus_helper/data_builder.rb +7 -2
  25. data/{lib/eac → app/helpers/eac_rails_utils}/menus_helper/gui_builder.rb +6 -3
  26. data/app/helpers/eac_rails_utils/open_graph_protocol_helper.rb +2 -0
  27. data/{lib/eac → app/validators/eac_rails_utils}/cpf_validator.rb +8 -4
  28. data/{lib/eac → app/validators/eac_rails_utils}/no_presence_validator.rb +3 -3
  29. data/lib/assets/javascripts/jMenu.jquery.min.js +12 -12
  30. data/lib/eac_rails_utils.rb +3 -41
  31. data/lib/eac_rails_utils/engine.rb +3 -0
  32. data/lib/{eac → eac_rails_utils}/htmlbeautifier.rb +3 -1
  33. data/lib/eac_rails_utils/models.rb +9 -0
  34. data/lib/eac_rails_utils/models/attribute_required.rb +43 -0
  35. data/lib/eac_rails_utils/models/fetch_errors.rb +92 -0
  36. data/lib/eac_rails_utils/models/inequality_queries.rb +39 -0
  37. data/lib/eac_rails_utils/models/tableless.rb +97 -0
  38. data/lib/eac_rails_utils/models/test_utils.rb +65 -0
  39. data/lib/eac_rails_utils/patches.rb +9 -0
  40. data/lib/eac_rails_utils/patches/action_controller_base.rb +3 -0
  41. data/lib/eac_rails_utils/version.rb +2 -1
  42. data/test/dummy/Rakefile +3 -1
  43. data/test/dummy/app/models/job.rb +2 -0
  44. data/test/dummy/app/models/user.rb +6 -0
  45. data/test/dummy/config.ru +2 -0
  46. data/test/dummy/config/application.rb +3 -1
  47. data/test/dummy/config/boot.rb +3 -1
  48. data/test/dummy/config/environment.rb +3 -1
  49. data/test/dummy/config/environments/test.rb +2 -0
  50. data/test/dummy/config/routes.rb +2 -0
  51. data/test/dummy/db/migrate/20160415125333_create_users.rb +2 -0
  52. data/test/dummy/db/migrate/20160415143123_create_jobs.rb +2 -0
  53. data/test/dummy/db/migrate/20160415143229_add_job_to_users.rb +2 -0
  54. data/test/{lib/eac → helpers/eac_rails_utils}/common_form_helper_test.rb +4 -2
  55. data/test/{lib/eac/data_table_test_helper.rb → helpers/eac_rails_utils/data_table_test_helper_test.rb} +4 -3
  56. data/test/{app/helpers → helpers}/eac_rails_utils/formatter_helper_test.rb +1 -0
  57. data/test/lib/eac_rails_utils/{patches/model_attribute_required_test.rb → models/attribute_required_test.rb} +3 -0
  58. data/test/lib/eac_rails_utils/models/fetch_errors_test.rb +80 -0
  59. data/test/lib/eac_rails_utils/models/tableless_test.rb +25 -0
  60. data/test/test_helper.rb +3 -1
  61. data/test/{lib/eac → validators}/cpf_validator_test.rb +4 -2
  62. metadata +91 -98
  63. data/lib/eac/data_table_helper.rb +0 -12
  64. data/lib/eac/inequality_queries.rb +0 -36
  65. data/lib/eac/model.rb +0 -87
  66. data/lib/eac/parsers/files_test.rb +0 -63
  67. data/lib/eac/source_target_fixtures.rb +0 -66
  68. data/lib/eac/test_utils.rb +0 -56
  69. data/lib/eac_rails_utils/patches/model_attribute_required.rb +0 -31
  70. data/lib/eac_rails_utils/patches/ofx_parser.rb +0 -42
  71. data/lib/eac_rails_utils/tableless_model.rb +0 -90
  72. data/test/lib/eac/model_test.rb +0 -76
  73. data/test/lib/eac/parsers/files_test_test.rb +0 -27
  74. data/test/lib/eac/parsers/ok_test_files/a.source.yaml +0 -1
  75. data/test/lib/eac/parsers/ok_test_files/a.target.yaml +0 -1
  76. data/test/lib/eac/parsers/ok_test_files/b.source.yaml +0 -1
  77. data/test/lib/eac/parsers/ok_test_files/b.target.yaml +0 -1
  78. data/test/lib/eac/source_target_fixtures_test.rb +0 -41
  79. data/test/lib/eac/source_target_fixtures_test_files/a.source.html +0 -1
  80. data/test/lib/eac/source_target_fixtures_test_files/a.target.yaml +0 -1
  81. data/test/lib/eac/source_target_fixtures_test_files/b.source.html +0 -1
  82. data/test/lib/eac/source_target_fixtures_test_files/c.target.yaml +0 -1
  83. data/test/lib/eac_rails_utils/tableless_model_test.rb +0 -23
@@ -1,4 +1,6 @@
1
- module Eac
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsUtils
2
4
  module MenusHelper
3
5
  # http://bootsnipp.com/snippets/featured/multi-level-dropdown-menu-bs3
4
6
  class BootstrapGuiBuilder
@@ -8,7 +10,8 @@ module Eac
8
10
  end
9
11
 
10
12
  def build(entries)
11
- fail "Argument \"entries\" is not a array" unless entries.is_a?(Array)
13
+ raise 'Argument "entries" is not a array' unless entries.is_a?(Array)
14
+
12
15
  @view.content_tag(:ul, class: "nav navbar-nav #{@options[:class]}".strip) do
13
16
  menu_entries(entries)
14
17
  end
@@ -28,12 +31,12 @@ module Eac
28
31
  elsif entry[:type] == :item
29
32
  menu_item(entry)
30
33
  else
31
- fail "Unknown menu entry type: \"#{entry[:type]}\""
34
+ raise "Unknown menu entry type: \"#{entry[:type]}\""
32
35
  end
33
36
  end
34
37
 
35
38
  def menu_group(entry)
36
- if entry[:level] == 0
39
+ if entry[:level].zero?
37
40
  menu_group_root(entry)
38
41
  else
39
42
  menu_group_sub(entry)
@@ -82,7 +85,7 @@ module Eac
82
85
  options[:method] = options[:link_method]
83
86
  options.delete(:link_method)
84
87
  end
85
- options[:class] = "#{@options[:button_class]}".strip if entry[:level] == 0
88
+ options[:class] = (@options[:button_class]).to_s.strip if entry[:level].zero?
86
89
  options
87
90
  end
88
91
  end
@@ -1,4 +1,6 @@
1
- module Eac
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsUtils
2
4
  module MenusHelper
3
5
  class DataBuilder
4
6
  def initialize(view)
@@ -12,7 +14,8 @@ module Eac
12
14
  private
13
15
 
14
16
  def build_entries(entries, level)
15
- fail 'Argument "entries" is not a hash' unless entries.is_a?(Hash)
17
+ raise 'Argument "entries" is not a hash' unless entries.is_a?(Hash)
18
+
16
19
  r = entries.map { |k, v| build_entry(k, v, level) }.select { |e| e }
17
20
  r.empty? ? nil : r
18
21
  end
@@ -28,12 +31,14 @@ module Eac
28
31
  def build_group(label, menu_entries, level)
29
32
  e = build_entries(menu_entries, level + 1)
30
33
  return nil unless e
34
+
31
35
  { type: :group, label: label, children: e, level: level }
32
36
  end
33
37
 
34
38
  def build_item(label, value, level)
35
39
  path, options = menu_item_options(value)
36
40
  return nil unless can_access_path?(path, options[:link_method])
41
+
37
42
  { type: :item, label: label, path: path, options: options, level: level }
38
43
  end
39
44
 
@@ -1,4 +1,6 @@
1
- module Eac
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsUtils
2
4
  module MenusHelper
3
5
  class GuiBuilder
4
6
  def initialize(view)
@@ -6,7 +8,8 @@ module Eac
6
8
  end
7
9
 
8
10
  def build(entries, options = {})
9
- fail "Argument \"entries\" is not a array" unless entries.is_a?(Array)
11
+ raise 'Argument "entries" is not a array' unless entries.is_a?(Array)
12
+
10
13
  @view.content_tag(:ul, options) do
11
14
  b = ActiveSupport::SafeBuffer.new
12
15
  entries.map { |v| menu_entry(v) }.each { |e| b << e }
@@ -22,7 +25,7 @@ module Eac
22
25
  elsif entry[:type] == :item
23
26
  menu_item(entry[:label], entry[:path], entry[:options])
24
27
  else
25
- fail "Unknown menu entry type: \"#{entry[:type]}\""
28
+ raise "Unknown menu entry type: \"#{entry[:type]}\""
26
29
  end
27
30
  end
28
31
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module EacRailsUtils
3
4
  module OpenGraphProtocolHelper
4
5
  OGP_META_DEFAULT_PREFIX = 'og'
@@ -89,6 +90,7 @@ module EacRailsUtils
89
90
 
90
91
  def tag
91
92
  return ::ActiveSupport::SafeBuffer.new unless content?
93
+
92
94
  view.tag(:meta, prefix: view.ogp_prefix, property: property_value, content: content)
93
95
  end
94
96
  end
@@ -1,7 +1,10 @@
1
- module Eac
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsUtils
2
4
  class CpfValidator < ActiveModel::EachValidator
3
5
  def validate_each(record, attribute, value)
4
6
  return if Cpf.new(value).valid?
7
+
5
8
  record.errors[attribute] << (options[:message] ||
6
9
  'CPF inválido (9 caracteres, somente dígitos)')
7
10
  end
@@ -13,6 +16,7 @@ module Eac
13
16
 
14
17
  def valid?
15
18
  return false if input_invalid?
19
+
16
20
  digito_verificador1_calculo == values[9] && digito_verificador2_calculo == values[10]
17
21
  end
18
22
 
@@ -25,8 +29,8 @@ module Eac
25
29
  end
26
30
 
27
31
  def null?
28
- %w(12345678909 11111111111 22222222222 33333333333 44444444444 55555555555
29
- 66666666666 77777777777 88888888888 99999999999 00000000000).member?(digits.join)
32
+ %w[12345678909 11111111111 22222222222 33333333333 44444444444 55555555555
33
+ 66666666666 77777777777 88888888888 99999999999 00000000000].member?(digits.join)
30
34
  end
31
35
 
32
36
  def digits
@@ -53,7 +57,7 @@ module Eac
53
57
  c -= 1
54
58
  end
55
59
  s -= (11 * (s / 11))
56
- (s == 0 || s == 1) ? 0 : 11 - s
60
+ [0, 1].include?(s) ? 0 : 11 - s
57
61
  end
58
62
  end
59
63
  end
@@ -1,11 +1,11 @@
1
-
2
-
3
1
  # frozen_string_literal: true
4
- module Eac
2
+
3
+ module EacRailsUtils
5
4
  # https://stackoverflow.com/questions/10070786/rails-3-validation-presence-false
6
5
  class NoPresenceValidator < ActiveModel::EachValidator
7
6
  def validate_each(record, attribute, _value)
8
7
  return if record.send(attribute).blank?
8
+
9
9
  record.errors[attribute] << (options[:message] || 'must be blank')
10
10
  end
11
11
  end
@@ -1,12 +1,12 @@
1
- /************************************************************************
2
- *************************************************************************
3
- @Name : jMenu - jQuery Plugin
4
- @Revison : 2.0
5
- @Date : 08/2013
6
- @Author : ALPIXEL - (www.myjqueryplugins.com - www.alpixel.fr)
7
- @Support : FF, IE7, IE8, MAC Firefox, MAC Safari
8
- @License : Open Source - MIT License : http://www.opensource.org/licenses/mit-license.php
9
-
10
- **************************************************************************
11
- *************************************************************************/
12
- (function(e){e.jMenu={defaults:{ulWidth:"auto",absoluteTop:33,absoluteLeft:0,TimeBeforeOpening:100,TimeBeforeClosing:100,animatedText:true,paddingLeft:7,openClick:false,effects:{effectSpeedOpen:150,effectSpeedClose:150,effectTypeOpen:"slide",effectTypeClose:"slide",effectOpen:"swing",effectClose:"swing"}},init:function(t){opts=e.extend({},e.jMenu.defaults,t);if(opts.ulWidth=="auto")$width=e(".fNiv").outerWidth(false);else $width=opts.ulWidth;e(".jMenu li").each(function(){var t=e(this).find("a:first"),n=e(this).find("ul");if(e.jMenu._IsParent(t)){t.addClass("isParent");var r=t.next(),i=t.position();if(e(this).hasClass("jmenu-level-0"))r.css({top:i.top+opts.absoluteTop,left:i.left+opts.absoluteLeft,width:$width});else r.css({top:i.top,left:i.left+$width,width:$width});if(!opts.openClick)e(this).bind({mouseenter:function(){if(e(this).hasClass("jmenu-level-0")){i=e(this).position();r.css({left:i.left+opts.absoluteLeft,top:i.top+opts.absoluteTop})}e.jMenu._show(r)},mouseleave:function(){e.jMenu._closeList(r)}});else e(this).bind({click:function(t){t.preventDefault();e.jMenu._show(r)},mouseleave:function(){e.jMenu._closeList(r)}})}})},_show:function(e){switch(opts.effects.effectTypeOpen){case"slide":e.stop(true,true).delay(opts.TimeBeforeOpening).slideDown(opts.effects.effectSpeedOpen,opts.effects.effectOpen);break;case"fade":e.stop(true,true).delay(opts.TimeBeforeOpening).fadeIn(opts.effects.effectSpeedOpen,opts.effects.effectOpen);break;default:e.stop(true,true).delay(opts.TimeBeforeOpening).show()}},_closeList:function(e){switch(opts.effects.effectTypeClose){case"slide":e.stop(true,true).delay(opts.TimeBeforeClosing).slideUp(opts.effects.effectSpeedClose,opts.effects.effectClose);break;case"fade":e.stop(true,true).delay(opts.TimeBeforeClosing).fadeOut(opts.effects.effectSpeedClose,opts.effects.effectClose);break;default:e.delay(opts.TimeBeforeClosing).hide()}},_animateText:function(t){var n=parseInt(t.css("padding-left"));t.hover(function(){e(this).stop(true,false).animate({paddingLeft:n+opts.paddingLeft},100)},function(){e(this).stop(true,false).animate({paddingLeft:n},100)})},_IsParent:function(e){if(e.next().is("ul"))return true;else return false},_isReadable:function(){if(e(".jmenu-level-0").length>0)return true;else return false},_error:function(){alert("jMenu plugin can't be initialized. Please, check you have the '.jmenu-level-0' class on your first level <li> elements.")}};jQuery.fn.jMenu=function(t){e(this).addClass("jMenu");e(this).children("li").addClass("jmenu-level-0").children("a").addClass("fNiv");if(e.jMenu._isReadable()){e.jMenu.init(t)}else{e.jMenu._error()}}})(jQuery)
1
+ /************************************************************************
2
+ *************************************************************************
3
+ @Name : jMenu - jQuery Plugin
4
+ @Revison : 2.0
5
+ @Date : 08/2013
6
+ @Author : ALPIXEL - (www.myjqueryplugins.com - www.alpixel.fr)
7
+ @Support : FF, IE7, IE8, MAC Firefox, MAC Safari
8
+ @License : Open Source - MIT License : http://www.opensource.org/licenses/mit-license.php
9
+
10
+ **************************************************************************
11
+ *************************************************************************/
12
+ (function(e){e.jMenu={defaults:{ulWidth:"auto",absoluteTop:33,absoluteLeft:0,TimeBeforeOpening:100,TimeBeforeClosing:100,animatedText:true,paddingLeft:7,openClick:false,effects:{effectSpeedOpen:150,effectSpeedClose:150,effectTypeOpen:"slide",effectTypeClose:"slide",effectOpen:"swing",effectClose:"swing"}},init:function(t){opts=e.extend({},e.jMenu.defaults,t);if(opts.ulWidth=="auto")$width=e(".fNiv").outerWidth(false);else $width=opts.ulWidth;e(".jMenu li").each(function(){var t=e(this).find("a:first"),n=e(this).find("ul");if(e.jMenu._IsParent(t)){t.addClass("isParent");var r=t.next(),i=t.position();if(e(this).hasClass("jmenu-level-0"))r.css({top:i.top+opts.absoluteTop,left:i.left+opts.absoluteLeft,width:$width});else r.css({top:i.top,left:i.left+$width,width:$width});if(!opts.openClick)e(this).bind({mouseenter:function(){if(e(this).hasClass("jmenu-level-0")){i=e(this).position();r.css({left:i.left+opts.absoluteLeft,top:i.top+opts.absoluteTop})}e.jMenu._show(r)},mouseleave:function(){e.jMenu._closeList(r)}});else e(this).bind({click:function(t){t.preventDefault();e.jMenu._show(r)},mouseleave:function(){e.jMenu._closeList(r)}})}})},_show:function(e){switch(opts.effects.effectTypeOpen){case"slide":e.stop(true,true).delay(opts.TimeBeforeOpening).slideDown(opts.effects.effectSpeedOpen,opts.effects.effectOpen);break;case"fade":e.stop(true,true).delay(opts.TimeBeforeOpening).fadeIn(opts.effects.effectSpeedOpen,opts.effects.effectOpen);break;default:e.stop(true,true).delay(opts.TimeBeforeOpening).show()}},_closeList:function(e){switch(opts.effects.effectTypeClose){case"slide":e.stop(true,true).delay(opts.TimeBeforeClosing).slideUp(opts.effects.effectSpeedClose,opts.effects.effectClose);break;case"fade":e.stop(true,true).delay(opts.TimeBeforeClosing).fadeOut(opts.effects.effectSpeedClose,opts.effects.effectClose);break;default:e.delay(opts.TimeBeforeClosing).hide()}},_animateText:function(t){var n=parseInt(t.css("padding-left"));t.hover(function(){e(this).stop(true,false).animate({paddingLeft:n+opts.paddingLeft},100)},function(){e(this).stop(true,false).animate({paddingLeft:n},100)})},_IsParent:function(e){if(e.next().is("ul"))return true;else return false},_isReadable:function(){if(e(".jmenu-level-0").length>0)return true;else return false},_error:function(){alert("jMenu plugin can't be initialized. Please, check you have the '.jmenu-level-0' class on your first level <li> elements.")}};jQuery.fn.jMenu=function(t){e(this).addClass("jMenu");e(this).children("li").addClass("jmenu-level-0").children("a").addClass("fNiv");if(e.jMenu._isReadable()){e.jMenu.init(t)}else{e.jMenu._error()}}})(jQuery)
@@ -1,45 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'active_support/dependencies'
3
2
 
4
- module EacRailsUtils
5
- require 'activemodel/associations'
6
- require 'nested_form_fields'
7
- require 'ofx-parser'
8
- require 'virtus'
9
-
10
- require 'eac_rails_utils/patches/action_controller_base'
11
- require 'eac_rails_utils/patches/model_attribute_required'
12
- require 'eac_rails_utils/patches/ofx_parser'
13
- require 'eac_rails_utils/engine'
14
- require 'eac_rails_utils/tableless_model'
15
- require 'eac/cpf_validator'
16
- require 'eac/common_form_helper/form_builder/association_select_field'
17
- require 'eac/common_form_helper/form_builder/common_text_fields'
18
- require 'eac/common_form_helper/form_builder/currency_field'
19
- require 'eac/common_form_helper/form_builder/date_field'
20
- require 'eac/common_form_helper/form_builder/fields_for'
21
- require 'eac/common_form_helper/form_builder/file_field'
22
- require 'eac/common_form_helper/form_builder/radio_select_field'
23
- require 'eac/common_form_helper/form_builder/searchable_association_field'
24
- require 'eac/common_form_helper/form_builder/select_field'
25
- require 'eac/common_form_helper/form_builder/time_field'
26
- require 'eac/common_form_helper/form_builder/year_month_field'
27
- require 'eac/common_form_helper/form_builder'
28
- require 'eac/common_form_helper'
29
- require 'eac/data_table_helper'
30
- require 'eac/htmlbeautifier'
31
- require 'eac/inequality_queries'
32
- require 'eac/menus_helper'
33
- require 'eac/menus_helper/bootstrap_gui_builder'
34
- require 'eac/menus_helper/data_builder'
35
- require 'eac/menus_helper/gui_builder'
36
- require 'eac/model'
37
- require 'eac/no_presence_validator'
38
- require 'eac/parsers/files_test'
39
- require 'eac/source_target_fixtures'
40
- require 'eac/test_utils'
3
+ require 'eac_ruby_utils/require_sub'
41
4
 
42
- ActionView::Base.send :include, Eac::CommonFormHelper
43
- ActionView::Base.send :include, Eac::DataTableHelper
44
- ActionView::Base.send :include, Eac::MenusHelper
5
+ module EacRailsUtils
6
+ ::EacRubyUtils.require_sub __FILE__
45
7
  end
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require 'nested_form_fields'
4
+
2
5
  module EacRailsUtils
3
6
  class Engine < ::Rails::Engine; end
4
7
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'htmlbeautifier'
2
4
 
3
- module Eac
5
+ module EacRailsUtils
4
6
  class Htmlbeautifier
5
7
  def self.beautify(string)
6
8
  ::HtmlBeautifier.beautify(string, tab_stops: 2) + "\n"
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/require_sub'
4
+
5
+ module EacRailsUtils
6
+ module Models
7
+ ::EacRubyUtils.require_sub __FILE__
8
+ end
9
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module EacRailsUtils
6
+ module Models
7
+ module AttributeRequired
8
+ extend ::ActiveSupport::Concern
9
+
10
+ class << self
11
+ def required?(model_class_or_record, attribute)
12
+ model = model_class_or_record_to_model(model_class_or_record)
13
+ record = model.new
14
+ record.validate
15
+ record.errors.key?(attribute.to_sym)
16
+ end
17
+
18
+ private
19
+
20
+ def model_class_or_record_to_model(model_class_or_record)
21
+ model_class_or_record.is_a?(::Class) ? model_class_or_record : model_class_or_record.class
22
+ end
23
+ end
24
+
25
+ included do
26
+ extend ClassMethods
27
+ include InstanceMethods
28
+ end
29
+
30
+ module ClassMethods
31
+ def column_required?(column)
32
+ ::EacRailsUtils::Models::AttributeRequired.required?(self, column)
33
+ end
34
+ end
35
+
36
+ module InstanceMethods
37
+ def attribute_required?(column)
38
+ self.class.column_required?(column)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsUtils
4
+ module Models
5
+ module FetchErrors
6
+ # Adiciona as mensagens de erro de record. As mensagens de uma coluna X em record
7
+ # serão adicionadas na coluna X em self. Se options[:default_column] for especificado
8
+ # as mensagens da coluna X de record em que X não existe em self serão adicionadas
9
+ # na coluna options[:default_column].
10
+ # Um array de colunas pode ser passado em options[:skip] de colunas em record que não
11
+ # terão suas falhas adicionadas.
12
+ def fetch_record_errors(record, options = {})
13
+ record.errors.keys.each do |column|
14
+ fetch_column_errors(record, column, column, options)
15
+ end
16
+ end
17
+
18
+ # Similar a fetch_record_errors, mas torna possível especificar, através de mapping,
19
+ # colunas-alvo em self com nomes diferentes das colunas-fonte em record.
20
+ # mapping tem o formato { record_column => self_column }.
21
+ def fetch_record_errors_by_mapping(record, mapping, options = {})
22
+ mapping.each do |record_column, self_column|
23
+ fetch_column_errors(record, record_column, self_column, options)
24
+ end
25
+ end
26
+
27
+ def fetch_column_errors(record, record_column, self_column, options = {})
28
+ return if options[:skip]&.include?(record_column)
29
+
30
+ record.errors[record_column].each do |message|
31
+ fetch_error_column_message(self_column, message, options[:default_column],
32
+ "#{record.class.human_attribute_name(record_column)}: ")
33
+ end
34
+ end
35
+
36
+ # Verifica se uma coluna existe.
37
+ def column?(column)
38
+ respond_to?(column) && respond_to?("#{column}=")
39
+ end
40
+
41
+ def save_or_raise
42
+ raise "Falha ao tentar salvar #{self.class.name}: #{errors_to_string}" unless save
43
+
44
+ self
45
+ end
46
+
47
+ private
48
+
49
+ def fetch_error_column_message(column, message, default_column, default_column_message_prefix)
50
+ build_self_columns_messages(column, message, default_column,
51
+ default_column_message_prefix).each do |k, v|
52
+ if column?(k)
53
+ add_error_message(k, v)
54
+ break
55
+ end
56
+ end
57
+ end
58
+
59
+ # Adiciona uma mensagem de erro a uma coluna somente se a coluna
60
+ # ainda não a possui
61
+ def add_error_message(column, message)
62
+ return if errors[column].include?(message)
63
+
64
+ errors.add(column, message)
65
+ end
66
+
67
+ # Produz uma lista de campos-mensagens, em ordem de preferência,
68
+ # que podem receber uma mensagem de falha.
69
+ def build_self_columns_messages(column, message, default_column,
70
+ default_column_message_prefix)
71
+ r = { column => message }
72
+ m = /^(.+)_id$/.match(column)
73
+ if m
74
+ r[m[1]] = message
75
+ else
76
+ r["#{column}_id"] = message
77
+ end
78
+ r[default_column] = "#{default_column_message_prefix}#{message}" if default_column
79
+ r
80
+ end
81
+
82
+ def errors_to_string
83
+ b = ''
84
+ errors.messages.each do |field, messages|
85
+ b += ' / ' if b != ''
86
+ b += field.to_s + ': ' + messages.to_s
87
+ end
88
+ b
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsUtils
4
+ module Models
5
+ # == Example:
6
+ #
7
+ # Note: model Product has a attribute "foo" Date, Time or Number:
8
+ #
9
+ # class Product
10
+ # include ::EacRailsUtils::Models::InequalityQueries
11
+ #
12
+ # add_inequality_queries(:foo)
13
+ # end
14
+ #
15
+ # This add the following scopes:
16
+ #
17
+ # Product.by_foo_gt(value) # Equivalent to Product.where("foo > ?", value)
18
+ # Product.by_foo_gteq(value) # Equivalent to Product.where("foo >= ?", value)
19
+ # Product.by_foo_lt(value) # Equivalent to Product.where("foo < ?", value)
20
+ # Product.by_foo_lteq(value) # Equivalent to Product.where("foo <= ?", value)
21
+ module InequalityQueries
22
+ class << self
23
+ def included(base)
24
+ base.extend(ClassMethods)
25
+ end
26
+ end
27
+
28
+ module ClassMethods
29
+ def add_inequality_queries(attribute)
30
+ %w[gt gteq lt lteq].each do |ineq|
31
+ scope "by_#{attribute}_#{ineq}", lambda { |v|
32
+ where(arel_table[attribute].send(ineq, v))
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end