rails-add_ons 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|