You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A hook to invoke the custom generator with scaffolding or with controller's generators
# lib/generators/rails/policy/hooks.rbrequire'rails/generators'require'rails/generators/rails/scaffold/scaffold_generator'require'rails/generators/rails/controller/controller_generator'Rails::Generators::ScaffoldGenerator.hook_for:policy,default: true,type: :boolean# invoke with scaffolding generatorsRails::Generators::ControllerGenerator.hook_for:policy,default: true,type: :boolean# invoke with the controllers' generator.
@annikoff Thanks for actually pointing toward the solution.
I forgot I made it work with some tweaks and the changed code is working with ruby 3.0.0 and rails 6
config/initializers/pundit_policy_generator.rb
# frozen_string_literal: truerequire'rails/generators'# NOTE: This is the only approach that works without skipping any existing# generators.# Other approaches tried:# - Added hook in an initializer by opening class# - Missing `jbuilder`# - Added whole files at the same generator locations# - Missing `controller_test` and `system test`# - The existing approach https://gist.github.com/annikoff/331f785aa7a207a7945b1eca6eff526b# - Missing modelmoduleRailsmoduleGeneratorsclassScaffoldControllerGenerator < NamedBase# invoke with scaffolding controllers' generatorshook_for:policy,in: :pundit,default: true,type: :booleanendclassControllerGenerator < NamedBase# invoke with the controllers' generator.hook_for:policy,in: :pundit,default: true,type: :booleanendendend
# frozen_string_literal: true# NOTE: Please do not remove this.## This is required in order to invoke custom generators with the following# command:# rails g controller [controller name]## We have already tried different approaches mentioned in:# config/initializers/pundit_policy_generator.rb#moduleRailsmoduleGeneratorsclassControllerGenerator < NamedBase# :nodoc:endendend
# frozen_string_literal: true# NOTE: Please do not remove this.## This is required in order to invoke custom generators with the following# command:# rails g scaffold [resource name]## We have already tried different approaches mentioned in:# config/initializers/pundit_policy_generator.rb#moduleRailsmoduleGeneratorsclassScaffoldControllerGenerator < NamedBase# :nodoc:endendend
Your solution only half worked for me. While it did not skip any scaffolding and did scaffold policies, it stopped picking my custom scaffold templates in lib/templates/rails/scaffold_controller/controller.rb.tt
I've come to a perfect solution heavily inspired by
I only need 1 initializer to get everything working:
# Inspired by:
# - https://gist.github.com/annikoff/331f785aa7a207a7945b1eca6eff526b
# - https://github.com/drapergem/draper/blob/master/lib/generators/controller_override.rb
# - https://github.com/drapergem/draper/blob/master/lib/draper/railtie.rb
require "rails/railtie"
require "rails/generators"
require "generators/pundit/policy/policy_generator"
module CustomPunditGenerator
module ControllerGenerator
extend ActiveSupport::Concern
included do
hook_for :policy, in: :pundit, default: true, type: :boolean do |generator|
invoke generator, [name.singularize]
end
end
end
module ScaffoldControllerGenerator
extend ActiveSupport::Concern
included do
hook_for :policy, in: :pundit, default: true, type: :boolean
end
end
module PolicyGenerator
extend ActiveSupport::Concern
included do
source_root File.expand_path("templates", __dir__)
def create_policy
template(
Rails.root.join("lib/templates/pundit/scaffold/policy.rb.tt"),
File.join("app/policies", class_path, "#{file_name}_policy.rb")
)
end
end
end
end
module ActiveModel
class Railtie < Rails::Railtie
generators do |app|
Rails::Generators.configure! app.config.generators
Rails::Generators::ControllerGenerator.include CustomPunditGenerator::ControllerGenerator
Rails::Generators::ScaffoldControllerGenerator.include CustomPunditGenerator::ScaffoldControllerGenerator
Pundit::Generators::PolicyGenerator.include CustomPunditGenerator::PolicyGenerator
end
end
end
Edit: Specs for policies are no longer generated. It seems as soon as we do
require "rails/railtie"
require "rails/generators"
module CustomPolicyGenerator
module ControllerGenerator
extend ActiveSupport::Concern
included do
hook_for :custom_policy, in: nil, default: true, type: :boolean do |generator|
invoke generator, [name.singularize]
end
end
end
module ScaffoldControllerGenerator
extend ActiveSupport::Concern
included do
hook_for :custom_policy, in: nil, default: true, type: :boolean
end
end
end
module ActiveModel
class Railtie < Rails::Railtie
generators do |app|
Rails::Generators.configure! app.config.generators
Rails::Generators::ControllerGenerator.include CustomPolicyGenerator::ControllerGenerator
Rails::Generators::ScaffoldControllerGenerator.include CustomPolicyGenerator::ScaffoldControllerGenerator
end
end
end
Rails.application.config.generators do |g|
g.policy false
g.custom_policy true
end
module Rails
class CustomPolicyGenerator < Rails::Generators::NamedBase
# source_root File.expand_path("templates", __dir__)
def create_policy
template "policy.rb", File.join("app/policies", class_path, "#{file_name}_policy.rb")
end
hook_for :test_framework
end
end
module Rspec
class CustomPolicyGenerator < Rails::Generators::NamedBase
# source_root File.expand_path("templates", __dir__)
def create_policy_spec
template "policy_spec.rb", File.join("spec/policies", class_path, "#{file_name}_policy_spec.rb")
end
end
end
Placed template files in
lib/templates/rails/custom_policy/policy.rb.tt
lib/templates/rspec/custom_policy/policy_spec.rb.tt
module ActiveModel
class Railtie < Rails::Railtie
generators do |app|
Rails::Generators.configure! app.config.generators
Rails::Generators::ControllerGenerator.include CustomPolicyGenerator::ControllerGenerator
Rails::Generators::ScaffoldControllerGenerator.include CustomPolicyGenerator::ScaffoldControllerGenerator
end
end
end
is the best way but outside of that, Rails::Generators::ScaffoldControllerGenerator is not defined and I am forced to use a require. If I use the requires:
Thanks yall. I wrote a blogpost to cover what ended up working for me. I did end up needing the requires, but I wasn't using custom templates so not sure if it breaks that like you mentioned.
@annikoff
There's an issue with this approach. I am currently using this to generate policy files.
This for some reason is not creating model. It is skipping the model generator.
Did you face the same issue and did you add any workaround for the same?