godmin 0.11.0 → 0.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +42 -2
- data/app/assets/javascripts/godmin/navigation.js +1 -1
- data/app/assets/javascripts/godmin/select-boxes.js +6 -1
- data/app/assets/stylesheets/godmin/index.css.scss +6 -0
- data/app/views/godmin/resource/_actions.html.erb +1 -0
- data/app/views/godmin/resource/_breadcrumb.html.erb +44 -17
- data/app/views/godmin/resource/_export_actions.html.erb +15 -0
- data/app/views/godmin/resource/columns/_actions.html.erb +4 -3
- data/app/views/godmin/resource/edit.html.erb +1 -1
- data/app/views/godmin/resource/index.csv.csvbuilder +5 -0
- data/app/views/godmin/resource/index.html.erb +1 -1
- data/app/views/godmin/resource/index.json.jbuilder +3 -0
- data/app/views/godmin/resource/new.html.erb +1 -1
- data/app/views/godmin/resource/show.html.erb +10 -1
- data/app/views/godmin/resource/show.json.jbuilder +1 -0
- data/config/locales/en.yml +5 -1
- data/config/locales/sv.yml +5 -1
- data/godmin.gemspec +1 -0
- data/lib/generators/godmin/resource/templates/resource_service.rb +1 -0
- data/lib/godmin.rb +1 -1
- data/lib/godmin/authorization.rb +3 -3
- data/lib/godmin/helpers/filters.rb +7 -1
- data/lib/godmin/resources/resource_controller.rb +13 -4
- data/lib/godmin/resources/resource_service.rb +32 -6
- data/lib/godmin/resources/resource_service/batch_actions.rb +2 -2
- data/lib/godmin/resources/resource_service/filters.rb +8 -1
- data/lib/godmin/version.rb +1 -1
- data/test/lib/godmin/resources/resource_service/batch_actions_test.rb +1 -7
- data/test/lib/godmin/resources/resource_service/filters_test.rb +10 -0
- data/test/lib/godmin/resources/resource_service_test.rb +8 -0
- data/test/test_helper.rb +14 -3
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70806f3cd970ce6827a4bceb51eace7bd9b0c4a9
|
4
|
+
data.tar.gz: 47d369f0024eeb1a2d12d2d3785a8aa9ce351802
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da4aa4c02bfdad59b0a29d3915539dcaeaca2f163916d8c7e57540e27e8116c5f48feff3aeed0ede9511f1600b84def6776591ee9f25eea6577c8feaf21c25b6
|
7
|
+
data.tar.gz: 38339632c4410e9c20db4f413a9f530a3d8014479741285188cf241365570080fdcf4dfc787eded23e3eb74471971b09001a79f4ee06c8001162b3021ea5ad37
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 0.11.1 - 2015-05-20
|
4
|
+
Features
|
5
|
+
- Adds `destroy_resource` method to `ResourceService`
|
6
|
+
- Adds query param to authorize
|
7
|
+
- Adds authorization to batch actions (https://github.com/varvet/godmin/issues/33)
|
8
|
+
- Adds show page (https://github.com/varvet/godmin/issues/77)
|
9
|
+
- Adds option to change add text on dropdowns (https://github.com/varvet/godmin/pull/106)
|
10
|
+
- Adds CSV export (https://github.com/varvet/godmin/issues/86)
|
11
|
+
- JSON export can now be controlled using `attrs_for_export` or by overriding a jbuilder
|
12
|
+
|
13
|
+
Bug fixes
|
14
|
+
- Fixes a regression where filter labels were not translated
|
15
|
+
|
3
16
|
### 0.11.0 - 2015-04-13
|
4
17
|
Other
|
5
18
|
- Split resources into controllers and service objects (https://github.com/varvet/godmin/pull/79)
|
data/README.md
CHANGED
@@ -158,11 +158,12 @@ class ArticleService
|
|
158
158
|
include Godmin::Resources::ResourceService
|
159
159
|
|
160
160
|
attrs_for_index :title, :published
|
161
|
+
attrs_for_show :title, :published
|
161
162
|
attrs_for_form :title, :published
|
162
163
|
end
|
163
164
|
```
|
164
165
|
|
165
|
-
Using `attrs_for_index` we can control what fields are displayed in the table listing, and using `attrs_for_form` we can control what fields are available in the new and edit forms. We can, for instance, add the `body` field to `attrs_for_form` to make it appear in forms:
|
166
|
+
Using `attrs_for_index` we can control what fields are displayed in the table listing, using `attrs_for_show` we can control what fields are displayed on the show page, and using `attrs_for_form` we can control what fields are available in the new and edit forms. We can, for instance, add the `body` field to `attrs_for_form` to make it appear in forms:
|
166
167
|
|
167
168
|
```ruby
|
168
169
|
attrs_for_form :title, :body, :published
|
@@ -261,11 +262,13 @@ class ArticlesController < ApplicationController
|
|
261
262
|
private
|
262
263
|
|
263
264
|
def redirect_after_batch_action_publish
|
264
|
-
|
265
|
+
articles_path(scope: :published)
|
265
266
|
end
|
266
267
|
end
|
267
268
|
```
|
268
269
|
|
270
|
+
If you are using Godmin's built in authorization functionality you must [authorize your batch actions in your policy](#batch-action-authorization).
|
271
|
+
|
269
272
|
### Resource fetching, building and saving
|
270
273
|
|
271
274
|
Resources are made available to the views through instance variables. The index view can access the resources using `@resources` while show, new and edit can access the single resource using `@resource`. In addition, the resource class is available as `@resource_class` and the service object is available as `@resource_service`.
|
@@ -279,6 +282,7 @@ In order to modify resource fetching and construction, these methods can be over
|
|
279
282
|
- `build_resource`
|
280
283
|
- `create_resource`
|
281
284
|
- `update_resource`
|
285
|
+
- `destroy_resource`
|
282
286
|
|
283
287
|
To change the class name of the resource from the default based on the service class name:
|
284
288
|
|
@@ -370,6 +374,18 @@ class ArticleService
|
|
370
374
|
end
|
371
375
|
```
|
372
376
|
|
377
|
+
To change the way a resource is destroyed in the `destroy` action:
|
378
|
+
|
379
|
+
```ruby
|
380
|
+
class ArticleService
|
381
|
+
include Godmin::Resources::ResourceService
|
382
|
+
|
383
|
+
def destroy_resource(resource)
|
384
|
+
resource.paranoid_destroy
|
385
|
+
end
|
386
|
+
end
|
387
|
+
```
|
388
|
+
|
373
389
|
#### Strong parameters
|
374
390
|
|
375
391
|
When using `attrs_for_form`, parameters are automatically permitted. If building a custom form, see the [forms](#forms) section, parameters can be permitted by overriding the `resource_params` method in the controller:
|
@@ -632,11 +648,16 @@ class ArticlePolicy < Godmin::Authorization::Policy
|
|
632
648
|
def destroy?
|
633
649
|
update?
|
634
650
|
end
|
651
|
+
|
652
|
+
def batch_action_destroy?
|
653
|
+
destroy?
|
654
|
+
end
|
635
655
|
end
|
636
656
|
```
|
637
657
|
|
638
658
|
That is, everyone can list and view articles, only editors can create them, and only unpublished articles can be updated and destroyed.
|
639
659
|
|
660
|
+
### Handle unauthorized access
|
640
661
|
When a user is not authorized to access a resource, a `NotAuthorizedError` is raised. By default this error is rescued by Godmin and turned into a status code `403 Forbidden` response.
|
641
662
|
If you want to change this behaviour you can rescue the error yourself in the appropriate `ApplicationController`:
|
642
663
|
|
@@ -653,6 +674,7 @@ class ApplicationController < ActionController::Base
|
|
653
674
|
end
|
654
675
|
```
|
655
676
|
|
677
|
+
### Override policy object
|
656
678
|
If you wish to specify what policy to use manually, override the following method in your model. It does not have to be an ActiveRecord object, but any object will do.
|
657
679
|
|
658
680
|
```ruby
|
@@ -663,6 +685,17 @@ class Article
|
|
663
685
|
end
|
664
686
|
```
|
665
687
|
|
688
|
+
### Batch action authorization
|
689
|
+
Batch actions must be authorized in your policy if you are using Godmin's built in authorization functionality. The policy method is called once for each record before they are passed to the batch action method defined by the user. If a user is not allowed to "batch action" a particular record, it will be filtered out before passed to the batch action method. Note that this does not raise any `NotAuthorizedError`.
|
690
|
+
|
691
|
+
```ruby
|
692
|
+
class ArticlePolicy < Godmin::Authorization::Policy
|
693
|
+
def batch_action_destroy?
|
694
|
+
@record.user_id == user.id
|
695
|
+
end
|
696
|
+
end
|
697
|
+
```
|
698
|
+
|
666
699
|
## Localization
|
667
700
|
|
668
701
|
Godmin supports localization out of the box. For a list of translatable strings, [look here](https://github.com/varvet/godmin/blob/master/config/locales/en.yml).
|
@@ -755,6 +788,13 @@ f.select :authors, Author.all, {}, data: { behavior: "select-box" }
|
|
755
788
|
f.text_field :tag_list, data: { behavior: "select-box" }
|
756
789
|
```
|
757
790
|
|
791
|
+
If you want to change the text that appears when an option does not exist and will be created, set the data attribute `data-add-label`.
|
792
|
+
|
793
|
+
```ruby
|
794
|
+
f.text_field :tag_list, data: { behavior: "select-box", add_label: "Create:" }
|
795
|
+
#=> Create: foobar...
|
796
|
+
```
|
797
|
+
|
758
798
|
If the field is added post page render, it can be initialized manually:
|
759
799
|
|
760
800
|
```js
|
@@ -13,7 +13,7 @@ Godmin.Navigation = (function() {
|
|
13
13
|
}
|
14
14
|
|
15
15
|
function removeEmptyDropdowns() {
|
16
|
-
$('.navbar-nav .dropdown').each(function() {
|
16
|
+
$('.navbar-nav .dropdown, .breadcrumb .dropdown').each(function() {
|
17
17
|
if ($(this).find('li').length === 0) {
|
18
18
|
$(this).remove();
|
19
19
|
}
|
@@ -14,7 +14,12 @@ Godmin.SelectBoxes = (function() {
|
|
14
14
|
|
15
15
|
function initializeSelectBox($el, options) {
|
16
16
|
var defaults = {
|
17
|
-
inputClass: 'selectize-input'
|
17
|
+
inputClass: 'selectize-input',
|
18
|
+
render: {
|
19
|
+
option_create: function(data, escape) {
|
20
|
+
return '<div class="create">' + (this.$input.data("add-label") || "+") + ' <strong>' + escape(data.input) + '</strong>…</div>';
|
21
|
+
}
|
22
|
+
}
|
18
23
|
};
|
19
24
|
|
20
25
|
$el.selectize($.extend(defaults, options));
|
@@ -1,18 +1,45 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
1
|
+
<div id="breadcrumb">
|
2
|
+
<ol class="breadcrumb">
|
3
|
+
<% if action_name == "index" %>
|
4
|
+
<li class="active">
|
5
|
+
<%= @resource_class.model_name.human(count: 2) %>
|
6
|
+
</li>
|
7
|
+
<% else %>
|
8
|
+
<li>
|
9
|
+
<%= link_to @resource_class.model_name.human(count: 2), @resource_class %>
|
10
|
+
</li>
|
11
|
+
<li class="active">
|
12
|
+
<% if @resource.new_record? %>
|
13
|
+
<%= t("helpers.submit.create", model: @resource_class.model_name.human) %>
|
14
|
+
<% else %>
|
15
|
+
<%= @resource.to_s %>
|
16
|
+
<% end %>
|
17
|
+
</li>
|
18
|
+
<% if @resource.persisted? %>
|
19
|
+
<li class="dropdown pull-right">
|
20
|
+
<a href="#" data-toggle="dropdown" role="button">
|
21
|
+
<%= translate_scoped("actions.label") %> <span class="caret"></span>
|
22
|
+
</a>
|
23
|
+
<ul class="dropdown-menu">
|
24
|
+
<% if policy(@resource).show? && action_name != "show" %>
|
25
|
+
<li>
|
26
|
+
<%= link_to translate_scoped("actions.show"), @resource %>
|
27
|
+
</li>
|
28
|
+
<% end %>
|
29
|
+
<% if policy(@resource).edit? && action_name != "edit" %>
|
30
|
+
<li>
|
31
|
+
<%= link_to translate_scoped("actions.edit"), [:edit, @resource] %>
|
32
|
+
</li>
|
33
|
+
<% end %>
|
34
|
+
<% if policy(@resource).destroy? %>
|
35
|
+
<li>
|
36
|
+
<%= link_to translate_scoped("actions.destroy"), @resource, method: :delete,
|
37
|
+
data: { confirm: translate_scoped("actions.confirm_message") } %>
|
38
|
+
</li>
|
39
|
+
<% end %>
|
40
|
+
</ul>
|
41
|
+
</li>
|
15
42
|
<% end %>
|
16
|
-
|
17
|
-
|
18
|
-
</
|
43
|
+
<% end %>
|
44
|
+
</ol>
|
45
|
+
</div>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% if @resource_service.attrs_for_export.present? %>
|
2
|
+
<div class="btn-group">
|
3
|
+
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
4
|
+
<%= translate_scoped("actions.export") %> <span class="caret"></span>
|
5
|
+
</button>
|
6
|
+
<ul class="dropdown-menu" role="menu">
|
7
|
+
<li>
|
8
|
+
<%= link_to "#{translate_scoped("actions.export_as")} JSON", url_for(params.merge(only_path: true, format: "json")) %>
|
9
|
+
</li>
|
10
|
+
<li>
|
11
|
+
<%= link_to "#{translate_scoped("actions.export_as")} CSV", url_for(params.merge(only_path: true, format: "csv")) %>
|
12
|
+
</li>
|
13
|
+
</ul>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
@@ -1,11 +1,12 @@
|
|
1
1
|
<div class="btn-group btn-group-sm pull-right">
|
2
2
|
<% if policy(resource).show? %>
|
3
|
-
<%= link_to translate_scoped("
|
3
|
+
<%= link_to translate_scoped("actions.show"), resource, class: "btn btn-default" %>
|
4
4
|
<% end %>
|
5
5
|
<% if policy(resource).edit? %>
|
6
|
-
<%= link_to translate_scoped("
|
6
|
+
<%= link_to translate_scoped("actions.edit"), [:edit, resource], class: "btn btn-default" %>
|
7
7
|
<% end %>
|
8
8
|
<% if policy(resource).destroy? %>
|
9
|
-
<%= link_to translate_scoped("
|
9
|
+
<%= link_to translate_scoped("actions.destroy"), resource, method: :delete,
|
10
|
+
class: "btn btn-danger", data: { confirm: translate_scoped("actions.confirm_message") } %>
|
10
11
|
<% end %>
|
11
12
|
</div>
|
@@ -1 +1,10 @@
|
|
1
|
-
|
1
|
+
<%= render partial: "breadcrumb" %>
|
2
|
+
|
3
|
+
<table class="table table-bordere table-striped">
|
4
|
+
<% @resource_service.attrs_for_show.each do |attr| %>
|
5
|
+
<tr>
|
6
|
+
<th><%= @resource_class.human_attribute_name(attr) %></th>
|
7
|
+
<td><%= column_value(@resource, attr) %></td>
|
8
|
+
</tr>
|
9
|
+
<% end %>
|
10
|
+
</table>
|
@@ -0,0 +1 @@
|
|
1
|
+
json.extract! @resource, *@resource_service.attrs_for_export
|
data/config/locales/en.yml
CHANGED
@@ -14,11 +14,14 @@ en:
|
|
14
14
|
buttons:
|
15
15
|
apply: Filter
|
16
16
|
clear: Clear filter
|
17
|
-
|
17
|
+
actions:
|
18
|
+
label: Actions
|
18
19
|
show: Show
|
19
20
|
edit: Edit
|
20
21
|
destroy: Destroy
|
21
22
|
confirm_message: Are you sure?
|
23
|
+
export: Export
|
24
|
+
export_as: As
|
22
25
|
sessions:
|
23
26
|
sign_in: Sign in
|
24
27
|
sign_out: Sign out
|
@@ -29,6 +32,7 @@ en:
|
|
29
32
|
create: "%{resource} was successfully created"
|
30
33
|
update: "%{resource} was successfully updated"
|
31
34
|
destroy: "%{resource} was successfully destroyed"
|
35
|
+
batch_action: "%{number_of_affected_records} of %{total_number_of_records} %{resource} were affected"
|
32
36
|
pagination:
|
33
37
|
first: "First"
|
34
38
|
last: "Last"
|
data/config/locales/sv.yml
CHANGED
@@ -14,11 +14,14 @@ sv:
|
|
14
14
|
buttons:
|
15
15
|
apply: Filtrera
|
16
16
|
clear: Rensa filter
|
17
|
-
|
17
|
+
actions:
|
18
|
+
label: Alternativ
|
18
19
|
show: Visa
|
19
20
|
edit: Ändra
|
20
21
|
destroy: Ta bort
|
21
22
|
confirm_message: Är du säker?
|
23
|
+
export: Exportera
|
24
|
+
export_as: Som
|
22
25
|
sessions:
|
23
26
|
sign_in: Logga in
|
24
27
|
sign_out: Logga ut
|
@@ -29,6 +32,7 @@ sv:
|
|
29
32
|
create: "%{resource} skapades"
|
30
33
|
update: "%{resource} uppdaterades"
|
31
34
|
destroy: "%{resource} togs bort"
|
35
|
+
batch_action: "%{number_of_affected_records} av %{total_number_of_records} %{resource} påverkades"
|
32
36
|
pagination:
|
33
37
|
first: "Första"
|
34
38
|
last: "Sista"
|
data/godmin.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |gem|
|
|
23
23
|
gem.add_dependency "bootstrap-sass", "~> 3.3.3"
|
24
24
|
gem.add_dependency "bootstrap_form", "~> 2.2.0"
|
25
25
|
gem.add_dependency "coffee-rails", [">= 4.0", "< 4.2"]
|
26
|
+
gem.add_dependency "csv_builder", "~> 2.1.1"
|
26
27
|
gem.add_dependency "momentjs-rails", ">= 2.8.1"
|
27
28
|
gem.add_dependency "rails", "~> 4.0"
|
28
29
|
gem.add_dependency "sass-rails", ">= 4.0"
|
@@ -3,6 +3,7 @@ class <%= class_name %>Service
|
|
3
3
|
include Godmin::Resources::ResourceService
|
4
4
|
|
5
5
|
attrs_for_index <%= @attributes.map { |x| ":#{x}" }.join(", ") %>
|
6
|
+
attrs_for_show <%= @attributes.map { |x| ":#{x}" }.join(", ") %>
|
6
7
|
attrs_for_form <%= @attributes.map { |x| ":#{x}" }.join(", ") %>
|
7
8
|
end
|
8
9
|
<% end -%>
|
data/lib/godmin.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "bootstrap-sass"
|
2
2
|
require "bootstrap_form"
|
3
|
+
require "csv_builder"
|
3
4
|
require "momentjs-rails"
|
4
5
|
require "selectize-rails"
|
5
6
|
require "godmin/application_controller"
|
@@ -11,7 +12,6 @@ require "godmin/rails"
|
|
11
12
|
require "godmin/resolver"
|
12
13
|
require "godmin/resources/resource_controller"
|
13
14
|
require "godmin/resources/resource_service"
|
14
|
-
require "godmin/version"
|
15
15
|
|
16
16
|
module Godmin
|
17
17
|
mattr_accessor :namespace
|
data/lib/godmin/authorization.rb
CHANGED
@@ -13,11 +13,11 @@ module Godmin
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def authorize(record)
|
16
|
+
def authorize(record, query = nil)
|
17
17
|
policy = policy(record)
|
18
18
|
|
19
|
-
unless policy.public_send(action_name + "?")
|
20
|
-
|
19
|
+
unless policy.public_send(query || action_name + "?")
|
20
|
+
fail NotAuthorizedError
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -26,6 +26,7 @@ module Godmin
|
|
26
26
|
text_field(
|
27
27
|
name, {
|
28
28
|
name: "filter[#{name}]",
|
29
|
+
label: @template.translate_scoped("filters.labels.#{name}", default: name.to_s.titleize),
|
29
30
|
value: default_filter_value(name),
|
30
31
|
placeholder: @template.translate_scoped("filters.labels.#{name}", default: name.to_s.titleize),
|
31
32
|
wrapper_class: "filter"
|
@@ -95,7 +96,12 @@ module Godmin
|
|
95
96
|
end
|
96
97
|
|
97
98
|
select(
|
98
|
-
name, choices, {
|
99
|
+
name, choices, {
|
100
|
+
wrapper_class: "filter",
|
101
|
+
label: @template.translate_scoped("filters.labels.#{name}", default: name.to_s.titleize),
|
102
|
+
include_hidden: true,
|
103
|
+
include_blank: true
|
104
|
+
}, {
|
99
105
|
data: { behavior: "select-box" }
|
100
106
|
}.deep_merge(html_options)
|
101
107
|
)
|
@@ -21,14 +21,15 @@ module Godmin
|
|
21
21
|
def index
|
22
22
|
respond_to do |format|
|
23
23
|
format.html
|
24
|
-
format.json
|
24
|
+
format.json
|
25
|
+
format.csv
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
29
|
def show
|
29
30
|
respond_to do |format|
|
30
31
|
format.html
|
31
|
-
format.json
|
32
|
+
format.json
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
@@ -65,7 +66,7 @@ module Godmin
|
|
65
66
|
end
|
66
67
|
|
67
68
|
def destroy
|
68
|
-
@resource
|
69
|
+
@resource_service.destroy_resource(@resource)
|
69
70
|
|
70
71
|
respond_to do |format|
|
71
72
|
format.html { redirect_to redirect_after_destroy, notice: redirect_flash_message }
|
@@ -154,9 +155,17 @@ module Godmin
|
|
154
155
|
return false unless params[:batch_action].present?
|
155
156
|
|
156
157
|
item_ids = params[:id].split(",").map(&:to_i)
|
158
|
+
records = @resource_class.find(item_ids)
|
159
|
+
if authorization_enabled?
|
160
|
+
records = records.select { |r| policy(r).send("batch_action_#{params[:batch_action]}?") }
|
161
|
+
end
|
157
162
|
|
158
|
-
if @resource_service.batch_action(params[:batch_action],
|
163
|
+
if @resource_service.batch_action(params[:batch_action], records)
|
159
164
|
flash[:updated_ids] = item_ids
|
165
|
+
flash[:notice] = translate_scoped("flash.batch_action",
|
166
|
+
number_of_affected_records: records.length,
|
167
|
+
total_number_of_records: item_ids.length,
|
168
|
+
resource: @resource_class.model_name.human(count: item_ids.length))
|
160
169
|
|
161
170
|
if respond_to?("redirect_after_batch_action_#{params[:batch_action]}", true)
|
162
171
|
redirect_to send("redirect_after_batch_action_#{params[:batch_action]}") and return true
|
@@ -23,7 +23,11 @@ module Godmin
|
|
23
23
|
|
24
24
|
# TODO: should this raise its own error?
|
25
25
|
def resource_class
|
26
|
-
@options[:resource_class] ||
|
26
|
+
@options[:resource_class] || resource_class_name.constantize
|
27
|
+
end
|
28
|
+
|
29
|
+
def resource_class_name
|
30
|
+
self.class.name.demodulize.chomp("Service")
|
27
31
|
end
|
28
32
|
|
29
33
|
def resources_relation
|
@@ -31,11 +35,11 @@ module Godmin
|
|
31
35
|
end
|
32
36
|
|
33
37
|
def resources(params)
|
34
|
-
apply_pagination(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
resources_relation
|
38
|
+
apply_pagination(
|
39
|
+
params[:page], apply_order(
|
40
|
+
params[:order], apply_filters(
|
41
|
+
params[:filter], apply_scope(
|
42
|
+
params[:scope], resources_relation
|
39
43
|
)
|
40
44
|
)
|
41
45
|
)
|
@@ -58,24 +62,46 @@ module Godmin
|
|
58
62
|
resource.update(params)
|
59
63
|
end
|
60
64
|
|
65
|
+
def destroy_resource(resource)
|
66
|
+
resource.destroy
|
67
|
+
end
|
68
|
+
|
61
69
|
def attrs_for_index
|
62
70
|
self.class.attrs_for_index
|
63
71
|
end
|
64
72
|
|
73
|
+
def attrs_for_show
|
74
|
+
self.class.attrs_for_show
|
75
|
+
end
|
76
|
+
|
65
77
|
def attrs_for_form
|
66
78
|
self.class.attrs_for_form
|
67
79
|
end
|
68
80
|
|
81
|
+
def attrs_for_export
|
82
|
+
self.class.attrs_for_export
|
83
|
+
end
|
84
|
+
|
69
85
|
module ClassMethods
|
70
86
|
def attrs_for_index(*attrs)
|
71
87
|
@attrs_for_index = attrs if attrs.present?
|
72
88
|
@attrs_for_index || []
|
73
89
|
end
|
74
90
|
|
91
|
+
def attrs_for_show(*attrs)
|
92
|
+
@attrs_for_show = attrs if attrs.present?
|
93
|
+
@attrs_for_show || []
|
94
|
+
end
|
95
|
+
|
75
96
|
def attrs_for_form(*attrs)
|
76
97
|
@attrs_for_form = attrs if attrs.present?
|
77
98
|
@attrs_for_form || []
|
78
99
|
end
|
100
|
+
|
101
|
+
def attrs_for_export(*attrs)
|
102
|
+
@attrs_for_export = attrs if attrs.present?
|
103
|
+
@attrs_for_export || []
|
104
|
+
end
|
79
105
|
end
|
80
106
|
end
|
81
107
|
end
|
@@ -6,9 +6,9 @@ module Godmin
|
|
6
6
|
|
7
7
|
delegate :batch_action_map, to: "self.class"
|
8
8
|
|
9
|
-
def batch_action(action,
|
9
|
+
def batch_action(action, records)
|
10
10
|
if batch_action?(action)
|
11
|
-
send("batch_action_#{action}",
|
11
|
+
send("batch_action_#{action}", records)
|
12
12
|
true
|
13
13
|
else
|
14
14
|
false
|
@@ -9,7 +9,7 @@ module Godmin
|
|
9
9
|
def apply_filters(filter_params, resources)
|
10
10
|
if filter_params.present?
|
11
11
|
filter_params.each do |name, value|
|
12
|
-
if
|
12
|
+
if apply_filter?(name, value)
|
13
13
|
resources = send("filter_#{name}", resources, value)
|
14
14
|
end
|
15
15
|
end
|
@@ -17,6 +17,13 @@ module Godmin
|
|
17
17
|
resources
|
18
18
|
end
|
19
19
|
|
20
|
+
private
|
21
|
+
|
22
|
+
def apply_filter?(name, value)
|
23
|
+
return false if value == [""]
|
24
|
+
filter_map.key?(name.to_sym) && value.present?
|
25
|
+
end
|
26
|
+
|
20
27
|
module ClassMethods
|
21
28
|
def filter_map
|
22
29
|
@filter_map ||= {}
|
data/lib/godmin/version.rb
CHANGED
@@ -4,13 +4,7 @@ module Godmin
|
|
4
4
|
module ResourceService
|
5
5
|
class BatchActionsTest < ActiveSupport::TestCase
|
6
6
|
def setup
|
7
|
-
|
8
|
-
def self.find(ids)
|
9
|
-
ids
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
@article_service = ArticleService.new(resource_class: resource_class)
|
7
|
+
@article_service = ArticleService.new
|
14
8
|
end
|
15
9
|
|
16
10
|
def test_batch_action
|
@@ -18,6 +18,16 @@ module Godmin
|
|
18
18
|
assert_equal [:resources, "Sweden"], @article_service.called_methods[:filters][:country]
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_calls_filter_when_present_multiselect
|
22
|
+
@article_service.apply_filters({ tags: ["Banana"] }, :resources)
|
23
|
+
assert_equal [:resources, ["Banana"]], @article_service.called_methods[:filters][:tags]
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_does_not_call_filter_when_empty_multiselect
|
27
|
+
@article_service.apply_filters({ tags: [""] }, :resources)
|
28
|
+
assert_equal nil, @article_service.called_methods[:filters][:tags]
|
29
|
+
end
|
30
|
+
|
21
31
|
def test_filter_map_with_default_options
|
22
32
|
expected_filter_map = { as: :string, option_text: "to_s", option_value: "id", collection: nil }
|
23
33
|
assert_equal expected_filter_map, @article_service.filter_map[:title]
|
@@ -14,8 +14,16 @@ module Godmin
|
|
14
14
|
assert_equal [:id, :title, :country], @article_service.attrs_for_index
|
15
15
|
end
|
16
16
|
|
17
|
+
def test_attrs_for_show
|
18
|
+
assert_equal [:title, :country], @article_service.attrs_for_show
|
19
|
+
end
|
20
|
+
|
17
21
|
def test_attrs_for_form
|
18
22
|
assert_equal [:id, :title, :country, :body], @article_service.attrs_for_form
|
19
23
|
end
|
24
|
+
|
25
|
+
def test_attrs_for_export
|
26
|
+
assert_equal [:id, :title], @article_service.attrs_for_export
|
27
|
+
end
|
20
28
|
end
|
21
29
|
end
|
data/test/test_helper.rb
CHANGED
@@ -32,22 +32,28 @@ end
|
|
32
32
|
class ArticleService
|
33
33
|
include Godmin::Resources::ResourceService
|
34
34
|
|
35
|
-
|
36
|
-
{ scopes: {}, filters: {}, batch_actions: {} }
|
37
|
-
end
|
35
|
+
attr_accessor :called_methods
|
38
36
|
|
39
37
|
attrs_for_index :id, :title, :country
|
38
|
+
attrs_for_show :title, :country
|
40
39
|
attrs_for_form :id, :title, :country, :body
|
40
|
+
attrs_for_export :id, :title
|
41
41
|
|
42
42
|
scope :unpublished, default: true
|
43
43
|
scope :published
|
44
44
|
|
45
45
|
filter :title
|
46
46
|
filter :country, as: :select, collection: %w(Sweden Canada)
|
47
|
+
filter :tags, as: :multiselect, collection: %w(Apple Banana)
|
47
48
|
|
48
49
|
batch_action :unpublish
|
49
50
|
batch_action :publish, confirm: true, only: :unpublished, except: :published
|
50
51
|
|
52
|
+
def initialize(*)
|
53
|
+
super
|
54
|
+
@called_methods = { scopes: {}, filters: {}, batch_actions: {} }
|
55
|
+
end
|
56
|
+
|
51
57
|
def resources_relation
|
52
58
|
[:foo, :bar, :baz]
|
53
59
|
end
|
@@ -72,6 +78,11 @@ end
|
|
72
78
|
resources
|
73
79
|
end
|
74
80
|
|
81
|
+
def filter_tags(resources, value)
|
82
|
+
called_methods[:filters][:tags] = [resources, value]
|
83
|
+
resources
|
84
|
+
end
|
85
|
+
|
75
86
|
def batch_action_unpublish(resources)
|
76
87
|
called_methods[:batch_actions][:unpublish] = resources
|
77
88
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: godmin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jens Ljungblad
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-05-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bcrypt
|
@@ -74,6 +74,20 @@ dependencies:
|
|
74
74
|
- - "<"
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '4.2'
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: csv_builder
|
79
|
+
requirement: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 2.1.1
|
84
|
+
type: :runtime
|
85
|
+
prerelease: false
|
86
|
+
version_requirements: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 2.1.1
|
77
91
|
- !ruby/object:Gem::Dependency
|
78
92
|
name: momentjs-rails
|
79
93
|
requirement: !ruby/object:Gem::Requirement
|
@@ -214,6 +228,7 @@ files:
|
|
214
228
|
- app/views/godmin/resource/_breadcrumb.html.erb
|
215
229
|
- app/views/godmin/resource/_button_actions.html.erb
|
216
230
|
- app/views/godmin/resource/_errors.html.erb
|
231
|
+
- app/views/godmin/resource/_export_actions.html.erb
|
217
232
|
- app/views/godmin/resource/_filters.html.erb
|
218
233
|
- app/views/godmin/resource/_form.html.erb
|
219
234
|
- app/views/godmin/resource/_pagination.html.erb
|
@@ -221,9 +236,12 @@ files:
|
|
221
236
|
- app/views/godmin/resource/_table.html.erb
|
222
237
|
- app/views/godmin/resource/columns/_actions.html.erb
|
223
238
|
- app/views/godmin/resource/edit.html.erb
|
239
|
+
- app/views/godmin/resource/index.csv.csvbuilder
|
224
240
|
- app/views/godmin/resource/index.html.erb
|
241
|
+
- app/views/godmin/resource/index.json.jbuilder
|
225
242
|
- app/views/godmin/resource/new.html.erb
|
226
243
|
- app/views/godmin/resource/show.html.erb
|
244
|
+
- app/views/godmin/resource/show.json.jbuilder
|
227
245
|
- app/views/godmin/sessions/new.html.erb
|
228
246
|
- app/views/godmin/shared/_navigation.html.erb
|
229
247
|
- app/views/layouts/godmin/_content.html.erb
|