rails-add_ons 2.1.1 → 2.2.0
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.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/app/assets/javascripts/rails/add_ons/application/acts-as-list.js.coffee +21 -0
- data/app/assets/javascripts/rails/add_ons/application.js +0 -2
- data/app/components/component/collection_table.rb +26 -2
- data/app/components/component/resource_table.rb +7 -1
- data/app/concerns/component/collection_table/acts_as_list_concern.rb +16 -0
- data/app/concerns/component/collection_table/acts_as_published_concern.rb +10 -0
- data/app/concerns/component/collection_table/batch_actions_concern.rb +12 -0
- data/app/concerns/component/collection_table/boolean_concern.rb +10 -0
- data/app/concerns/component/resource_table/boolean_concern.rb +10 -0
- data/app/concerns/resources_controller/acts_as_list_concern.rb +32 -0
- data/app/concerns/resources_controller/acts_as_published_concern.rb +73 -0
- data/app/concerns/resources_controller/awesome_nested_set_concern.rb +31 -0
- data/app/concerns/resources_controller/batch_actions_concern.rb +16 -0
- data/app/concerns/resources_controller/friendly_id_concern.rb +15 -0
- data/app/concerns/resources_controller/kaminari.rb +13 -11
- data/app/concerns/resources_controller/location_history.rb +31 -26
- data/app/concerns/resources_controller/pagination.rb +13 -11
- data/app/concerns/resources_controller/resource_inflections.rb +13 -11
- data/app/concerns/resources_controller/resources.rb +9 -7
- data/app/concerns/resources_controller/rest_actions.rb +77 -73
- data/app/concerns/resources_controller/rest_resource_urls.rb +25 -23
- data/app/concerns/resources_controller/sorting.rb +22 -14
- data/app/concerns/resources_controller/will_paginate.rb +14 -12
- data/app/concerns/service_controller/rest_actions.rb +15 -0
- data/app/helpers/rails/add_ons/table_helper.rb +10 -0
- data/app/views/component/_collection_table.haml +13 -12
- data/app/views/component/table/body_cells/_acts_as_list.haml +11 -0
- data/app/views/component/table/body_cells/_acts_as_published.haml +9 -0
- data/app/views/component/table/body_cells/_association.haml +5 -1
- data/app/views/component/table/body_cells/_batch_actions.haml +1 -0
- data/app/views/component/table/body_cells/_boolean.haml +4 -0
- data/app/views/component/table/header_cells/_batch_actions.haml +42 -0
- data/config/locales/de.yml +30 -1
- data/config/locales/en.yml +4 -1
- data/lib/generators/rails/add_ons/install_generator.rb +15 -0
- data/lib/generators/rails/add_ons/resources_controller_spec_generator.rb +53 -0
- data/lib/generators/rails/add_ons/templates/initializer.rb +7 -0
- data/lib/generators/rails/add_ons/templates/spec.rb +53 -0
- data/lib/rails/add_ons/configuration.rb +11 -0
- data/lib/rails/add_ons/shoulda/matchers/implement_create_action_matcher.rb +36 -4
- data/lib/rails/add_ons/shoulda/matchers/implement_update_action_matcher.rb +60 -17
- data/lib/rails/add_ons/version.rb +1 -1
- data/lib/rails/add_ons.rb +3 -2
- metadata +23 -2
@@ -1,91 +1,95 @@
|
|
1
|
-
module ResourcesController
|
2
|
-
|
3
|
-
|
4
|
-
included do
|
5
|
-
include ActionController::MimeResponds
|
6
|
-
|
7
|
-
respond_to :html
|
8
|
-
responders :flash
|
9
|
-
|
10
|
-
if respond_to?(:before_action)
|
11
|
-
before_action :load_collection, only: [:index]
|
12
|
-
before_action :load_resource, only: [:show, :edit, :destroy, :update]
|
13
|
-
before_action :initialize_resource, only: [:new]
|
14
|
-
before_action :initialize_resource_for_create, only: [:create]
|
15
|
-
else
|
16
|
-
before_filter :load_collection, only: [:index]
|
17
|
-
before_filter :load_resource, only: [:show, :edit, :destroy, :update]
|
18
|
-
before_filter :initialize_resource, only: [:new]
|
19
|
-
before_filter :initialize_resource_for_create, only: [:create]
|
20
|
-
end
|
21
|
-
end
|
1
|
+
module ResourcesController
|
2
|
+
module RestActions
|
3
|
+
extend ActiveSupport::Concern
|
22
4
|
|
23
|
-
|
24
|
-
|
25
|
-
def show; end
|
26
|
-
def edit; end
|
5
|
+
included do
|
6
|
+
include ActionController::MimeResponds
|
27
7
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
8
|
+
respond_to :html
|
9
|
+
responders :flash
|
10
|
+
|
11
|
+
if respond_to?(:before_action)
|
12
|
+
before_action :load_collection, only: [:index]
|
13
|
+
before_action :load_resource, only: [:show, :edit, :destroy, :update]
|
14
|
+
before_action :initialize_resource, only: [:new]
|
15
|
+
before_action :initialize_resource_for_create, only: [:create]
|
16
|
+
else
|
17
|
+
before_filter :load_collection, only: [:index]
|
18
|
+
before_filter :load_resource, only: [:show, :edit, :destroy, :update]
|
19
|
+
before_filter :initialize_resource, only: [:new]
|
20
|
+
before_filter :initialize_resource_for_create, only: [:create]
|
21
|
+
end
|
33
22
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
23
|
+
|
24
|
+
def index; end
|
25
|
+
def new; end
|
26
|
+
def show; end
|
27
|
+
def edit; end
|
28
|
+
|
29
|
+
def update
|
30
|
+
if Rails::VERSION::MAJOR < 4
|
31
|
+
@resource.update_attributes(permitted_params)
|
32
|
+
else
|
33
|
+
@resource.update(permitted_params)
|
34
|
+
end
|
35
|
+
|
36
|
+
if respond_to?(:after_update_location, true)
|
37
|
+
respond_with(respond_with_namespace, @resource, location: after_update_location)
|
38
|
+
else
|
39
|
+
respond_with(respond_with_namespace, @resource)
|
40
|
+
end
|
38
41
|
end
|
39
|
-
end
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
def destroy
|
44
|
+
@resource.destroy
|
45
|
+
if respond_to?(:after_destroy_location, true)
|
46
|
+
respond_with(respond_with_namespace, @resource, location: after_destroy_location)
|
47
|
+
else
|
48
|
+
respond_with(respond_with_namespace, @resource)
|
49
|
+
end
|
47
50
|
end
|
48
|
-
end
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
def create
|
53
|
+
@resource.save
|
54
|
+
if respond_to?(:after_create_location, true)
|
55
|
+
respond_with(respond_with_namespace, @resource, location: after_create_location)
|
56
|
+
else
|
57
|
+
respond_with(respond_with_namespace, @resource)
|
58
|
+
end
|
56
59
|
end
|
57
|
-
end
|
58
60
|
|
59
|
-
|
61
|
+
private
|
60
62
|
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
def respond_with_namespace
|
64
|
+
nil
|
65
|
+
end
|
64
66
|
|
65
|
-
|
66
|
-
|
67
|
-
|
67
|
+
def load_collection_scope
|
68
|
+
resource_class
|
69
|
+
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
def load_collection
|
72
|
+
@collection = load_collection_scope.all
|
73
|
+
end
|
72
74
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
def load_resource
|
77
|
-
@resource = load_resource_scope.find(params[:id])
|
78
|
-
end
|
75
|
+
def load_resource_scope
|
76
|
+
resource_class
|
77
|
+
end
|
79
78
|
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
def load_resource
|
80
|
+
@resource = load_resource_scope.find(params[:id])
|
81
|
+
end
|
83
82
|
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
def initialize_resource
|
84
|
+
@resource = resource_class.new
|
85
|
+
end
|
87
86
|
|
88
|
-
|
89
|
-
|
87
|
+
def initialize_resource_for_create
|
88
|
+
@resource = resource_class.new(permitted_params)
|
89
|
+
end
|
90
|
+
|
91
|
+
def permitted_params
|
92
|
+
raise "not implemented"
|
93
|
+
end
|
90
94
|
end
|
91
95
|
end
|
@@ -1,32 +1,34 @@
|
|
1
|
-
module ResourcesController
|
2
|
-
|
1
|
+
module ResourcesController
|
2
|
+
module RestResourceUrls
|
3
|
+
extend ActiveSupport::Concern
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
included do
|
6
|
+
helper_method :new_resource_path
|
7
|
+
helper_method :collection_path
|
8
|
+
helper_method :resource_path
|
9
|
+
helper_method :edit_resource_path
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
+
private
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def new_resource_path
|
15
|
+
resource_router.send(:url_for, { action: :new, only_path: true })
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def collection_path
|
19
|
+
resource_router.send(:url_for, { action: :index, only_path: true })
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def resource_path(resource)
|
23
|
+
resource_router.send(:url_for, { action: :show, id: resource, only_path: true })
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
def edit_resource_path(resource)
|
27
|
+
resource_router.send(:url_for, { action: :edit, id: resource, only_path: true })
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
def resource_router
|
31
|
+
self
|
32
|
+
end
|
31
33
|
end
|
32
34
|
end
|
@@ -1,20 +1,28 @@
|
|
1
|
-
module ResourcesController
|
2
|
-
|
1
|
+
module ResourcesController
|
2
|
+
module Sorting
|
3
|
+
private
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def load_collection_scope
|
6
|
+
add_order_scope(super)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def add_order_scope(base_scope)
|
10
|
+
if params[:sort_by].present?
|
11
|
+
if params[:sort_by].include?(' ') || params[:sort_direction].include?(' ')
|
12
|
+
raise "Possible SQL Injection attempt while trying to sort by #{params[:sort_by]} #{params[:sort_direction]}"
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
sort_by = params[:sort_by]
|
16
|
+
sort_direction = (params[:sort_direction] || :asc)
|
17
|
+
|
18
|
+
if sort_by.include?('.')
|
19
|
+
base_scope.reorder("#{sort_by} #{sort_direction}")
|
20
|
+
else
|
21
|
+
base_scope.reorder(sort_by => sort_direction)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
base_scope
|
25
|
+
end
|
18
26
|
end
|
19
27
|
end
|
20
28
|
end
|
@@ -1,17 +1,19 @@
|
|
1
|
-
module ResourcesController
|
2
|
-
|
1
|
+
module ResourcesController
|
2
|
+
module WillPaginate
|
3
|
+
extend ActiveSupport::Concern
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
included do
|
6
|
+
helper_method :paginate?
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def paginate?
|
10
|
+
true
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
+
private
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
def load_collection
|
16
|
+
@collection = load_collection_scope.paginate(page: params[:page])
|
17
|
+
end
|
16
18
|
end
|
17
|
-
end
|
19
|
+
end
|
@@ -62,6 +62,21 @@ module ServiceController::RestActions
|
|
62
62
|
@service = service_class.new({}, service_options)
|
63
63
|
end
|
64
64
|
|
65
|
+
# Override this method in your child class to manipulate your service before
|
66
|
+
# it performs.
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
# # app/controller/import_services_controller.rb
|
70
|
+
# class ImportServices < ApplicationServicesController
|
71
|
+
# #...
|
72
|
+
# private
|
73
|
+
#
|
74
|
+
# def initialize_service_for_create
|
75
|
+
# super
|
76
|
+
# @service.current_user_id = session['current_user_id']
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
#
|
65
80
|
def initialize_service_for_create
|
66
81
|
@service = service_class.new(hashified_params, service_options)
|
67
82
|
end
|
@@ -1,5 +1,15 @@
|
|
1
1
|
module Rails
|
2
2
|
module AddOns
|
3
|
+
# Provides helpers to render tables for collections and single resources.
|
4
|
+
# To use it you have to add it to your controller:
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# class PostsController < ApplicationController
|
9
|
+
# #...
|
10
|
+
# helper Rails::AddOns::TableHelper
|
11
|
+
# end
|
12
|
+
#
|
3
13
|
module TableHelper
|
4
14
|
def collection_table(options = {}, &block)
|
5
15
|
Component::CollectionTable.new(self, options, &block).perform
|
@@ -1,17 +1,18 @@
|
|
1
1
|
%table{ class: table_css_classes }
|
2
|
-
|
3
|
-
%
|
4
|
-
|
5
|
-
-
|
6
|
-
|
7
|
-
- if
|
8
|
-
-
|
2
|
+
- if show_header
|
3
|
+
%thead
|
4
|
+
%tr
|
5
|
+
- columns.each do |name, options|
|
6
|
+
- title = options.delete(:title)
|
7
|
+
- if title.nil?
|
8
|
+
- if resource_class.respond_to?(:human_attribute_name)
|
9
|
+
- title = resource_class.human_attribute_name(name)
|
10
|
+
- else
|
11
|
+
- title = name
|
12
|
+
- if options.has_key?(:sort)
|
13
|
+
%td= sort_link(name, title, options[:sort])
|
9
14
|
- else
|
10
|
-
|
11
|
-
- if options.has_key?(:sort)
|
12
|
-
%td= sort_link(name, title, options[:sort])
|
13
|
-
- else
|
14
|
-
%td= title
|
15
|
+
%td= title
|
15
16
|
%tbody
|
16
17
|
- collection.each do |resource|
|
17
18
|
- tr_options = { class: resource_class.name.underscore.gsub('/', '-') }
|
@@ -0,0 +1,11 @@
|
|
1
|
+
:ruby
|
2
|
+
scope = options.delete(:scope)
|
3
|
+
data_attributes = {
|
4
|
+
'acts-as-list-item': true,
|
5
|
+
'acts-as-list-item-uid': resource.to_param,
|
6
|
+
'acts-as-list-item-on-drop-target': url_for([:reposition, resource])
|
7
|
+
}
|
8
|
+
data_attributes['acts-as-list-item-scope'] = "#{scope}-#{resource.send(scope)}" if scope.present?
|
9
|
+
|
10
|
+
%span.btn.btn-xs.btn-default.acts-as-list-item{ data: data_attributes }
|
11
|
+
%span.glyphicon.glyphicon-sort.fas.fa-sort
|
@@ -0,0 +1,9 @@
|
|
1
|
+
- link_path = controller.url_for(action: :toggle_published, id: resource.to_param)
|
2
|
+
- if resource.published?
|
3
|
+
= button_to(link_path, class: 'btn btn-xs btn-danger btn-responsive', method: :post) do
|
4
|
+
%span.glyphicon.glyphicon-eye-close
|
5
|
+
%span.btn-text= t('.unpublish', default: t('acts_as_published.actions.unpublish'))
|
6
|
+
- else
|
7
|
+
= button_to(link_path, class: 'btn btn-xs btn-success btn-responsive', method: :post) do
|
8
|
+
%span.glyphicon.glyphicon-eye-open
|
9
|
+
%span.btn-text= t('.publish', default: t('acts_as_published.actions.publish'))
|
@@ -1,5 +1,9 @@
|
|
1
1
|
- label = if options[:label_method].present?
|
2
|
-
-
|
2
|
+
- case options[:label_method]
|
3
|
+
- when Proc
|
4
|
+
- options[:label_method].call(resource.send(name))
|
5
|
+
- else
|
6
|
+
- resource.send(name).try(options[:label_method])
|
3
7
|
- else
|
4
8
|
- resource.send(name)
|
5
9
|
- link_to = options[:link_to]
|
@@ -0,0 +1 @@
|
|
1
|
+
= check_box_tag "ids[]", resource.id, false, class: 'batch-action-checkbox'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
:css
|
2
|
+
#batch-action-dropdown {
|
3
|
+
display: none;
|
4
|
+
}
|
5
|
+
|
6
|
+
%form{ method: 'post', id: 'batch-action-form' }
|
7
|
+
= hidden_field_tag :authenticity_token, form_authenticity_token
|
8
|
+
.dropdown.batch-action-dropdown
|
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')
|
11
|
+
%span.caret
|
12
|
+
%ul.dropdown-menu{"aria-labelledby" => 'batch-action-dropdown' }
|
13
|
+
- options[:actions].each do |action, target|
|
14
|
+
%li
|
15
|
+
%a{ href: target, class: 'batch-action-form-submit-link' }= t(".#{action}")
|
16
|
+
|
17
|
+
:javascript
|
18
|
+
$(document).ready(function() {
|
19
|
+
$('.batch-action-checkbox').click(function() {
|
20
|
+
var check_count = $('.batch-action-checkbox:checked').size();
|
21
|
+
if( check_count > 0 ) {
|
22
|
+
$("#batch-action-dropdown").show();
|
23
|
+
} else {
|
24
|
+
$("#batch-action-dropdown").hide();
|
25
|
+
}
|
26
|
+
});
|
27
|
+
|
28
|
+
$('#batch-action-form').submit(function() {
|
29
|
+
$('#batch-action-form input:checked').remove();
|
30
|
+
var selected_items = $('.batch-action-checkbox:checked').clone();
|
31
|
+
selected_items.css('display', 'none');
|
32
|
+
$('#batch-action-form').append(selected_items);
|
33
|
+
return true;
|
34
|
+
});
|
35
|
+
|
36
|
+
$('.batch-action-form-submit-link').click(function(e) {
|
37
|
+
e.preventDefault();
|
38
|
+
var target = $(this).attr('href');
|
39
|
+
$("#batch-action-form").attr("action", target);
|
40
|
+
$('#batch-action-form').submit();
|
41
|
+
});
|
42
|
+
});
|
data/config/locales/de.yml
CHANGED
@@ -4,10 +4,20 @@ de:
|
|
4
4
|
component:
|
5
5
|
collection_table:
|
6
6
|
column_titles:
|
7
|
-
|
7
|
+
acts_as_list: Sortierung
|
8
|
+
acts_as_published: Veröffentlichung
|
9
|
+
awesome_nested_set: Sortierung
|
8
10
|
delete: Löschen
|
9
11
|
edit: Bearbeiten
|
10
12
|
show: Anzeigen
|
13
|
+
table:
|
14
|
+
body_cells:
|
15
|
+
boolean:
|
16
|
+
'true': Ja
|
17
|
+
'false': Nein
|
18
|
+
header_cells:
|
19
|
+
batch_actions:
|
20
|
+
destroy: Löschen
|
11
21
|
flash:
|
12
22
|
actions:
|
13
23
|
create:
|
@@ -20,6 +30,25 @@ de:
|
|
20
30
|
perform:
|
21
31
|
notice: "%{resource_name} wurde ausgeführt."
|
22
32
|
alert: "%{resource_name} konnte nicht ausgeführt werden. Es traten folgende Fehler auf: %{errors}"
|
33
|
+
acts_as_list:
|
34
|
+
flash:
|
35
|
+
actions:
|
36
|
+
reposition:
|
37
|
+
inserted_after: "%{inserted_resource} nach %{target_resource} eingefügt"
|
38
|
+
inserted_before: "%{inserted_resource} vor %{target_resource} eingefügt"
|
39
|
+
acts_as_published:
|
40
|
+
flash:
|
41
|
+
actions:
|
42
|
+
toggle_published:
|
43
|
+
published:
|
44
|
+
notice: "%{resource_name} veröffentlicht."
|
45
|
+
unpublished:
|
46
|
+
notice: "%{resource_name} zurückgezogen."
|
47
|
+
awesome_nested_set:
|
48
|
+
flash:
|
49
|
+
actions:
|
50
|
+
reposition:
|
51
|
+
notice: "%{inserted_resource} nach %{target_resource} eingefügt"
|
23
52
|
i18n:
|
24
53
|
locales:
|
25
54
|
en: English
|
data/config/locales/en.yml
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rails
|
2
|
+
module AddOns
|
3
|
+
module Generators
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
desc 'Generates the initializer'
|
6
|
+
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
def generate_initializer
|
10
|
+
template 'initializer.rb', 'config/initializers/rails-add_ons.rb'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Rails
|
2
|
+
module AddOns
|
3
|
+
# This will generate specs for create, read, update, delete and list.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
#
|
7
|
+
# rails g rails:add_ons:resources_controller_spec --uri /de/backend/uploads
|
8
|
+
# create spec/features/de/backend/uploads_feature_spec.rb
|
9
|
+
#
|
10
|
+
# If your resource class does not match the last part of your url (i.e.
|
11
|
+
# /de/posts would guess the resource class to Post) you can specify the resource
|
12
|
+
# name like this:
|
13
|
+
#
|
14
|
+
# RESOURCE_CLASS=Blog::Post rails g rails:add_ons:resources_controller_spec --uri /de/posts
|
15
|
+
# create spec/features/de/posts_feature_spec.rb
|
16
|
+
#
|
17
|
+
class ResourcesControllerSpecGenerator < Rails::Generators::Base
|
18
|
+
desc 'Generates CRUDL specs for REST resources'
|
19
|
+
|
20
|
+
source_root File.expand_path('../templates', __FILE__)
|
21
|
+
|
22
|
+
class_option :uri, type: :string, required: true
|
23
|
+
|
24
|
+
def uri
|
25
|
+
@uri ||= options['uri']
|
26
|
+
end
|
27
|
+
|
28
|
+
def edit_form_dom_selector
|
29
|
+
".edit_#{resource_class.demodulize.underscore}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_form_dom_selector
|
33
|
+
"#new_#{resource_class.demodulize.underscore}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def resource_class
|
37
|
+
@resource_class ||= ENV.fetch('RESOURCE_CLASS') { @uri.split('/').last.camelize.singularize }
|
38
|
+
end
|
39
|
+
|
40
|
+
def factory_name
|
41
|
+
underscored_resource_class
|
42
|
+
end
|
43
|
+
|
44
|
+
def underscored_resource_class
|
45
|
+
@undescored_resource_class ||= resource_class.underscore.gsub('/', '_')
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_spec
|
49
|
+
template 'spec.rb', "spec/features#{uri}_feature_spec.rb"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe '<%= uri %>', type: :feature do
|
4
|
+
let(:resource_class) { <%= resource_class %> }
|
5
|
+
let(:resource) { create(:<%= factory_name %>) }
|
6
|
+
let(:resources) { create_list(:<%= factory_name %>, 3) }
|
7
|
+
|
8
|
+
# List
|
9
|
+
it { resources; expect(subject).to implement_index_action(self) }
|
10
|
+
|
11
|
+
# Create
|
12
|
+
it {
|
13
|
+
expect(subject).to implement_create_action(self)
|
14
|
+
.for(resource_class)
|
15
|
+
.within_form('<%= new_form_dom_selector %>') {
|
16
|
+
# fill the needed form inputs via capybara here
|
17
|
+
#
|
18
|
+
# Example:
|
19
|
+
#
|
20
|
+
# select 'de', from: 'slider[locale]'
|
21
|
+
# fill_in 'slider[name]', with: 'My first slider'
|
22
|
+
# check 'slider[auto_start]'
|
23
|
+
# fill_in 'slider[interval]', with: '3'
|
24
|
+
}
|
25
|
+
.increasing{ <%= resource_class %>.count }.by(1)
|
26
|
+
}
|
27
|
+
|
28
|
+
# Read
|
29
|
+
it { expect(subject).to implement_show_action(self).for(resource) }
|
30
|
+
|
31
|
+
# Update
|
32
|
+
it {
|
33
|
+
expect(subject).to implement_update_action(self)
|
34
|
+
.for(resource)
|
35
|
+
.within_form('<%= edit_form_dom_selector %>') {
|
36
|
+
# fill the needed form inputs via capybara here
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
#
|
40
|
+
# fill_in 'slider[name]', with: 'New name'
|
41
|
+
}
|
42
|
+
.updating
|
43
|
+
.from(resource.attributes)
|
44
|
+
.to({ }) # Example: .to({ 'name' => 'New name' })
|
45
|
+
}
|
46
|
+
|
47
|
+
# Delete
|
48
|
+
it {
|
49
|
+
expect(subject).to implement_delete_action(self)
|
50
|
+
.for(resource)
|
51
|
+
.reducing{ resource_class.count }.by(1)
|
52
|
+
}
|
53
|
+
end
|