godmin 0.11.0 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +42 -2
  4. data/app/assets/javascripts/godmin/navigation.js +1 -1
  5. data/app/assets/javascripts/godmin/select-boxes.js +6 -1
  6. data/app/assets/stylesheets/godmin/index.css.scss +6 -0
  7. data/app/views/godmin/resource/_actions.html.erb +1 -0
  8. data/app/views/godmin/resource/_breadcrumb.html.erb +44 -17
  9. data/app/views/godmin/resource/_export_actions.html.erb +15 -0
  10. data/app/views/godmin/resource/columns/_actions.html.erb +4 -3
  11. data/app/views/godmin/resource/edit.html.erb +1 -1
  12. data/app/views/godmin/resource/index.csv.csvbuilder +5 -0
  13. data/app/views/godmin/resource/index.html.erb +1 -1
  14. data/app/views/godmin/resource/index.json.jbuilder +3 -0
  15. data/app/views/godmin/resource/new.html.erb +1 -1
  16. data/app/views/godmin/resource/show.html.erb +10 -1
  17. data/app/views/godmin/resource/show.json.jbuilder +1 -0
  18. data/config/locales/en.yml +5 -1
  19. data/config/locales/sv.yml +5 -1
  20. data/godmin.gemspec +1 -0
  21. data/lib/generators/godmin/resource/templates/resource_service.rb +1 -0
  22. data/lib/godmin.rb +1 -1
  23. data/lib/godmin/authorization.rb +3 -3
  24. data/lib/godmin/helpers/filters.rb +7 -1
  25. data/lib/godmin/resources/resource_controller.rb +13 -4
  26. data/lib/godmin/resources/resource_service.rb +32 -6
  27. data/lib/godmin/resources/resource_service/batch_actions.rb +2 -2
  28. data/lib/godmin/resources/resource_service/filters.rb +8 -1
  29. data/lib/godmin/version.rb +1 -1
  30. data/test/lib/godmin/resources/resource_service/batch_actions_test.rb +1 -7
  31. data/test/lib/godmin/resources/resource_service/filters_test.rb +10 -0
  32. data/test/lib/godmin/resources/resource_service_test.rb +8 -0
  33. data/test/test_helper.rb +14 -3
  34. metadata +20 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f825ae621a3f84cb0d609b8c701f17f6e7febe80
4
- data.tar.gz: 37128e9e80e832c80f1fff70a840495ed703d3bb
3
+ metadata.gz: 70806f3cd970ce6827a4bceb51eace7bd9b0c4a9
4
+ data.tar.gz: 47d369f0024eeb1a2d12d2d3785a8aa9ce351802
5
5
  SHA512:
6
- metadata.gz: dba1ad1a2b6512520a88ae0731e73b8d0c482d101cc54bd982a76bda45248aecd7492cc9ceb626cc2f9a77c1efa34878f354b94ea881ec4ce3b81b20551ac79d
7
- data.tar.gz: b61ac263261cd384466f9ae7f6e31de566655b21de48ba6d25f3c5c1d02c2f87bf4d5726fc3195fc2a75ba990796b165d3fcae1a87f774f3df902e648249c068
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
- redirect_to articles_path(scope: :published)
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>&hellip;</div>';
21
+ }
22
+ }
18
23
  };
19
24
 
20
25
  $el.selectize($.extend(defaults, options));
@@ -24,6 +24,12 @@ body {
24
24
  margin-top: 20px;
25
25
  }
26
26
 
27
+ #breadcrumb {
28
+ .dropdown:before {
29
+ content: " ";
30
+ }
31
+ }
32
+
27
33
  #scopes {
28
34
  margin-bottom: 20px;
29
35
  }
@@ -4,5 +4,6 @@
4
4
  </div>
5
5
  <div class="pull-right">
6
6
  <%= render partial: "button_actions" %>
7
+ <%= render partial: "export_actions" %>
7
8
  </div>
8
9
  </div>
@@ -1,18 +1,45 @@
1
- <ol class="breadcrumb">
2
- <% if index %>
3
- <li class="active">
4
- <%= @resource_class.model_name.human(count: 2) %>
5
- </li>
6
- <% else %>
7
- <li>
8
- <%= link_to @resource_class.model_name.human(count: 2), @resource_class %>
9
- </li>
10
- <li class="active">
11
- <% if @resource.new_record? %>
12
- <%= t("helpers.submit.create", model: @resource_class.model_name.human) %>
13
- <% else %>
14
- <%= @resource.to_s %>
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
- </li>
17
- <% end %>
18
- </ol>
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("column_actions.show"), resource, class: "btn btn-default" %>
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("column_actions.edit"), [:edit, resource], class: "btn btn-default" %>
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("column_actions.destroy"), resource, method: :delete, data: { confirm: translate_scoped("column_actions.confirm_message") }, class: "btn btn-danger" %>
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,4 +1,4 @@
1
- <%= render partial: "breadcrumb", locals: { index: false } %>
1
+ <%= render partial: "breadcrumb" %>
2
2
 
3
3
  <%= render partial: "errors", locals: { errors: @resource.errors } %>
4
4
 
@@ -0,0 +1,5 @@
1
+ csv << @resource_service.attrs_for_export
2
+
3
+ @resources.limit(nil).offset(nil).each do |resource|
4
+ csv << @resource_service.attrs_for_export.map { |attr| resource.send(attr) }
5
+ end
@@ -1,4 +1,4 @@
1
- <%= render partial: "breadcrumb", locals: { index: true } %>
1
+ <%= render partial: "breadcrumb" %>
2
2
  <%= render partial: "scopes" %>
3
3
  <%= render partial: "filters" %>
4
4
 
@@ -0,0 +1,3 @@
1
+ json.array! @resources.limit(nil).offset(nil) do |resource|
2
+ json.extract! resource, *@resource_service.attrs_for_export
3
+ end
@@ -1,4 +1,4 @@
1
- <%= render partial: "breadcrumb", locals: { index: false } %>
1
+ <%= render partial: "breadcrumb" %>
2
2
 
3
3
  <%= render partial: "errors", locals: { errors: @resource.errors } %>
4
4
 
@@ -1 +1,10 @@
1
- The fate of this page has yet to be determined...
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
@@ -14,11 +14,14 @@ en:
14
14
  buttons:
15
15
  apply: Filter
16
16
  clear: Clear filter
17
- column_actions:
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"
@@ -14,11 +14,14 @@ sv:
14
14
  buttons:
15
15
  apply: Filtrera
16
16
  clear: Rensa filter
17
- column_actions:
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
@@ -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
- raise NotAuthorizedError
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, { include_blank: true, wrapper_class: "filter" }, {
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 { render json: @resources.to_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 { render json: @resource.to_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.destroy
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], item_ids)
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] || self.class.name.demodulize.chomp("Service").constantize
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(params[:page],
35
- apply_order(params[:order],
36
- apply_filters(params[:filter],
37
- apply_scope(params[:scope],
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, item_ids)
9
+ def batch_action(action, records)
10
10
  if batch_action?(action)
11
- send("batch_action_#{action}", resource_class.find(item_ids))
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 filter_map.key?(name.to_sym) && value.present?
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 ||= {}
@@ -1,3 +1,3 @@
1
1
  module Godmin
2
- VERSION = "0.11.0"
2
+ VERSION = "0.11.1"
3
3
  end
@@ -4,13 +4,7 @@ module Godmin
4
4
  module ResourceService
5
5
  class BatchActionsTest < ActiveSupport::TestCase
6
6
  def setup
7
- resource_class = Class.new do
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
- mattr_accessor :called_methods do
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.0
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-04-13 00:00:00.000000000 Z
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