godmin 1.3.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +0 -2
  3. data/.gitignore +1 -0
  4. data/.travis.yml +9 -10
  5. data/Appraisals +4 -4
  6. data/CHANGELOG.md +84 -2
  7. data/Gemfile +1 -2
  8. data/README.md +119 -10
  9. data/Rakefile +2 -2
  10. data/app/views/godmin/resource/_breadcrumb.html.erb +12 -24
  11. data/app/views/godmin/resource/_breadcrumb_actions.html.erb +41 -0
  12. data/app/views/godmin/resource/_button_actions.html.erb +1 -1
  13. data/app/views/godmin/resource/_pagination.html.erb +4 -4
  14. data/app/views/godmin/resource/_table.html.erb +3 -0
  15. data/app/views/godmin/resource/columns/_actions.html.erb +4 -4
  16. data/app/views/godmin/resource/show.html.erb +1 -1
  17. data/config/locales/en.yml +2 -0
  18. data/config/locales/pt-BR.yml +2 -0
  19. data/config/locales/sv.yml +2 -0
  20. data/gemfiles/rails_5.gemfile +3 -4
  21. data/gemfiles/rails_6.gemfile +8 -0
  22. data/godmin.gemspec +18 -16
  23. data/lib/generators/godmin/resource/resource_generator.rb +7 -1
  24. data/lib/generators/godmin/resource/templates/resource_model.rb +4 -0
  25. data/lib/godmin/application_controller.rb +10 -11
  26. data/lib/godmin/authentication.rb +11 -11
  27. data/lib/godmin/authentication/sessions_controller.rb +2 -1
  28. data/lib/godmin/authorization.rb +34 -14
  29. data/lib/godmin/engine_wrapper.rb +10 -1
  30. data/lib/godmin/generators/base.rb +4 -4
  31. data/lib/godmin/generators/named_base.rb +4 -4
  32. data/lib/godmin/helpers/application.rb +3 -3
  33. data/lib/godmin/helpers/batch_actions.rb +1 -1
  34. data/lib/godmin/helpers/forms.rb +5 -1
  35. data/lib/godmin/paginator.rb +12 -4
  36. data/lib/godmin/resolver.rb +20 -5
  37. data/lib/godmin/resources/resource_controller.rb +24 -5
  38. data/lib/godmin/resources/resource_controller/batch_actions.rb +1 -1
  39. data/lib/godmin/resources/resource_service.rb +8 -7
  40. data/lib/godmin/resources/resource_service/associations.rb +23 -0
  41. data/lib/godmin/version.rb +1 -1
  42. data/template.rb +17 -3
  43. data/test/dummy/admin/app/controllers/admin/authorized_articles_controller.rb +29 -0
  44. data/test/dummy/admin/app/models/admin/article.rb +4 -0
  45. data/test/dummy/admin/app/models/admin/magazine.rb +4 -0
  46. data/test/dummy/admin/app/policies/admin/article_policy.rb +11 -0
  47. data/test/dummy/admin/app/policies/admin/magazine_policy.rb +4 -0
  48. data/test/dummy/admin/app/views/admin/shared/_navigation.html.erb +5 -0
  49. data/test/dummy/admin/config/routes.rb +1 -0
  50. data/test/dummy/app/assets/config/manifest.js +4 -0
  51. data/test/dummy/app/controllers/another_admin_sessions_controller.rb +8 -0
  52. data/test/dummy/app/controllers/comments_controller.rb +3 -0
  53. data/test/dummy/app/models/another_admin_user.rb +7 -0
  54. data/test/dummy/app/models/article.rb +1 -0
  55. data/test/dummy/app/models/comment.rb +7 -0
  56. data/test/dummy/app/models/magazine.rb +2 -0
  57. data/test/dummy/app/services/article_service.rb +2 -0
  58. data/test/dummy/app/services/comment_service.rb +7 -0
  59. data/test/dummy/bin/rails +1 -1
  60. data/test/dummy/config/application.rb +2 -14
  61. data/test/dummy/config/locales/en.yml +9 -0
  62. data/test/dummy/config/routes.rb +6 -1
  63. data/test/dummy/db/migrate/20150717121532_create_articles.rb +1 -1
  64. data/test/dummy/db/migrate/20150907133753_create_admin_users.rb +1 -1
  65. data/test/dummy/db/migrate/20160713134238_create_comment.rb +9 -0
  66. data/test/dummy/db/migrate/20170207081043_create_another_admin_user.rb +10 -0
  67. data/test/dummy/db/migrate/20210519215502_create_magazines.rb +9 -0
  68. data/test/dummy/db/schema.rb +38 -16
  69. data/test/fakes/article.rb +1 -1
  70. data/test/fakes/article_service.rb +3 -7
  71. data/test/generators/resource_generator_test.rb +78 -0
  72. data/test/integration/authentication_test.rb +8 -0
  73. data/test/integration/authorization_test.rb +13 -0
  74. data/test/integration/nested_resources_test.rb +47 -0
  75. data/test/test_helper.rb +1 -4
  76. data/test/{lib/godmin → unit}/engine_wrapper_test.rb +1 -1
  77. data/test/{lib/godmin → unit}/helpers/filters_test.rb +0 -0
  78. data/test/{lib/godmin → unit}/paginator_test.rb +11 -0
  79. data/test/{lib/godmin → unit}/resolver_test.rb +0 -0
  80. data/test/{lib/godmin → unit}/resources/resource_service/batch_actions_test.rb +1 -1
  81. data/test/{lib/godmin → unit}/resources/resource_service/filters_test.rb +1 -1
  82. data/test/{lib/godmin → unit}/resources/resource_service/ordering_test.rb +1 -1
  83. data/test/{lib/godmin → unit}/resources/resource_service/pagination_test.rb +0 -0
  84. data/test/{lib/godmin → unit}/resources/resource_service/scopes_test.rb +0 -0
  85. data/test/{lib/godmin → unit}/resources/resource_service_test.rb +0 -0
  86. metadata +175 -108
  87. data/gemfiles/rails_4.gemfile +0 -9
  88. data/lib/godmin/authorization/policy_finder.rb +0 -31
  89. data/lib/tasks/godmin_tasks.rake +0 -4
  90. data/test/lib/godmin/policy_finder_test.rb +0 -55
@@ -40,8 +40,17 @@ module Godmin
40
40
  end
41
41
  end
42
42
 
43
+ # Some gymnastics because the `parents` function is slated for deprecation
44
+ # and being replaced by `module_parents` and we don't want to clutter our
45
+ # log with a million warnings
46
+ def parents_of(controller)
47
+ return controller.module_parents if controller.respond_to?(:module_parents)
48
+
49
+ controller.parents
50
+ end
51
+
43
52
  def find_engine_module(controller)
44
- controller.parents.find do |parent|
53
+ parents_of(controller).find do |parent|
45
54
  parent.respond_to?(:use_relative_model_naming?) && parent.use_relative_model_naming?
46
55
  end
47
56
  end
@@ -4,7 +4,7 @@ module Godmin
4
4
  module Generators
5
5
  class Base < Rails::Generators::Base
6
6
  def self.source_paths
7
- %w(authentication install policy resource).map do |path|
7
+ %w[authentication install policy resource].map do |path|
8
8
  File.expand_path("../../../generators/godmin/#{path}/templates", __FILE__)
9
9
  end
10
10
  end
@@ -12,15 +12,15 @@ module Godmin
12
12
  private
13
13
 
14
14
  def namespace
15
- @namespace ||= Rails::Generators.namespace
15
+ @_namespace ||= Rails::Generators.namespace
16
16
  end
17
17
 
18
18
  def namespaced?
19
- @namespaced ||= namespace.present?
19
+ @_namespaced ||= namespace.present?
20
20
  end
21
21
 
22
22
  def namespaced_path
23
- @namespaced_path ||= begin
23
+ @_namespaced_path ||= begin
24
24
  if namespaced?
25
25
  namespace.name.split("::").map(&:underscore)
26
26
  else
@@ -8,7 +8,7 @@ module Godmin
8
8
  private
9
9
 
10
10
  def full_class_name
11
- if namespace
11
+ if namespaced?
12
12
  "#{namespace}::#{class_name}"
13
13
  else
14
14
  class_name
@@ -16,15 +16,15 @@ module Godmin
16
16
  end
17
17
 
18
18
  def class_name
19
- @class_name ||= name.classify
19
+ @_class_name ||= name.classify
20
20
  end
21
21
 
22
22
  def class_path
23
- @class_path ||= namespaced_path + name.classify.deconstantize.split("::").map(&:underscore)
23
+ @_class_path ||= namespaced_path + name.classify.deconstantize.split("::").map(&:underscore)
24
24
  end
25
25
 
26
26
  def file_name
27
- @file_name ||= class_name.demodulize.underscore
27
+ @_file_name ||= class_name.demodulize.underscore
28
28
  end
29
29
  end
30
30
  end
@@ -4,17 +4,17 @@ module Godmin
4
4
  # Renders the provided partial with locals if it exists, otherwise
5
5
  # yields the given block. The lookup context call is cached for
6
6
  # each partial.
7
- def partial_override(partial, locals = {})
7
+ def partial_override(partial, locals = {}, &block)
8
8
  @_partial_override ||= {}
9
9
 
10
- if @_partial_override[partial].nil?
10
+ unless @_partial_override.key?(partial)
11
11
  @_partial_override[partial] = lookup_context.exists?(partial, nil, true)
12
12
  end
13
13
 
14
14
  if @_partial_override[partial]
15
15
  render partial: partial, locals: locals
16
16
  else
17
- yield
17
+ capture(&block)
18
18
  end
19
19
  end
20
20
 
@@ -6,7 +6,7 @@ module Godmin
6
6
 
7
7
  link_to(
8
8
  translate_scoped("batch_actions.labels.#{name}", default: name.to_s.titleize),
9
- @resource_class,
9
+ [*@resource_parents, @resource_class],
10
10
  method: :patch,
11
11
  class: "btn btn-default hidden",
12
12
  data: {
@@ -2,7 +2,11 @@ module Godmin
2
2
  module Helpers
3
3
  module Forms
4
4
  def form_for(record, options = {}, &block)
5
- super(record, { builder: FormBuilders::FormBuilder, inline_errors: false }.merge(options), &block)
5
+ super(record, {
6
+ url: [*@resource_parents, record],
7
+ builder: FormBuilders::FormBuilder,
8
+ inline_errors: false
9
+ }.merge(options), &block)
6
10
  end
7
11
  end
8
12
  end
@@ -1,12 +1,12 @@
1
1
  module Godmin
2
2
  class Paginator
3
- WINDOW_SIZE = 7.freeze
3
+ WINDOW_SIZE = 7
4
4
 
5
5
  attr_reader :per_page, :current_page
6
6
 
7
7
  def initialize(resources, per_page: 25, current_page: nil)
8
- @resources = resources
9
- @per_page = per_page
8
+ @resources = resources
9
+ @per_page = per_page
10
10
  @current_page = current_page ? current_page.to_i : 1
11
11
  end
12
12
 
@@ -35,7 +35,15 @@ module Godmin
35
35
  end
36
36
 
37
37
  def total_resources
38
- @total_resources ||= @resources.count
38
+ @total_resources ||= begin
39
+ count = @resources.count
40
+
41
+ if count.respond_to?(:count)
42
+ count.count
43
+ else
44
+ count
45
+ end
46
+ end
39
47
  end
40
48
 
41
49
  private
@@ -16,15 +16,30 @@ module Godmin
16
16
  @engine_wrapper = engine_wrapper
17
17
  end
18
18
 
19
+ # This function is for Rails 6 and up since the `find_templates` function
20
+ # is deprecated. It does the same thing, just a little differently. It's
21
+ # not being run by versions previous to Rails 6.
22
+ def _find_all(name, prefix, partial, details, key, locals)
23
+ templates = []
24
+
25
+ template_paths(prefix).each do |p|
26
+ break if templates.present?
27
+
28
+ path = Path.build(name, "#{@path}/#{p}", partial)
29
+ templates = query(path, details, details[:formats], locals, cache: !!key)
30
+ end
31
+
32
+ templates
33
+ end
34
+
35
+ # This is how we find templates in Rails 5 and below.
19
36
  def find_templates(name, prefix, *args)
20
37
  templates = []
21
38
 
22
39
  template_paths(prefix).each do |path|
23
- if templates.present?
24
- break
25
- else
26
- templates = super(name, path, *args)
27
- end
40
+ break if templates.present?
41
+
42
+ templates = super(name, path, *args)
28
43
  end
29
44
 
30
45
  templates
@@ -17,6 +17,7 @@ module Godmin
17
17
 
18
18
  before_action :set_resource_service
19
19
  before_action :set_resource_class
20
+ before_action :set_resource_parents
20
21
  before_action :set_resources, only: :index
21
22
  before_action :set_resource, only: [:show, :new, :edit, :create, :update, :destroy]
22
23
  end
@@ -83,6 +84,10 @@ module Godmin
83
84
  @resource_class = resource_class
84
85
  end
85
86
 
87
+ def set_resource_parents
88
+ @resource_parents = resource_parents
89
+ end
90
+
86
91
  def set_resources
87
92
  @resources = resources
88
93
  authorize(@resources) if authorization_enabled?
@@ -98,17 +103,31 @@ module Godmin
98
103
  end
99
104
 
100
105
  def resource_service
106
+ resource_service = resource_service_class.new
107
+
101
108
  if authentication_enabled?
102
- resource_service_class.new(admin_user: admin_user)
103
- else
104
- resource_service_class.new
109
+ resource_service.options[:admin_user] = admin_user
110
+ end
111
+
112
+ if resource_parents.present?
113
+ resource_service.options[:resource_parent] = resource_parents.last
105
114
  end
115
+
116
+ resource_service
106
117
  end
107
118
 
108
119
  def resource_class
109
120
  @resource_service.resource_class
110
121
  end
111
122
 
123
+ def resource_parents
124
+ params.to_unsafe_h.each_with_object([]) do |(name, value), parents|
125
+ if name =~ /(.+)_id$/
126
+ parents << $1.classify.constantize.find(value)
127
+ end
128
+ end
129
+ end
130
+
112
131
  def resources
113
132
  @resource_service.resources(params)
114
133
  end
@@ -151,11 +170,11 @@ module Godmin
151
170
  end
152
171
 
153
172
  def redirect_after_save
154
- @resource
173
+ [*@resource_parents, @resource]
155
174
  end
156
175
 
157
176
  def redirect_after_destroy
158
- resource_class.model_name.route_key.to_sym
177
+ [*@resource_parents, resource_class.model_name.route_key.to_sym]
159
178
  end
160
179
 
161
180
  def redirect_flash_message
@@ -33,7 +33,7 @@ module Godmin
33
33
  end
34
34
  end
35
35
 
36
- redirect_back
36
+ redirect_back(fallback_location: root_path)
37
37
  end
38
38
 
39
39
  def batch_action_ids
@@ -1,3 +1,4 @@
1
+ require "godmin/resources/resource_service/associations"
1
2
  require "godmin/resources/resource_service/batch_actions"
2
3
  require "godmin/resources/resource_service/filters"
3
4
  require "godmin/resources/resource_service/ordering"
@@ -9,6 +10,7 @@ module Godmin
9
10
  module ResourceService
10
11
  extend ActiveSupport::Concern
11
12
 
13
+ include Associations
12
14
  include BatchActions
13
15
  include Filters
14
16
  include Ordering
@@ -21,17 +23,16 @@ module Godmin
21
23
  @options = options
22
24
  end
23
25
 
24
- # TODO: should this raise its own error?
25
26
  def 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
+ self.class.name.chomp("Service").constantize
31
28
  end
32
29
 
33
30
  def resources_relation
34
- resource_class.all
31
+ if options[:resource_parent].present?
32
+ resource_class.where(options[:resource_parent].class.name.underscore => options[:resource_parent])
33
+ else
34
+ resource_class.all
35
+ end
35
36
  end
36
37
 
37
38
  def resources(params)
@@ -0,0 +1,23 @@
1
+ module Godmin
2
+ module Resources
3
+ module ResourceService
4
+ module Associations
5
+ extend ActiveSupport::Concern
6
+
7
+ delegate :has_many_map, to: "self.class"
8
+
9
+ module ClassMethods
10
+ def has_many_map
11
+ @has_many_map ||= {}
12
+ end
13
+
14
+ def has_many(attr, options = {})
15
+ has_many_map[attr] = {
16
+ class_name: attr.to_s.singularize.classify
17
+ }.merge(options)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Godmin
2
- VERSION = "1.3.1"
2
+ VERSION = "2.2.0"
3
3
  end
data/template.rb CHANGED
@@ -3,7 +3,7 @@ require "active_support/all"
3
3
  def install_standalone
4
4
  set_ruby_version
5
5
 
6
- gem "godmin", "1.3.0"
6
+ gem "godmin", "1.5.0"
7
7
 
8
8
  after_bundle do
9
9
  create_database
@@ -21,6 +21,7 @@ def install_standalone
21
21
  modify_author_service
22
22
  modify_article_controller
23
23
  modify_article_service
24
+ modify_readme
24
25
 
25
26
  migrate_and_seed
26
27
  end
@@ -36,7 +37,7 @@ def install_engine
36
37
 
37
38
  inject_into_file "admin/admin.gemspec", before: /^end/ do
38
39
  <<-END.strip_heredoc.indent(2)
39
- s.add_dependency "godmin", "~> 1.3.0"
40
+ s.add_dependency "godmin", "~> 1.5.0"
40
41
  END
41
42
  end
42
43
 
@@ -64,6 +65,7 @@ def install_engine
64
65
  modify_author_service("admin")
65
66
  modify_article_controller("admin")
66
67
  modify_article_service("admin")
68
+ modify_readme
67
69
 
68
70
  migrate_and_seed
69
71
  end
@@ -71,7 +73,7 @@ end
71
73
 
72
74
  def set_ruby_version
73
75
  prepend_to_file "Gemfile" do
74
- "ruby '2.2.2'\n"
76
+ "ruby '2.3.5'\n"
75
77
  end
76
78
  end
77
79
 
@@ -308,6 +310,18 @@ def modify_author_service(namespace = nil)
308
310
  end
309
311
  end
310
312
 
313
+ def modify_readme
314
+ readme_file = "README.md"
315
+ run "rm #{readme_file}"
316
+ readme_text = <<~README
317
+ # README
318
+
319
+ This is the source code for a demo application of the [Godmin](https://github.com/varvet/godmin) admin framework for Rails.
320
+ It is generated by running `rake sandbox:deploy` inside the Godmin repo.
321
+ README
322
+ File.open(readme_file, 'w') { |file| file.write(readme_text) }
323
+ end
324
+
311
325
  def migrate_and_seed
312
326
  rake("db:migrate")
313
327
  rake("db:seed")
@@ -0,0 +1,29 @@
1
+ require_dependency "admin/articles_controller"
2
+
3
+ module Admin
4
+ class AuthorizedArticlesController < ArticlesController
5
+ include Godmin::Authorization
6
+
7
+ def admin_user
8
+ "admin"
9
+ end
10
+
11
+ def new
12
+ # The following calls to #policy are to check that the Authorization
13
+ # module can handle various different scenarios:
14
+ policy(Magazine).index?
15
+ policy(::Magazine).index?
16
+ policy(Magazine.new).index?
17
+ policy(Magazine.all).index?
18
+ policy(Admin::Magazine).index?
19
+ policy(Admin::Magazine.new).index?
20
+ policy(Admin::Magazine.where(name: "name")).index?
21
+
22
+ super
23
+ end
24
+
25
+ def resource_service_class
26
+ Admin::ArticleService
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,4 @@
1
+ module Admin
2
+ class Article < ::Article
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Admin
2
+ class Magazine < ::Magazine
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ module Admin
2
+ class ArticlePolicy < Godmin::Authorization::Policy
3
+ def index?
4
+ false
5
+ end
6
+
7
+ def new?
8
+ true
9
+ end
10
+ end
11
+ end