Add scaffold generators
This PR introduces a Pundit generator for Rails scaffolds and adds authorize and policy_scope Pundit's methods to scaffolded controllers. It modifies the scaffold generator to include a hook for Pundit policies and overrides scaffold controller templates through a Railtie to add Pundit's methods.
Example scaffold command:
# rails g scaffold Post
invoke active_record
create db/migrate/20240225223237_create_posts.rb
create app/models/post.rb
invoke rspec
create spec/models/post_spec.rb
invoke resource_route
route resources :posts
invoke scaffold_controller
create app/controllers/posts_controller.rb
invoke erb
create app/views/posts
create app/views/posts/index.html.erb
create app/views/posts/edit.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/_form.html.erb
create app/views/posts/_post.html.erb
invoke resource_route
invoke rspec
create spec/requests/posts_spec.rb
create spec/views/posts/edit.html.erb_spec.rb
create spec/views/posts/index.html.erb_spec.rb
create spec/views/posts/new.html.erb_spec.rb
create spec/views/posts/show.html.erb_spec.rb
create spec/routing/posts_routing_spec.rb
invoke helper
create app/helpers/posts_helper.rb
invoke rspec
create spec/helpers/posts_helper_spec.rb
invoke jbuilder
create app/views/posts/index.json.jbuilder
create app/views/posts/show.json.jbuilder
create app/views/posts/_post.json.jbuilder
invoke policy
create app/policies/post_policy.rb
invoke rspec
create spec/policies/post_policy_spec.rb
Generated PostsController:
class PostsController < ApplicationController
before_action :set_post, only: %i[show edit update destroy]
# GET /posts
def index
@posts = policy_scope(Post.all)
end
# GET /posts/1
def show
authorize @post
end
# GET /posts/new
def new
@post = Post.new
authorize @post
end
# GET /posts/1/edit
def edit
authorize @post
end
# POST /posts
def create
@post = Post.new(post_params)
authorize @post
if @post.save
redirect_to @post, notice: "Post was successfully created."
else
render :new, status: :unprocessable_entity
end
end
# PATCH/PUT /posts/1
def update
authorize @post
if @post.update(post_params)
redirect_to @post, notice: "Post was successfully updated.", status: :see_other
else
render :edit, status: :unprocessable_entity
end
end
# DELETE /posts/1
def destroy
authorize @post
@post.destroy!
redirect_to posts_url, notice: "Post was successfully destroyed.", status: :see_other
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
@post = Post.find(params[:id])
authorize @post
end
# Only allow a list of trusted parameters through.
def post_params
params.fetch(:post, {})
end
end
I believe this introduces a dependency on Rails? Pundit should not have Rails as a dependency.
I hope that by adding the condition require "pundit/railtie" if defined?(Rails), it is ensured that the gem can be used in both Rails and non-Rails Ruby environments. This makes the inclusion of the Railtie and generators optional and dependent on the runtime context.
I hope that by adding the condition
require "pundit/railtie" if defined?(Rails), it is ensured that the gem can be used in both Rails and non-Rails Ruby environments. This makes the inclusion of the Railtie and generators optional and dependent on the runtime context.
I believe you're correct, that seems like it's the recommended approach when viewing the documentation: https://api.rubyonrails.org/classes/Rails/Railtie.html
I'm for the spirit of more guidance in how to use Pundit, and making it more convenient.
However, I'm significantly more hesitant towards providing and maintaining controller generation templates. That's a lot of code to have an opinion on, when Pundit is mostly only concerned with a relatively small part of the generated code.
My gut feeling is that I'd like a more surgical approach. I'm not sure that's possible.
Regardless I feel I also need to run this PR by another maintainer friend before making a decision.
I also missed that this PR was born out of https://github.com/varvet/pundit/issues/735
It's worth mentioning that I still think that generating policies automatically on scaffold is a good idea. Pundit kind of own policies in that sense, and can have opinions on how to write those.
Thank you for your work. I've decided that maintaining controller templates is not something for Pundit to do.