eac_rails_utils 0.0.1

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 (57) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +18 -0
  3. data/lib/assets/javascripts/currency_field.js +21 -0
  4. data/lib/assets/javascripts/eac_rails_utils.js +6 -0
  5. data/lib/assets/javascripts/input_searchable.js +78 -0
  6. data/lib/assets/javascripts/jMenu.jquery.min.js +12 -0
  7. data/lib/assets/javascripts/jquery.maskMoney.js +409 -0
  8. data/lib/assets/stylesheets/autocomplete.scss +33 -0
  9. data/lib/assets/stylesheets/bootstrap3-dropdown.scss +47 -0
  10. data/lib/assets/stylesheets/eac_rails_utils.scss +44 -0
  11. data/lib/assets/stylesheets/jmenu.scss +78 -0
  12. data/lib/eac/common_form_helper.rb +37 -0
  13. data/lib/eac/common_form_helper/form_builder.rb +88 -0
  14. data/lib/eac/common_form_helper/form_builder/association_select_field.rb +40 -0
  15. data/lib/eac/common_form_helper/form_builder/common_text_fields.rb +18 -0
  16. data/lib/eac/common_form_helper/form_builder/currency_field.rb +39 -0
  17. data/lib/eac/common_form_helper/form_builder/date_field.rb +20 -0
  18. data/lib/eac/common_form_helper/form_builder/fields_for.rb +44 -0
  19. data/lib/eac/common_form_helper/form_builder/radio_select_field.rb +44 -0
  20. data/lib/eac/common_form_helper/form_builder/searchable_association_field.rb +77 -0
  21. data/lib/eac/cpf_validator.rb +60 -0
  22. data/lib/eac/formatter_helper.rb +27 -0
  23. data/lib/eac/htmlbeautifier.rb +25 -0
  24. data/lib/eac/menus_helper.rb +17 -0
  25. data/lib/eac/menus_helper/bootstrap_gui_builder.rb +90 -0
  26. data/lib/eac/menus_helper/data_builder.rb +57 -0
  27. data/lib/eac/menus_helper/gui_builder.rb +51 -0
  28. data/lib/eac/model.rb +87 -0
  29. data/lib/eac/simple_cache.rb +29 -0
  30. data/lib/eac/source_target_fixtures.rb +51 -0
  31. data/lib/eac_rails_utils.rb +29 -0
  32. data/lib/eac_rails_utils/patches/model_attribute_required.rb +31 -0
  33. data/lib/eac_rails_utils/rails/engine.rb +5 -0
  34. data/lib/eac_rails_utils/version.rb +3 -0
  35. data/test/dummy/Rakefile +6 -0
  36. data/test/dummy/app/models/job.rb +4 -0
  37. data/test/dummy/app/models/user.rb +7 -0
  38. data/test/dummy/config.ru +4 -0
  39. data/test/dummy/config/application.rb +12 -0
  40. data/test/dummy/config/boot.rb +4 -0
  41. data/test/dummy/config/database.yml +5 -0
  42. data/test/dummy/config/environment.rb +5 -0
  43. data/test/dummy/config/environments/test.rb +42 -0
  44. data/test/dummy/config/routes.rb +8 -0
  45. data/test/dummy/config/secrets.yml +22 -0
  46. data/test/dummy/db/migrate/20160415125333_create_users.rb +9 -0
  47. data/test/dummy/db/migrate/20160415143123_create_jobs.rb +7 -0
  48. data/test/dummy/db/migrate/20160415143229_add_job_to_users.rb +5 -0
  49. data/test/dummy/db/schema.rb +25 -0
  50. data/test/lib/eac/common_form_helper_test.rb +31 -0
  51. data/test/lib/eac/cpf_validator_test.rb +33 -0
  52. data/test/lib/eac/formatter_helper_test.rb +19 -0
  53. data/test/lib/eac/model_test.rb +76 -0
  54. data/test/lib/eac/simple_cache_test.rb +56 -0
  55. data/test/lib/eac_rails_utils/patches/model_attribute_required_test.rb +39 -0
  56. data/test/test_helper.rb +11 -0
  57. metadata +189 -0
@@ -0,0 +1,51 @@
1
+ module Eac
2
+ module MenusHelper
3
+ class GuiBuilder
4
+ def initialize(view)
5
+ @view = view
6
+ end
7
+
8
+ def build(entries, options = {})
9
+ fail "Argument \"entries\" is not a array" unless entries.is_a?(Array)
10
+ @view.content_tag(:ul, options) do
11
+ b = ActiveSupport::SafeBuffer.new
12
+ entries.map { |v| menu_entry(v) }.each { |e| b << e }
13
+ b
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def menu_entry(entry)
20
+ if entry[:type] == :group
21
+ menu_group(entry[:label], entry[:children])
22
+ elsif entry[:type] == :item
23
+ menu_item(entry[:label], entry[:path], entry[:options])
24
+ else
25
+ fail "Unknown menu entry type: \"#{entry[:type]}\""
26
+ end
27
+ end
28
+
29
+ def menu_group(label, children)
30
+ @view.content_tag(:li) do
31
+ @view.link_to(label) << build(children)
32
+ end
33
+ end
34
+
35
+ def menu_item(label, path, options)
36
+ @view.content_tag(:li) do
37
+ @view.link_to(label, path, menu_item_link_options(options))
38
+ end
39
+ end
40
+
41
+ def menu_item_link_options(options)
42
+ options = options.dup
43
+ if options.key?(:link_method)
44
+ options[:method] = options[:link_method]
45
+ options.delete(:link_method)
46
+ end
47
+ options
48
+ end
49
+ end
50
+ end
51
+ end
data/lib/eac/model.rb ADDED
@@ -0,0 +1,87 @@
1
+ module Eac
2
+ module Model
3
+ # Adiciona as mensagens de erro de record. As mensagens de uma coluna X em record
4
+ # serão adicionadas na coluna X em self. Se options[:default_column] for especificado
5
+ # as mensagens da coluna X de record em que X não existe em self serão adicionadas
6
+ # na coluna options[:default_column].
7
+ # Um array de colunas pode ser passado em options[:skip] de colunas em record que não
8
+ # terão suas falhas adicionadas.
9
+ def fetch_record_errors(record, options = {})
10
+ record.errors.keys.each do |column|
11
+ fetch_column_errors(record, column, column, options)
12
+ end
13
+ end
14
+
15
+ # Similar a fetch_record_errors, mas torna possível especificar, através de mapping,
16
+ # colunas-alvo em self com nomes diferentes das colunas-fonte em record.
17
+ # mapping tem o formato { record_column => self_column }.
18
+ def fetch_record_errors_by_mapping(record, mapping, options = {})
19
+ mapping.each do |record_column, self_column|
20
+ fetch_column_errors(record, record_column, self_column, options)
21
+ end
22
+ end
23
+
24
+ def fetch_column_errors(record, record_column, self_column, options = {})
25
+ return if options[:skip] && options[:skip].include?(record_column)
26
+ record.errors[record_column].each do |message|
27
+ fetch_error_column_message(self_column, message, options[:default_column],
28
+ "#{record.class.human_attribute_name(record_column)}: ")
29
+ end
30
+ end
31
+
32
+ # Verifica se uma coluna existe.
33
+ def column?(column)
34
+ respond_to?(column) && respond_to?("#{column}=")
35
+ end
36
+
37
+ def save_or_raise
38
+ unless save
39
+ fail "Falha ao tentar salvar #{self.class.name}: #{errors_to_string}"
40
+ end
41
+ self
42
+ end
43
+
44
+ private
45
+
46
+ def fetch_error_column_message(column, message, default_column, default_column_message_prefix)
47
+ build_self_columns_messages(column, message, default_column,
48
+ default_column_message_prefix).each do |k, v|
49
+ if column?(k)
50
+ add_error_message(k, v)
51
+ break
52
+ end
53
+ end
54
+ end
55
+
56
+ # Adiciona uma mensagem de erro a uma coluna somente se a coluna
57
+ # ainda não a possui
58
+ def add_error_message(column, message)
59
+ return if errors[column].include?(message)
60
+ errors.add(column, message)
61
+ end
62
+
63
+ # Produz uma lista de campos-mensagens, em ordem de preferência,
64
+ # que podem receber uma mensagem de falha.
65
+ def build_self_columns_messages(column, message, default_column,
66
+ default_column_message_prefix)
67
+ r = { column => message }
68
+ m = /^(.+)_id$/.match(column)
69
+ if m
70
+ r[m[1]] = message
71
+ else
72
+ r["#{column}_id"] = message
73
+ end
74
+ r[default_column] = "#{default_column_message_prefix}#{message}" if default_column
75
+ r
76
+ end
77
+
78
+ def errors_to_string
79
+ b = ''
80
+ errors.messages.each do |field, messages|
81
+ b += ' / ' if b != ''
82
+ b += field.to_s + ': ' + messages.to_s
83
+ end
84
+ b
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,29 @@
1
+ module Eac
2
+ module SimpleCache
3
+ def method_missing(method, *args, &block)
4
+ uncached_method = "#{method}_uncached"
5
+ if respond_to?(uncached_method, true)
6
+ call_method_with_cache(uncached_method, args, &block)
7
+ else
8
+ super
9
+ end
10
+ end
11
+
12
+ def reset_cache
13
+ @cache_keys = nil
14
+ end
15
+
16
+ private
17
+
18
+ def call_method_with_cache(method, args, &block)
19
+ fail 'Não é possível realizar o cache de métodos com bloco' if block
20
+ key = ([method] + args).join('@@@')
21
+ cache_keys[key] = send(method, *args) unless cache_keys.key?(key)
22
+ cache_keys[key]
23
+ end
24
+
25
+ def cache_keys
26
+ @cache_keys ||= {}
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml'
5
+
6
+ module Eac
7
+ class SourceTargetFixtures
8
+ attr_reader :fixtures_directory
9
+
10
+ def initialize(fixtures_directory)
11
+ @fixtures_directory = fixtures_directory
12
+ end
13
+
14
+ def source_target_files(&block)
15
+ sources_targets_basenames.each do |test_basename|
16
+ block.call(source_file(test_basename), target_file(test_basename))
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def target_file(basename)
23
+ fixture_file(basename, 'target')
24
+ end
25
+
26
+ def source_file(basename)
27
+ fixture_file(basename, 'source')
28
+ end
29
+
30
+ def fixture_file(basename, suffix)
31
+ prefix = "#{basename}.#{suffix}"
32
+ Dir.foreach(fixtures_directory) do |item|
33
+ next if item == '.' || item == '..'
34
+ return File.expand_path(item, fixtures_directory) if item.starts_with?(prefix)
35
+ end
36
+ fail "\"#{prefix}\" not found (Basename: #{basename}, Suffix: #{suffix})"
37
+ end
38
+
39
+ def sources_targets_basenames
40
+ basenames = []
41
+ Dir.foreach(fixtures_directory) do |item|
42
+ next if item == '.' || item == '..'
43
+ if /^(.+)\.(?:source|target)(?:\..+)?$/ =~ File.basename(item)
44
+ basenames << Regexp.last_match(1)
45
+ end
46
+ end
47
+ fail "\"#{fixtures_directory}\" não possui nenhum arquivo para teste." if basenames.empty?
48
+ basenames
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ module EacRailsUtils
2
+ require 'nested_form_fields'
3
+
4
+ require 'eac_rails_utils/patches/model_attribute_required'
5
+ require 'eac_rails_utils/rails/engine'
6
+ require 'eac/cpf_validator'
7
+ require 'eac/formatter_helper'
8
+ require 'eac/common_form_helper/form_builder/association_select_field'
9
+ require 'eac/common_form_helper/form_builder/common_text_fields'
10
+ require 'eac/common_form_helper/form_builder/currency_field'
11
+ require 'eac/common_form_helper/form_builder/date_field'
12
+ require 'eac/common_form_helper/form_builder/fields_for'
13
+ require 'eac/common_form_helper/form_builder/radio_select_field'
14
+ require 'eac/common_form_helper/form_builder/searchable_association_field'
15
+ require 'eac/common_form_helper/form_builder'
16
+ require 'eac/common_form_helper'
17
+ require 'eac/htmlbeautifier'
18
+ require 'eac/menus_helper'
19
+ require 'eac/menus_helper/bootstrap_gui_builder'
20
+ require 'eac/menus_helper/data_builder'
21
+ require 'eac/menus_helper/gui_builder'
22
+ require 'eac/model'
23
+ require 'eac/simple_cache'
24
+ require 'eac/source_target_fixtures'
25
+
26
+ ActionView::Base.send :include, Eac::CommonFormHelper
27
+ ActionView::Base.send :include, Eac::FormatterHelper
28
+ ActionView::Base.send :include, Eac::MenusHelper
29
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_record'
2
+
3
+ module EacRailsUtils
4
+ module Patches
5
+ module ModelAttributeRequired
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ base.include InstanceMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ def column_required?(column)
13
+ m = new
14
+ m.validate
15
+ m.errors.key?(column.to_sym)
16
+ end
17
+ end
18
+
19
+ module InstanceMethods
20
+ def attribute_required?(column)
21
+ self.class.column_required?(column)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ [::ActiveRecord::Base, ::ActiveModel::Model].each do |c|
29
+ next if c.included_modules.include? ::EacRailsUtils::Patches::ModelAttributeRequired
30
+ c.include ::EacRailsUtils::Patches::ModelAttributeRequired
31
+ end
@@ -0,0 +1,5 @@
1
+ module EacRailsUtils
2
+ module Rails
3
+ class Engine < ::Rails::Engine; end
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module EacRailsUtils
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,4 @@
1
+ class Job < ActiveRecord::Base
2
+ has_many :users
3
+ accepts_nested_attributes_for :users, reject_if: :all_blank, allow_destroy: true
4
+ end
@@ -0,0 +1,7 @@
1
+ class User < ActiveRecord::Base
2
+ belongs_to :job
3
+
4
+ validates :job, presence: true
5
+ validates :password, presence: true
6
+ validates :email, format: { with: /\A[^@\s]+@[^@\s]+\z/ }
7
+ end
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Rails.application
@@ -0,0 +1,12 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
4
+
5
+ Bundler.require(*Rails.groups)
6
+ require 'eac_rails_utils'
7
+
8
+ module Dummy
9
+ class Application < Rails::Application
10
+ config.active_record.raise_in_transactional_callbacks = true
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ # Set up gems listed in the Gemfile.
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
@@ -0,0 +1,5 @@
1
+ test:
2
+ adapter: sqlite3
3
+ pool: 5
4
+ timeout: 5000
5
+ database: db/test.sqlite3
@@ -0,0 +1,5 @@
1
+ # Load the Rails application.
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the Rails application.
5
+ Rails.application.initialize!
@@ -0,0 +1,42 @@
1
+ Rails.application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb.
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Do not eager load code on boot. This avoids loading your whole application
11
+ # just for the purpose of running a single test. If you are using a tool that
12
+ # preloads Rails for running tests, you may have to set it to true.
13
+ config.eager_load = false
14
+
15
+ # Configure static file server for tests with Cache-Control for performance.
16
+ config.serve_static_files = true
17
+ config.static_cache_control = 'public, max-age=3600'
18
+
19
+ # Show full error reports and disable caching.
20
+ config.consider_all_requests_local = true
21
+ config.action_controller.perform_caching = false
22
+
23
+ # Raise exceptions instead of rendering exception templates.
24
+ config.action_dispatch.show_exceptions = false
25
+
26
+ # Disable request forgery protection in test environment.
27
+ config.action_controller.allow_forgery_protection = false
28
+
29
+ # Tell Action Mailer not to deliver emails to the real world.
30
+ # The :test delivery method accumulates sent emails in the
31
+ # ActionMailer::Base.deliveries array.
32
+ config.action_mailer.delivery_method = :test
33
+
34
+ # Randomize the order test cases are executed.
35
+ config.active_support.test_order = :random
36
+
37
+ # Print deprecation notices to the stderr.
38
+ config.active_support.deprecation = :stderr
39
+
40
+ # Raises error for missing translations
41
+ # config.action_view.raise_on_missing_translations = true
42
+ end
@@ -0,0 +1,8 @@
1
+ Rails.application.routes.draw do
2
+ resources :jobs do
3
+ collection do
4
+ get 'search'
5
+ end
6
+ end
7
+ resources :users
8
+ end
@@ -0,0 +1,22 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key is used for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+
6
+ # Make sure the secret is at least 30 characters and all random,
7
+ # no regular words or you'll be exposed to dictionary attacks.
8
+ # You can use `rake secret` to generate a secure secret key.
9
+
10
+ # Make sure the secrets in this file are kept private
11
+ # if you're sharing your code publicly.
12
+
13
+ development:
14
+ secret_key_base: 50d3bce23e309d961dafde3edfa89be2713718a5e2fb75b6c3e1f61826230921535243d2f221b8cecebeaceccb574a1e74fbbf3b89a9d53758ac988950f1753c
15
+
16
+ test:
17
+ secret_key_base: 75f37392ef7726b50b4ce117bd6a7eca7cdc299608e256f7ca163b14032559217364d41b7c091483ce02179a18c956f6e076331a611c0500f2862f83979a6c16
18
+
19
+ # Do not keep production secrets in the repository,
20
+ # instead read values from the environment.
21
+ production:
22
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
@@ -0,0 +1,9 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :name
5
+ t.string :email
6
+ t.string :password
7
+ end
8
+ end
9
+ end