rails-add_ons 2.2.1 → 3.0.0.pre1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/rails/add_ons/application/autosubmit.js.coffee +4 -0
  3. data/app/assets/stylesheets/rails/add_ons/application/{bootstrap_overrides.scss → bootstrap_overrides.css} +0 -0
  4. data/app/assets/stylesheets/rails/add_ons/application/{table_monospaced.scss → table_monospaced.css} +0 -0
  5. data/app/assets/stylesheets/rails/add_ons/application/{widgets.scss → widgets.css} +0 -0
  6. data/app/assets/stylesheets/rails/add_ons/application.css +3 -0
  7. data/app/assets/stylesheets/rails/add_ons/{bootstrap_v3_flex_extension.scss → bootstrap_v3_flex_extension.css} +0 -0
  8. data/app/components/component/collection_table.rb +4 -0
  9. data/app/concerns/component/collection_table/batch_actions_concern.rb +4 -0
  10. data/app/concerns/controller/autosubmit_concern.rb +48 -0
  11. data/app/concerns/controller/query_conditions.rb +18 -1
  12. data/app/concerns/resources_controller/acts_as_list_concern.rb +7 -1
  13. data/app/concerns/resources_controller/batch_actions_concern.rb +9 -2
  14. data/app/concerns/resources_controller/location_history.rb +1 -0
  15. data/app/concerns/resources_controller/rest_actions.rb +4 -3
  16. data/app/concerns/resources_controller/search_form_concern.rb +9 -0
  17. data/app/concerns/resources_controller/will_paginate.rb +16 -2
  18. data/app/concerns/service_controller/rest_actions.rb +1 -1
  19. data/app/controllers/api/resources_controller/base.rb +1 -1
  20. data/app/controllers/api/service_controller/base.rb +1 -1
  21. data/app/controllers/resources_controller/base.rb +1 -1
  22. data/app/controllers/service_controller/base.rb +1 -1
  23. data/app/helpers/rails/add_ons/autosubmit_helper.rb +11 -0
  24. data/app/helpers/rails/add_ons/search_form_helper.rb +103 -0
  25. data/app/parsers/api/resources_controller/condition_parser.rb +62 -16
  26. data/app/views/component/table/header_cells/_batch_actions.haml +1 -1
  27. data/app/views/service_controller/base/_form_errors.haml +2 -1
  28. data/config/locales/de.yml +17 -0
  29. data/lib/generators/rails/add_ons/templates/initializer.rb +24 -0
  30. data/lib/rails/add_ons/configuration.rb +5 -1
  31. data/lib/rails/add_ons/shoulda/matchers/implement_create_action_matcher.rb +12 -6
  32. data/lib/rails/add_ons/shoulda/matchers/implement_delete_action_matcher.rb +12 -6
  33. data/lib/rails/add_ons/shoulda/matchers/implement_index_action_matcher.rb +13 -6
  34. data/lib/rails/add_ons/shoulda/matchers/implement_show_action_matcher.rb +15 -10
  35. data/lib/rails/add_ons/shoulda/matchers/implement_update_action_matcher.rb +12 -6
  36. data/lib/rails/add_ons/version.rb +1 -1
  37. metadata +28 -9
  38. data/app/assets/stylesheets/rails/add_ons/application.scss +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c7c4f39bddae1458684c318b7c5eb56192a5807
4
- data.tar.gz: 837bb68a45e06765a53361094424189022aac308
3
+ metadata.gz: cbbb783440b059a3b92ea129bd2f842870974373
4
+ data.tar.gz: caee54825a95a1bb70770ca526d967a8178c09c2
5
5
  SHA512:
6
- metadata.gz: 0b3ea72bef606239b4f36ef3a3f968cade7414a163fed52b017065206141ccef0bb73a00db0cc66dbd9cc37259425e97834e50702e34f67e40b15c353226c5e6
7
- data.tar.gz: 1e719c48c0dfece1b0a28c9cbfe0b2084b70527a551a3c16f20b0b58aa10b47e4ab307c80447fc38b04ca3cb5c129c772cf0678b7ee75c0eff854f2088432b1d
6
+ metadata.gz: 0cd22f3de8861299824bb3c9fbf377f8b9a920c6a71db291774f6a36bb5a514eaf72a1ec8eb112a6f33e77e40ac7177545edf7f5b7d16e3d72f817925eaec15f
7
+ data.tar.gz: 3ec98bb46404d2dc7d356ec2b7cec645cdbb87f481cf020a9c5c968ebc1f5fc1d6c8c72ef68e9312b5d74c3665fc0e6a0e9f7a357685c97d0c8657c2e5ff5aee
@@ -0,0 +1,4 @@
1
+ $ ->
2
+ $('[data-autosubmit="true"]').each ->
3
+ $(this).closest("form").append('<div class="loading">Loading&#8230;</div>')
4
+ $(this).closest("form").submit()
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree ./application/
3
+ */
@@ -49,6 +49,10 @@ module Component
49
49
  timestamp(:updated_at, options)
50
50
  end
51
51
 
52
+ # Example:
53
+ #
54
+ # = table.association :category, sortable: true, label_method: :name, link_to: ->(r) { url_for(r.category) }
55
+ #
52
56
  def association(name, options = {}, &block)
53
57
  options.reverse_merge!(render_as: :association)
54
58
  column(name, options, &block)
@@ -2,6 +2,10 @@ module Component
2
2
  module CollectionTable::BatchActionsConcern
3
3
  extend ActiveSupport::Concern
4
4
 
5
+ # Example:
6
+ #
7
+ # = table.batch_actions(actions: { destroy: url_for(action: :destroy_many) })
8
+ #
5
9
  def batch_actions(options = {}, &block)
6
10
  @wrap_in_form = true
7
11
  title = @view.render partial: 'component/table/header_cells/batch_actions', locals: { options: options }
@@ -0,0 +1,48 @@
1
+ module Controller
2
+ # Handles automatic form submits.
3
+ #
4
+ # Prerequisites:
5
+ #
6
+ # Include the javascript:
7
+ #
8
+ # # app/assets/javascripts/application.js
9
+ # //= require rails/add_ons/application/autosubmit
10
+ #
11
+ # Example:
12
+ #
13
+ # # app/controllers/posts_controller.rb
14
+ # class PostsController < ApplicationController
15
+ # include AutosubmitConcern
16
+ #
17
+ # # ...
18
+ #
19
+ # private
20
+ #
21
+ # def autosubmit?
22
+ # true
23
+ # end
24
+ # end
25
+ #
26
+ # # app/views/posts/new.html.haml
27
+ # = form_for(...) do |f|
28
+ # = autosubmit
29
+ #
30
+ module AutosubmitConcern
31
+ extend ActiveSupport::Concern
32
+
33
+ included do
34
+ helper Rails::AddOns::AutosubmitHelper
35
+ helper_method :autosubmit?, :autosubmit_now?
36
+ end
37
+
38
+ private
39
+
40
+ def autosubmit?
41
+ false
42
+ end
43
+
44
+ def autosubmit_now?
45
+ autosubmit? && action_name == 'new'
46
+ end
47
+ end
48
+ end
@@ -2,7 +2,13 @@ module Controller::QueryConditions
2
2
  private
3
3
 
4
4
  def add_conditions_from_query(scope)
5
- query_params.each do |field, condition|
5
+ if query_params.keys.include?('q')
6
+ condition_params = normalize_query_params(query_params)
7
+ else
8
+ condition_params = query_params
9
+ end
10
+
11
+ condition_params.reject.reject { |k,v| v.blank? }.each do |field, condition|
6
12
  case field
7
13
  when 'limit'
8
14
  scope = scope.limit(condition.to_i)
@@ -31,4 +37,15 @@ module Controller::QueryConditions
31
37
  def default_query_params_exceptions
32
38
  %w(sort_by sort_direction utf8 commit page)
33
39
  end
40
+
41
+ def normalize_query_params(params)
42
+ params['q'].each_with_object({}) { |(k, v), m| m[normalize_key(k)] = v }
43
+ end
44
+
45
+ def normalize_key(key)
46
+ splitted_key = key.split('_')
47
+ predicate = splitted_key.last
48
+ attribute = splitted_key[0..-2].join('_')
49
+ "#{attribute}(#{predicate})"
50
+ end
34
51
  end
@@ -26,7 +26,13 @@ module ResourcesController
26
26
  end
27
27
  end
28
28
 
29
- redirect_to collection_path, notice: I18n.t("acts_as_list.flash.actions.reposition.inserted_#{position}", target_resource: target_resource_label, inserted_resource: inserted_resource_label)
29
+ redirect_to after_reposition_location, notice: I18n.t("acts_as_list.flash.actions.reposition.inserted_#{position}", target_resource: target_resource_label, inserted_resource: inserted_resource_label)
30
+ end
31
+
32
+ private
33
+
34
+ def after_reposition_location
35
+ collection_path
30
36
  end
31
37
  end
32
38
  end
@@ -1,10 +1,17 @@
1
1
  module ResourcesController
2
+ # Don't forget to add routes:
3
+ #
4
+ # # config/routes.rb;
5
+ # resources :users do
6
+ # post :destroy_many, on: :collection
7
+ # end
8
+ #
2
9
  module BatchActionsConcern
3
10
  def destroy_many
4
11
  @collection = load_collection_scope.where(id: params[:ids])
5
12
  @collection.destroy_all
6
13
 
7
- respond_with @collection, location: after_destroy_many_location, noticse: t('.success')
14
+ respond_with @collection, location: after_destroy_many_location, notice: t('.success')
8
15
  end
9
16
 
10
17
  private
@@ -13,4 +20,4 @@ module ResourcesController
13
20
  collection_path
14
21
  end
15
22
  end
16
- end
23
+ end
@@ -17,6 +17,7 @@ module ResourcesController
17
17
  def store_location
18
18
  return if request.referer.nil?
19
19
  truncate_location_history(9)
20
+ puts "[LocationHistoryConcern] Storing last location [#{request.referer}]"
20
21
  location_history[Time.zone.now] = request.referer
21
22
  end
22
23
 
@@ -13,6 +13,7 @@ module ResourcesController
13
13
  before_action :load_resource, only: [:show, :edit, :destroy, :update]
14
14
  before_action :initialize_resource, only: [:new]
15
15
  before_action :initialize_resource_for_create, only: [:create]
16
+ before_action :before_rest_action, if: -> { respond_to?(:before_rest_action, true) }
16
17
  else
17
18
  before_filter :load_collection, only: [:index]
18
19
  before_filter :load_resource, only: [:show, :edit, :destroy, :update]
@@ -27,7 +28,7 @@ module ResourcesController
27
28
  def edit; end
28
29
 
29
30
  def update
30
- if @resource.send(update_method_name, permitted_params) && respond_to?(:after_update_location, true)
31
+ if @resource.send(update_method_name, permitted_params) && respond_to?(:after_update_location, true) && after_update_location.present?
31
32
  respond_with(respond_with_namespace, @resource, location: after_update_location)
32
33
  else
33
34
  respond_with(respond_with_namespace, @resource)
@@ -36,7 +37,7 @@ module ResourcesController
36
37
 
37
38
  def destroy
38
39
  @resource.destroy
39
- if respond_to?(:after_destroy_location, true)
40
+ if respond_to?(:after_destroy_location, true) && after_destroy_location.present?
40
41
  respond_with(respond_with_namespace, @resource, location: after_destroy_location)
41
42
  else
42
43
  respond_with(respond_with_namespace, @resource)
@@ -44,7 +45,7 @@ module ResourcesController
44
45
  end
45
46
 
46
47
  def create
47
- if @resource.save && respond_to?(:after_create_location, true)
48
+ if @resource.save && respond_to?(:after_create_location, true) && after_create_location.present?
48
49
  respond_with(respond_with_namespace, @resource, location: after_create_location)
49
50
  else
50
51
  respond_with(respond_with_namespace, @resource)
@@ -0,0 +1,9 @@
1
+ module ResourcesController
2
+ module SearchFormConcern
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ helper Rails::AddOns::SearchFormHelper
7
+ end
8
+ end
9
+ end
@@ -1,4 +1,16 @@
1
1
  module ResourcesController
2
+ # Setting the pagination size in the controller:
3
+ #
4
+ # # app/controllers/posts_controller.rb
5
+ # class PostsController < ApplicationController
6
+ # # ...
7
+ # private
8
+ #
9
+ # def per_page
10
+ # 15
11
+ # end
12
+ # end
13
+ #
2
14
  module WillPaginate
3
15
  extend ActiveSupport::Concern
4
16
 
@@ -13,7 +25,9 @@ module ResourcesController
13
25
  private
14
26
 
15
27
  def load_collection
16
- @collection = load_collection_scope.paginate(page: params[:page])
28
+ options = { page: params[:page] }
29
+ options[:per_page] = per_page if respond_to?(:per_page, true)
30
+ @collection = load_collection_scope.paginate(options)
17
31
  end
18
32
  end
19
- end
33
+ end
@@ -26,7 +26,7 @@ module ServiceController::RestActions
26
26
  @result = execute_service
27
27
  if @result.success?
28
28
 
29
- if respond_to?(:after_success_location, true)
29
+ if respond_to?(:after_success_location, true) && after_success_location.present?
30
30
  redirect_to(after_success_location, notice: success_message)
31
31
  else
32
32
  flash.now[:success] = success_message
@@ -1,6 +1,6 @@
1
1
  module Api
2
2
  module ResourcesController
3
- class Base < ::ApiController
3
+ class Base < Rails::AddOns::Configuration.api_resources_controller_base_class_name.constantize
4
4
  module RestActions
5
5
  extend ActiveSupport::Concern
6
6
 
@@ -1,6 +1,6 @@
1
1
  module Api
2
2
  module ServiceController
3
- class Base < ::ApiController
3
+ class Base < Rails::AddOns::Configuration.api_service_controller_base_class_name.constantize
4
4
  module RestActions
5
5
  extend ActiveSupport::Concern
6
6
 
@@ -1,5 +1,5 @@
1
1
  module ResourcesController
2
- class Base < ::FrontendController
2
+ class Base < Rails::AddOns::Configuration.resources_controller_base_class_name.constantize
3
3
  layout 'rails/add_ons/application'
4
4
 
5
5
  include RestActions
@@ -1,5 +1,5 @@
1
1
  module ServiceController
2
- class Base < ::FrontendController
2
+ class Base < Rails::AddOns::Configuration.service_controller_base_class_name.constantize
3
3
  layout 'rails/add_ons/application'
4
4
 
5
5
  include ServiceController::Service
@@ -0,0 +1,11 @@
1
+ module Rails
2
+ module AddOns
3
+ module AutosubmitHelper
4
+ def autosubmit
5
+ if autosubmit_now?
6
+ content_tag(:div, nil, data: { autosubmit: true} ).html_safe
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,103 @@
1
+ module Rails
2
+ module AddOns
3
+ module SearchFormHelper
4
+ # Example:
5
+ #
6
+ # = search_form_for(@collection, url: collection_path, method: :get) do |f|
7
+ # = f.input :title_cont
8
+ # = f.input :product_number_cont
9
+ # = f.boolean :active_eq
10
+ # = f.submit nil, class: 'btn btn-primary'
11
+ # = f.reset nil, class: 'btn btn-default'
12
+ #
13
+ def search_form_for(collection, options = {}, &block)
14
+ wrapped_collection = SearchableCollection.new(collection, params[:q])
15
+ simple_form_for(wrapped_collection, options.reverse_merge(as: :q, url: collection_path, method: :get, builder: SearchFormBuilder), &block)
16
+ end
17
+
18
+ class SearchFormBuilder < SimpleForm::FormBuilder
19
+ def boolean(name, options = {})
20
+ translated_label = translate_label_for_boolean(name)
21
+ options.reverse_merge!(collection: [[I18n.t("search_form_builder.yes"), 1], [I18n.t("search_form_builder.no"), 0]], include_blank: true, label: translated_label)
22
+ input name, options
23
+ end
24
+
25
+ def input(name, options = {})
26
+ if association = options.delete(:association)
27
+ translated_label = translate_label(name, association)
28
+ input_name = "#{association}.#{name}"
29
+ else
30
+ translated_label = translate_label(name)
31
+ input_name = name
32
+ end
33
+ super(input_name, options.reverse_merge(label: translated_label))
34
+ end
35
+
36
+ def submit(title = nil, options = {})
37
+ title ||= I18n.t('search_form_builder.submit')
38
+ super(title, options)
39
+ end
40
+
41
+ def reset(title = nil, options = {})
42
+ title ||= I18n.t('search_form_builder.reset')
43
+ link_html = options.delete(:link_html) || {}
44
+ template.link_to(title, template.url_for(), link_html)
45
+ end
46
+
47
+ private
48
+
49
+ def translate_label(name, association = nil)
50
+ splitted_name = name.to_s.split('_')
51
+ attribute_name = splitted_name[0..-2].join('_')
52
+ predicate = splitted_name.last
53
+ if association.nil?
54
+ klass_name = object.original_model_class_name
55
+ else
56
+ klass_name = object.original_model_class.reflect_on_association(association).klass.name
57
+ end
58
+ translated_attribute_name = klass_name.constantize.human_attribute_name(attribute_name)
59
+ I18n.t("search_form_builder.predicates.#{predicate}", attribute_name: translated_attribute_name)
60
+ end
61
+
62
+ def translate_label_for_boolean(name)
63
+ splitted_name = name.to_s.split('_')
64
+ attribute_name = splitted_name[0..-2].join('_')
65
+ predicate = splitted_name.last
66
+ if association.nil?
67
+ klass_name = object.original_model_class_name
68
+ else
69
+ klass_name = object.original_model_class.reflect_on_association(association).klass
70
+ end
71
+ translated_attribute_name = klass_name.constantize.human_attribute_name(attribute_name)
72
+ I18n.t("search_form_builder.boolean_label", attribute_name: translated_attribute_name)
73
+ end
74
+ end
75
+
76
+ class SearchableCollection
77
+ include ActiveModel::Model
78
+ extend ActiveModel::Translation
79
+
80
+ def method_missing(method, *args)
81
+ if method.to_s.match(/(.+)_(gt|gt_or_eq|eq|not_eq|lt_or_eq|lt|null|not_null|cont)/)
82
+ @query.send(:[], method)
83
+ else
84
+ super
85
+ end
86
+ end
87
+
88
+ def initialize(collection, query)
89
+ @collection = collection
90
+ @query = query || {}
91
+ end
92
+
93
+ def original_model_class_name
94
+ @collection.class.to_s.deconstantize
95
+ end
96
+
97
+ def original_model_class
98
+ @collection.klass
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -9,7 +9,8 @@ module Api
9
9
  lt_or_eq: :<=,
10
10
  lt: :<,
11
11
  null: :is_null,
12
- not_null: :is_not_null
12
+ not_null: :is_not_null,
13
+ cont: :like
13
14
  }
14
15
 
15
16
  def initialize(scope, field, condition)
@@ -24,13 +25,19 @@ module Api
24
25
 
25
26
  def build_condition_statement(parent_key, condition, nested = false)
26
27
  if is_a_condition?(parent_key) && !nested
27
- column, operator = extract_column_and_operator(parent_key)
28
+ table, column, operator = extract_table_column_and_operator(parent_key)
28
29
  return handle_null_condition(column, operator) if is_null_operator?(operator)
29
- if column_is_boolean?(column)
30
- ["#{column} = ?", to_boolean(condition)]
30
+ # binding.pry
31
+ if operator == 'cont'
32
+ return ["#{table}.#{column} LIKE ?", "%#{normalized_condition(table, column, condition)}%"]
31
33
  else
32
- ["#{column} = ?", condition]
34
+ return ["#{table}.#{column} = ?", normalized_condition(table, column, condition)]
33
35
  end
36
+ # if column_is_boolean?(column)
37
+ # ["#{column} = ?", to_boolean(condition)]
38
+ # else
39
+ # ["#{column} = ?", condition]
40
+ # end
34
41
  else
35
42
  if nested
36
43
  column = extract_column(parent_key)
@@ -70,9 +77,23 @@ module Api
70
77
  obj.to_s.split("(").first
71
78
  end
72
79
 
73
- def extract_column_and_operator(string)
80
+ # def extract_column_and_operator(string)
81
+ # if string =~ /([\.a-z_]{1,})\(([a-z_]{2,})\)/
82
+ # return $~[1], $~[2]
83
+ # end
84
+ # end
85
+
86
+ def extract_table_column_and_operator(string)
74
87
  if string =~ /([\.a-z_]{1,})\(([a-z_]{2,})\)/
75
- return $~[1], $~[2]
88
+ table_and_column = $~[1]
89
+ operator = $~[2]
90
+ column, table_or_association = table_and_column.split('.').reverse
91
+ if table_or_association.nil?
92
+ table = @scope.table_name
93
+ else
94
+ table = tables_and_classes_with_associations[table_or_association].table_name
95
+ end
96
+ return table, column, operator
76
97
  end
77
98
  end
78
99
 
@@ -80,23 +101,48 @@ module Api
80
101
  OPERATOR_MAP
81
102
  end
82
103
 
83
- def column_is_boolean?(column_name)
84
- scope, column = get_scope_and_column_from_column_name(column_name)
104
+ def column_is_boolean?(table_name, column_name)
105
+ scope, column = get_scope_and_column_from_column_name(column_name, table_name)
106
+ raise "Unknown column: #{column_name}" unless scope.columns_hash.has_key?(column)
85
107
  scope.columns_hash[column].type == :boolean
86
108
  end
87
109
 
88
- def get_scope_and_column_from_column_name(column_name)
89
- if column_name =~ /(.*)\.(.*)/
90
- tables_and_classes = @scope.reflect_on_all_associations.each_with_object({}) { |a, memo| memo[a.table_name] = a.klass }
91
- scope = tables_and_classes[$~[1]]
92
- return scope, $~[2]
93
- else
110
+ def get_scope_and_column_from_column_name(column_name, table_name = nil)
111
+ if table_name == @scope.table_name
94
112
  return @scope, column_name
113
+ else
114
+ # tables_and_classes = @scope.reflect_on_all_associations.reject { |a| a.polymorphic? }.each_with_object({}) { |a, memo| memo[a.table_name] = a.klass }
115
+ # associations_and_classes = @scope.reflect_on_all_associations.reject { |a| a.polymorphic? }.each_with_object({}) { |a, memo| memo[a.name.to_s] = a.klass }
116
+ # scope = tables_and_classes.merge(associations_and_classes)[$~[1]]
117
+ scope = tables_and_classes_with_associations[table_name]
118
+ return scope, column_name
95
119
  end
96
120
  end
97
121
 
122
+ def tables_and_classes_with_associations
123
+ tables_and_classes = @scope.reflect_on_all_associations.reject { |a| (a.respond_to?(:polymorphic?) && a.polymorphic?) || a.options[:polymorphic] == true }.each_with_object({}) { |a, memo| memo[a.table_name] = a.klass }
124
+ associations_and_classes = @scope.reflect_on_all_associations.reject { |a| (a.respond_to?(:polymorphic?) && a.polymorphic?) || a.options[:polymorphic] == true }.each_with_object({}) { |a, memo| memo[a.name.to_s] = a.klass }
125
+ tables_and_classes.merge(associations_and_classes)
126
+ end
127
+
98
128
  def to_boolean(string)
99
- ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)
129
+ result = case
130
+ when Rails.version < '4.2'
131
+ ::ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)
132
+ when Rails.version < '5.0'
133
+ ::ActiveRecord::Type::Boolean.new.type_cast_for_schema(string)
134
+ else
135
+ ::ActiveRecord::Type::Boolean.new.cast(string)
136
+ end
137
+ result.gsub('"', '')
138
+ end
139
+
140
+ def normalized_condition(table, column, condition)
141
+ if column_is_boolean?(table, column)
142
+ to_boolean(condition)
143
+ else
144
+ condition
145
+ end
100
146
  end
101
147
  end
102
148
  end
@@ -7,7 +7,7 @@
7
7
  = hidden_field_tag :authenticity_token, form_authenticity_token
8
8
  .dropdown.batch-action-dropdown
9
9
  %button.btn.btn-default.dropdown-toggle{"aria-expanded" => "true", "aria-haspopup" => "true", "data-toggle" => "dropdown", :type => "button", id: 'batch-action-dropdown' }
10
- = t('.batch_actions')
10
+ = t('.title')
11
11
  %span.caret
12
12
  %ul.dropdown-menu{"aria-labelledby" => 'batch-action-dropdown' }
13
13
  - options[:actions].each do |action, target|
@@ -1,6 +1,7 @@
1
1
  - if service.errors.any?
2
2
  = bootstrap_alert(context: :danger, class: 'error-explanation') do
3
- .error-heading= t('errors.template.header', count: service.errors.count, model: service.class.model_name.human)
3
+ - message_default = t('errors.template.header', count: service.errors.count, model: service.class.model_name.human)
4
+ .error-heading= t('errors.template.services.header', count: service.errors.count, model: service.class.model_name.human, default: message_default)
4
5
  %ul
5
6
  - service.errors.full_messages.each do |msg|
6
7
  %li= msg
@@ -10,6 +10,7 @@ de:
10
10
  delete: Löschen
11
11
  edit: Bearbeiten
12
12
  show: Anzeigen
13
+ download: Download
13
14
  table:
14
15
  body_cells:
15
16
  boolean:
@@ -17,7 +18,14 @@ de:
17
18
  'false': Nein
18
19
  header_cells:
19
20
  batch_actions:
21
+ title: Stapelverarbeitung
20
22
  destroy: Löschen
23
+ errors:
24
+ template:
25
+ services:
26
+ header:
27
+ one: "Konnte %{model} nicht ausführen: Ein Fehler"
28
+ other: "Konnte %{model} nicht ausführen: %{count} Fehler"
21
29
  flash:
22
30
  actions:
23
31
  create:
@@ -76,3 +84,12 @@ de:
76
84
  pagination:
77
85
  last: '&#9654;'
78
86
  next: '&#9664;'
87
+ search_form_builder:
88
+ predicates:
89
+ cont: "%{attribute_name} enthält"
90
+ eq: "%{attribute_name} ist"
91
+ boolean_label: "%{attribute_name}?"
92
+ submit: Suchen
93
+ reset: Zurücksetzen
94
+ 'yes': Ja
95
+ 'no': Nein
@@ -4,4 +4,28 @@ Rails::AddOns.configure do |config|
4
4
  # Default: config.table_default_timestamp_format = nil
5
5
  #
6
6
  config.table_default_timestamp_format = nil
7
+
8
+ # Sets the parent controller for Api::ServiceController::Base
9
+ #
10
+ # default: config.api_service_controller_base_class_name = '::ApiController'
11
+ #
12
+ config.api_service_controller_base_class_name = '::ApiController'
13
+
14
+ # Sets the parent controller for Api::ResourcesController::Base
15
+ #
16
+ # default: config.api_resources_controller_base_class_name = '::ApiController'
17
+ #
18
+ config.api_resources_controller_base_class_name = '::ApiController'
19
+
20
+ # Sets the parent controller for ServiceController::Base
21
+ #
22
+ # default: config.service_controller_base_class_name = '::FrontendController'
23
+ #
24
+ config.service_controller_base_class_name = '::FrontendController'
25
+
26
+ # Sets the parent controller for ResourcesController::Base
27
+ #
28
+ # default: config.resources_controller_base_class_name = '::FrontendController'
29
+ #
30
+ config.resources_controller_base_class_name = '::FrontendController'
7
31
  end
@@ -5,7 +5,11 @@ module Rails
5
5
  yield self
6
6
  end
7
7
 
8
- mattr_accessor(:table_default_timestamp_format) { :short }
8
+ mattr_accessor(:table_default_timestamp_format) { :short }
9
+ mattr_accessor(:api_service_controller_base_class_name) { '::ApiController' }
10
+ mattr_accessor(:api_resources_controller_base_class_name) { '::ApiController' }
11
+ mattr_accessor(:service_controller_base_class_name) { '::FrontendController' }
12
+ mattr_accessor(:resources_controller_base_class_name) { '::FrontendController' }
9
13
  end
10
14
  end
11
15
  end
@@ -87,7 +87,8 @@ module Rails
87
87
  end
88
88
 
89
89
  def matches?(base_path)
90
- @base_path = base_path
90
+ @base_path = @spec.class.name.split('::')[0..2].join('::').constantize.description
91
+ # @base_path = base_path
91
92
  @new_path = "#{@base_path}/new"
92
93
 
93
94
  @spec.visit(@new_path)
@@ -111,11 +112,16 @@ module Rails
111
112
  end
112
113
 
113
114
  def has_correct_status_code
114
- if @spec.status_code == 200
115
- true
116
- else
117
- @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
118
- false
115
+ begin
116
+ if @spec.status_code == 200
117
+ true
118
+ else
119
+ @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
120
+ false
121
+ end
122
+ rescue Capybara::NotSupportedByDriverError => e
123
+ puts "[Warning] Skipping status code check as it is not supported by your driver [#{@spec.driver.instance_variable_get(:@name)}]."
124
+ return true
119
125
  end
120
126
  end
121
127
 
@@ -47,7 +47,8 @@ module Rails
47
47
  end
48
48
 
49
49
  def matches?(base_path)
50
- @base_path = base_path
50
+ @base_path = @spec.class.name.split('::')[0..2].join('::').constantize.description
51
+ # @base_path = base_path
51
52
  @expected_path = @base_path
52
53
  @show_path = "#{@base_path}/#{id}"
53
54
 
@@ -65,11 +66,16 @@ module Rails
65
66
  end
66
67
 
67
68
  def has_correct_status_code
68
- if @spec.status_code == 200
69
- true
70
- else
71
- @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
72
- false
69
+ begin
70
+ if @spec.status_code == 200
71
+ true
72
+ else
73
+ @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
74
+ false
75
+ end
76
+ rescue Capybara::NotSupportedByDriverError => e
77
+ puts "[Warning] Skipping status code check as it is not supported by your driver [#{@spec.driver.instance_variable_get(:@name)}]."
78
+ return true
73
79
  end
74
80
  end
75
81
 
@@ -22,17 +22,24 @@ module Rails
22
22
  end
23
23
 
24
24
  def matches?(base_path)
25
- @base_path = base_path
25
+ @base_path = @spec.class.name.split('::')[0..2].join('::').constantize.description
26
+ # @base_path = base_path
27
+
26
28
  @spec.visit(@base_path)
27
29
  has_correct_status_code && has_correct_current_path
28
30
  end
29
31
 
30
32
  def has_correct_status_code
31
- if @spec.status_code == 200
32
- true
33
- else
34
- @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
35
- false
33
+ begin
34
+ if @spec.status_code == 200
35
+ true
36
+ else
37
+ @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
38
+ false
39
+ end
40
+ rescue Capybara::NotSupportedByDriverError => e
41
+ puts "[Warning] Skipping status code check as it is not supported by your driver [#{@spec.driver.instance_variable_get(:@name)}]."
42
+ return true
36
43
  end
37
44
  end
38
45
 
@@ -32,20 +32,25 @@ module Rails
32
32
  end
33
33
 
34
34
  def matches?(base_path)
35
- @base_path = base_path
35
+ @base_path = @spec.class.name.split('::')[0..2].join('::').constantize.description
36
+ # @base_path = base_path
36
37
  @expected_path = "#{@base_path}/#{id}"
37
38
 
38
39
  @spec.visit(@expected_path)
39
-
40
40
  has_correct_status_code && has_correct_current_path
41
41
  end
42
42
 
43
43
  def has_correct_status_code
44
- if @spec.status_code == 200
45
- true
46
- else
47
- @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
48
- false
44
+ begin
45
+ if @spec.status_code == 200
46
+ true
47
+ else
48
+ @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
49
+ false
50
+ end
51
+ rescue Capybara::NotSupportedByDriverError => e
52
+ puts "[Warning] Skipping status code check as it is not supported by your driver [#{@spec.driver.instance_variable_get(:@name)}]."
53
+ return true
49
54
  end
50
55
  end
51
56
 
@@ -59,17 +64,17 @@ module Rails
59
64
  end
60
65
 
61
66
  def failure_message
62
- "Should expose show action on #{@base_path}. Error: #{@error}"
67
+ "Should expose show action on #{@expected_path}. Error: #{@error}"
63
68
  end
64
69
 
65
70
  def failure_message_when_negated
66
- "Should not expose show action on #{@base_path}. Error: #{@error}"
71
+ "Should not expose show action on #{@expected_path}. Error: #{@error}"
67
72
  end
68
73
 
69
74
  alias negative_failure_message failure_message_when_negated
70
75
 
71
76
  def description
72
- "expose show action on #{@base_path}"
77
+ "expose show action on #{@expected_path}"
73
78
  end
74
79
  end
75
80
  end
@@ -80,7 +80,8 @@ module Rails
80
80
  end
81
81
 
82
82
  def matches?(base_path)
83
- @base_path = base_path
83
+ @base_path = @spec.class.name.split('::')[0..2].join('::').constantize.description
84
+ # @base_path = base_path
84
85
  @show_path = "#{@base_path}/#{id}"
85
86
  @edit_path = "#{@base_path}/#{id}/edit"
86
87
 
@@ -101,11 +102,16 @@ module Rails
101
102
  end
102
103
 
103
104
  def has_correct_status_code
104
- if @spec.status_code == 200
105
- true
106
- else
107
- @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
108
- false
105
+ begin
106
+ if @spec.status_code == 200
107
+ true
108
+ else
109
+ @error = "Wrong status code [#{@spec.status_code}] instead of [200]"
110
+ false
111
+ end
112
+ rescue Capybara::NotSupportedByDriverError => e
113
+ puts "[Warning] Skipping status code check as it is not supported by your driver [#{@spec.driver.instance_variable_get(:@name)}]."
114
+ return true
109
115
  end
110
116
  end
111
117
 
@@ -1,5 +1,5 @@
1
1
  module Rails
2
2
  module AddOns
3
- VERSION = '2.2.1'.freeze
3
+ VERSION = '3.0.0.pre1'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-add_ons
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 3.0.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Vasquez Angel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-25 00:00:00.000000000 Z
11
+ date: 2019-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-rails
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: haml-rails
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -177,13 +191,14 @@ files:
177
191
  - app/assets/config/rails_add_ons_manifest.js
178
192
  - app/assets/javascripts/rails/add_ons/application.js
179
193
  - app/assets/javascripts/rails/add_ons/application/acts-as-list.js.coffee
194
+ - app/assets/javascripts/rails/add_ons/application/autosubmit.js.coffee
180
195
  - app/assets/javascripts/rails/add_ons/application/widgets.js.coffee
181
196
  - app/assets/javascripts/rails_add_ons.js
182
- - app/assets/stylesheets/rails/add_ons/application.scss
183
- - app/assets/stylesheets/rails/add_ons/application/bootstrap_overrides.scss
184
- - app/assets/stylesheets/rails/add_ons/application/table_monospaced.scss
185
- - app/assets/stylesheets/rails/add_ons/application/widgets.scss
186
- - app/assets/stylesheets/rails/add_ons/bootstrap_v3_flex_extension.scss
197
+ - app/assets/stylesheets/rails/add_ons/application.css
198
+ - app/assets/stylesheets/rails/add_ons/application/bootstrap_overrides.css
199
+ - app/assets/stylesheets/rails/add_ons/application/table_monospaced.css
200
+ - app/assets/stylesheets/rails/add_ons/application/widgets.css
201
+ - app/assets/stylesheets/rails/add_ons/bootstrap_v3_flex_extension.css
187
202
  - app/assets/stylesheets/rails/add_ons/font_awesome.css
188
203
  - app/assets/stylesheets/rails_add_ons.css
189
204
  - app/caches/api/cache.rb
@@ -197,6 +212,7 @@ files:
197
212
  - app/concerns/component/collection_table/batch_actions_concern.rb
198
213
  - app/concerns/component/collection_table/boolean_concern.rb
199
214
  - app/concerns/component/resource_table/boolean_concern.rb
215
+ - app/concerns/controller/autosubmit_concern.rb
200
216
  - app/concerns/controller/query_conditions.rb
201
217
  - app/concerns/resources_controller/acts_as_list_concern.rb
202
218
  - app/concerns/resources_controller/acts_as_published_concern.rb
@@ -210,6 +226,7 @@ files:
210
226
  - app/concerns/resources_controller/resources.rb
211
227
  - app/concerns/resources_controller/rest_actions.rb
212
228
  - app/concerns/resources_controller/rest_resource_urls.rb
229
+ - app/concerns/resources_controller/search_form_concern.rb
213
230
  - app/concerns/resources_controller/sorting.rb
214
231
  - app/concerns/resources_controller/will_paginate.rb
215
232
  - app/concerns/service_controller/location_history.rb
@@ -223,6 +240,8 @@ files:
223
240
  - app/controllers/resources_controller/base.rb
224
241
  - app/controllers/service_controller/base.rb
225
242
  - app/extensions/object_extensions.rb
243
+ - app/helpers/rails/add_ons/autosubmit_helper.rb
244
+ - app/helpers/rails/add_ons/search_form_helper.rb
226
245
  - app/helpers/rails/add_ons/table_helper.rb
227
246
  - app/helpers/rails/add_ons/widget_helper.rb
228
247
  - app/parsers/api/resources_controller/condition_parser.rb
@@ -309,9 +328,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
309
328
  version: '0'
310
329
  required_rubygems_version: !ruby/object:Gem::Requirement
311
330
  requirements:
312
- - - ">="
331
+ - - ">"
313
332
  - !ruby/object:Gem::Version
314
- version: '0'
333
+ version: 1.3.1
315
334
  requirements: []
316
335
  rubyforge_project:
317
336
  rubygems_version: 2.6.11
@@ -1,3 +0,0 @@
1
- @import "application/bootstrap_overrides";
2
- @import "application/table_monospaced";
3
- @import "application/widgets";