godmin 1.3.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +0 -2
  3. data/.gitignore +1 -0
  4. data/.travis.yml +7 -15
  5. data/Appraisals +4 -4
  6. data/CHANGELOG.md +83 -2
  7. data/Gemfile +1 -2
  8. data/README.md +74 -9
  9. data/Rakefile +2 -10
  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/_table.html.erb +3 -0
  14. data/app/views/godmin/resource/columns/_actions.html.erb +4 -4
  15. data/app/views/godmin/resource/show.html.erb +1 -1
  16. data/config/locales/en.yml +2 -0
  17. data/config/locales/pt-BR.yml +2 -0
  18. data/config/locales/sv.yml +2 -0
  19. data/gemfiles/rails_5.gemfile +3 -4
  20. data/gemfiles/rails_6.gemfile +8 -0
  21. data/godmin.gemspec +18 -16
  22. data/lib/generators/godmin/resource/resource_generator.rb +7 -1
  23. data/lib/generators/godmin/resource/templates/resource_model.rb +4 -0
  24. data/lib/godmin/application_controller.rb +10 -11
  25. data/lib/godmin/authentication.rb +11 -11
  26. data/lib/godmin/authentication/sessions_controller.rb +2 -1
  27. data/lib/godmin/authorization.rb +6 -20
  28. data/lib/godmin/engine_wrapper.rb +10 -1
  29. data/lib/godmin/generators/base.rb +4 -4
  30. data/lib/godmin/generators/named_base.rb +4 -4
  31. data/lib/godmin/helpers/application.rb +3 -3
  32. data/lib/godmin/helpers/batch_actions.rb +1 -1
  33. data/lib/godmin/helpers/forms.rb +5 -1
  34. data/lib/godmin/paginator.rb +12 -4
  35. data/lib/godmin/resolver.rb +23 -5
  36. data/lib/godmin/resources/resource_controller.rb +24 -5
  37. data/lib/godmin/resources/resource_controller/batch_actions.rb +1 -1
  38. data/lib/godmin/resources/resource_service.rb +8 -7
  39. data/lib/godmin/resources/resource_service/associations.rb +23 -0
  40. data/lib/godmin/version.rb +1 -1
  41. data/template.rb +42 -7
  42. data/test/dummy/admin/app/controllers/admin/authorized_articles_controller.rb +15 -0
  43. data/test/dummy/admin/app/models/admin/article.rb +4 -0
  44. data/test/dummy/admin/app/policies/admin/article_policy.rb +7 -0
  45. data/test/dummy/admin/config/routes.rb +1 -0
  46. data/test/dummy/app/assets/config/manifest.js +4 -0
  47. data/test/dummy/app/controllers/another_admin_sessions_controller.rb +8 -0
  48. data/test/dummy/app/controllers/comments_controller.rb +3 -0
  49. data/test/dummy/app/models/another_admin_user.rb +7 -0
  50. data/test/dummy/app/models/article.rb +1 -0
  51. data/test/dummy/app/models/comment.rb +7 -0
  52. data/test/dummy/app/services/article_service.rb +2 -0
  53. data/test/dummy/app/services/comment_service.rb +7 -0
  54. data/test/dummy/bin/rails +1 -1
  55. data/test/dummy/config/application.rb +2 -14
  56. data/test/dummy/config/locales/en.yml +9 -0
  57. data/test/dummy/config/routes.rb +6 -1
  58. data/test/dummy/db/migrate/20150717121532_create_articles.rb +1 -1
  59. data/test/dummy/db/migrate/20150907133753_create_admin_users.rb +1 -1
  60. data/test/dummy/db/migrate/20160713134238_create_comment.rb +9 -0
  61. data/test/dummy/db/migrate/20170207081043_create_another_admin_user.rb +10 -0
  62. data/test/dummy/db/schema.rb +26 -11
  63. data/test/fakes/article.rb +1 -1
  64. data/test/fakes/article_service.rb +3 -7
  65. data/test/generators/resource_generator_test.rb +77 -0
  66. data/test/integration/authentication_test.rb +8 -0
  67. data/test/integration/authorization_test.rb +5 -0
  68. data/test/integration/nested_resources_test.rb +47 -0
  69. data/test/test_helper.rb +1 -4
  70. data/test/{lib/godmin → unit}/engine_wrapper_test.rb +1 -1
  71. data/test/{lib/godmin → unit}/helpers/filters_test.rb +0 -0
  72. data/test/{lib/godmin → unit}/paginator_test.rb +11 -0
  73. data/test/{lib/godmin → unit}/resolver_test.rb +0 -0
  74. data/test/{lib/godmin → unit}/resources/resource_service/batch_actions_test.rb +1 -1
  75. data/test/{lib/godmin → unit}/resources/resource_service/filters_test.rb +1 -1
  76. data/test/{lib/godmin → unit}/resources/resource_service/ordering_test.rb +1 -1
  77. data/test/{lib/godmin → unit}/resources/resource_service/pagination_test.rb +0 -0
  78. data/test/{lib/godmin → unit}/resources/resource_service/scopes_test.rb +0 -0
  79. data/test/{lib/godmin → unit}/resources/resource_service_test.rb +0 -0
  80. metadata +167 -107
  81. data/gemfiles/rails_4.gemfile +0 -9
  82. data/lib/godmin/authorization/policy_finder.rb +0 -31
  83. data/lib/tasks/godmin_tasks.rake +0 -4
  84. 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
@@ -1,3 +1,6 @@
1
+ require "action_view"
2
+ require "action_view/template/resolver"
3
+
1
4
  module Godmin
2
5
  class Resolver < ::ActionView::FileSystemResolver
3
6
  def self.resolvers(controller_path, engine_wrapper)
@@ -13,15 +16,30 @@ module Godmin
13
16
  @engine_wrapper = engine_wrapper
14
17
  end
15
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.
16
36
  def find_templates(name, prefix, *args)
17
37
  templates = []
18
38
 
19
39
  template_paths(prefix).each do |path|
20
- if templates.present?
21
- break
22
- else
23
- templates = super(name, path, *args)
24
- end
40
+ break if templates.present?
41
+
42
+ templates = super(name, path, *args)
25
43
  end
26
44
 
27
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.0"
2
+ VERSION = "2.1.0"
3
3
  end
data/template.rb CHANGED
@@ -1,10 +1,15 @@
1
1
  require "active_support/all"
2
2
 
3
3
  def install_standalone
4
- gem "godmin", "1.2.0"
4
+ set_ruby_version
5
+
6
+ gem "godmin", "1.5.0"
5
7
 
6
8
  after_bundle do
7
- generate_model
9
+ create_database
10
+
11
+ generate_models
12
+
8
13
  generate("godmin:install")
9
14
  generate("godmin:resource", "article")
10
15
  generate("godmin:resource", "author")
@@ -16,12 +21,15 @@ def install_standalone
16
21
  modify_author_service
17
22
  modify_article_controller
18
23
  modify_article_service
24
+ modify_readme
19
25
 
20
26
  migrate_and_seed
21
27
  end
22
28
  end
23
29
 
24
30
  def install_engine
31
+ set_ruby_version
32
+
25
33
  run_ruby_script("bin/rails plugin new admin --mountable")
26
34
 
27
35
  gsub_file "admin/admin.gemspec", "TODO: ", ""
@@ -29,14 +37,17 @@ def install_engine
29
37
 
30
38
  inject_into_file "admin/admin.gemspec", before: /^end/ do
31
39
  <<-END.strip_heredoc.indent(2)
32
- s.add_dependency "godmin", "~> 1.0.0"
40
+ s.add_dependency "godmin", "~> 1.5.0"
33
41
  END
34
42
  end
35
43
 
36
44
  gem "admin", path: "admin"
37
45
 
38
46
  after_bundle do
39
- generate_model
47
+ create_database
48
+
49
+ generate_models
50
+
40
51
  run_ruby_script("admin/bin/rails g godmin:install")
41
52
  run_ruby_script("admin/bin/rails g godmin:resource article")
42
53
  run_ruby_script("admin/bin/rails g godmin:resource author")
@@ -54,12 +65,24 @@ def install_engine
54
65
  modify_author_service("admin")
55
66
  modify_article_controller("admin")
56
67
  modify_article_service("admin")
68
+ modify_readme
57
69
 
58
70
  migrate_and_seed
59
71
  end
60
72
  end
61
73
 
62
- def generate_model
74
+ def set_ruby_version
75
+ prepend_to_file "Gemfile" do
76
+ "ruby '2.3.5'\n"
77
+ end
78
+ end
79
+
80
+ def create_database
81
+ rake("db:drop")
82
+ rake("db:create")
83
+ end
84
+
85
+ def generate_models
63
86
  generate(:model, "author name:string")
64
87
  generate(:model, "article title:string body:text author:references published:boolean published_at:datetime")
65
88
 
@@ -106,6 +129,7 @@ def modify_rakefile
106
129
  desc "Reseed the database"
107
130
  task reseed: :environment do
108
131
  Rake::Task["sandbox:reset"].invoke
132
+ Rake::Task["db:environment:set"].invoke
109
133
  Rake::Task["db:schema:load"].invoke
110
134
  Rake::Task["db:seed"].invoke
111
135
  end
@@ -285,9 +309,20 @@ def modify_author_service(namespace = nil)
285
309
  END
286
310
  end
287
311
  end
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
+
288
325
  def migrate_and_seed
289
- rake("db:drop")
290
- rake("db:create")
291
326
  rake("db:migrate")
292
327
  rake("db:seed")
293
328
  end