Skip to content

Commit

Permalink
Add context to Page
Browse files Browse the repository at this point in the history
  • Loading branch information
goosys committed Sep 8, 2024
1 parent 6fb318f commit 8ef9389
Show file tree
Hide file tree
Showing 17 changed files with 248 additions and 38 deletions.
53 changes: 41 additions & 12 deletions app/controllers/administrate/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ class ApplicationController < ActionController::Base
def index
authorize_resource(resource_class)
search_term = params[:search].to_s.strip
resources = filter_resources(scoped_resource, search_term: search_term)
authorized_scope = authorize_scope(scoped_resource)
resources = filter_resources(authorized_scope, search_term: search_term)
resources = apply_collection_includes(resources)
resources = order.apply(resources)
resources = paginate_resources(resources)
page = Administrate::Page::Collection.new(dashboard, order: order)
page.context = self

render locals: {
resources: resources,
Expand All @@ -20,28 +22,39 @@ def index
end

def show
page = Administrate::Page::Show.new(dashboard, requested_resource)
page.context = self
render locals: {
page: Administrate::Page::Show.new(dashboard, requested_resource)
page: page
}
end

def new
resource = new_resource
authorize_resource(resource)
resource = new_resource.tap do |resource|
authorize_resource(resource)
contextualize_resource(resource)
end

page = Administrate::Page::Form.new(dashboard, resource)
page.context = self
render locals: {
page: Administrate::Page::Form.new(dashboard, resource)
page: page
}
end

def edit
page = Administrate::Page::Form.new(dashboard, requested_resource)
page.context = self
render locals: {
page: Administrate::Page::Form.new(dashboard, requested_resource)
page: page
}
end

def create
resource = new_resource(resource_params)
authorize_resource(resource)
resource = new_resource(resource_params).tap do |resource|
authorize_resource(resource)
contextualize_resource(resource)
end

if resource.save
yield(resource) if block_given?
Expand All @@ -50,8 +63,10 @@ def create
notice: translate_with_resource("create.success")
)
else
page = Administrate::Page::Form.new(dashboard, resource)
page.context = self
render :new, locals: {
page: Administrate::Page::Form.new(dashboard, resource)
page: page
}, status: :unprocessable_entity
end
end
Expand All @@ -64,8 +79,10 @@ def update
status: :see_other
)
else
page = Administrate::Page::Form.new(dashboard, requested_resource)
page.context = self
render :edit, locals: {
page: Administrate::Page::Form.new(dashboard, requested_resource)
page: page
}, status: :unprocessable_entity
end
end
Expand Down Expand Up @@ -184,11 +201,16 @@ def dashboard
def requested_resource
@requested_resource ||= find_resource(params[:id]).tap do |resource|
authorize_resource(resource)
contextualize_resource(resource)
end
end

def find_resource(param)
scoped_resource.find(param)
authorize_scope(scoped_resource).find(param)
end

def authorize_scope(scope)
scope
end

def scoped_resource
Expand All @@ -203,7 +225,7 @@ def apply_collection_includes(relation)

def resource_params
params.require(resource_class.model_name.param_key)
.permit(dashboard.permitted_attributes(action_name))
.permit(dashboard.permitted_attributes(action_name, self))
.transform_values { |v| read_param_value(v) }
end

Expand Down Expand Up @@ -285,6 +307,13 @@ def authorize_resource(resource)
end
end

# Override this if you want to contextualize the resource differently.
#
# @param resource A resource to be contextualized.
# @return nothing
def contextualize_resource(resource)
end

def paginate_resources(resources)
resources.page(params[:_page]).per(records_per_page)
end
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/concerns/administrate/punditize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ def policy_namespace
[]
end

def scoped_resource
namespaced_scope = policy_namespace + [super]
def authorize_scope(scope)
namespaced_scope = policy_namespace + [scope]
policy_scope!(pundit_user, namespaced_scope)
end

Expand Down
11 changes: 11 additions & 0 deletions docs/customizing_controller_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ class Admin::FoosController < Admin::ApplicationController
# resource_class.with_less_stuff
# end
# end


# Override this if you want to contextualize the resource differently.
# This will be used to contextualize the resource for the all actions without `index`.
#
# def contextualize_resource(resource)
# case action_name
# when "new", "create"
# resource.author = current_user
# end
# end
end
```

Expand Down
6 changes: 3 additions & 3 deletions lib/administrate/base_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def all_attributes
attribute_types.keys
end

def form_attributes(action = nil)
def form_attributes(action = nil, _context = nil)
action =
case action
when "update" then "edit"
Expand All @@ -69,8 +69,8 @@ def specific_form_attributes_for(action)
self.class.const_get(cname) if self.class.const_defined?(cname)
end

def permitted_attributes(action = nil)
attributes = form_attributes action
def permitted_attributes(action = nil, context = nil)
attributes = form_attributes(action, context)

if attributes.is_a? Hash
attributes = attributes.values.flatten
Expand Down
7 changes: 6 additions & 1 deletion lib/administrate/field/belongs_to.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ def include_blank_option
private

def candidate_resources
scope = options[:scope] ? options[:scope].call : associated_class.all
scope =
if options[:scope]
options[:scope].call(self)
else
associated_class.all
end

order = options.delete(:order)
order ? scope.reorder(order) : scope
Expand Down
2 changes: 2 additions & 0 deletions lib/administrate/page/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def item_associations
dashboard.try(:item_associations) || []
end

attr_accessor :context

private

def attribute_field(dashboard, resource, attribute_name, page)
Expand Down
2 changes: 1 addition & 1 deletion lib/administrate/page/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def initialize(dashboard, resource)
attr_reader :resource

def attributes(action = nil)
attributes = dashboard.form_attributes(action)
attributes = dashboard.form_attributes(action, context)

if attributes.is_a? Array
attributes = {"" => attributes}
Expand Down
20 changes: 18 additions & 2 deletions spec/controllers/admin/customers_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
describe Admin::CustomersController, type: :controller do
describe "GET index" do
it "passes all customers to the view" do
customer = create(:customer)
customers = create_list(:customer, 5)

locals = capture_view_locals { get :index }
expect(locals[:resources]).to eq([customer])
expect(locals[:resources]).to eq(customers)
end

it "applies any scope overrides" do
Expand Down Expand Up @@ -47,6 +47,22 @@
expect(locals[:resources].map(&:id)).to eq customers.map(&:id).sort
end

context "when the user is an admin" do
controller(Admin::CustomersController) do
def authenticate_admin
@current_user = Customer.last
end
end

it "passes one customers to the view" do
_other_customers = create_list(:customer, 5)
customer = create(:customer)

locals = capture_view_locals { get :index }
expect(locals[:resources]).to eq([customer])
end
end

context "with alternate sorting attributes" do
controller(Admin::CustomersController) do
def default_sorting_attribute
Expand Down
66 changes: 62 additions & 4 deletions spec/controllers/admin/orders_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ def pundit_user
end

describe "GET new" do
it "raises a Pundit error" do
expect { get :new }.to raise_error(Pundit::NotAuthorizedError)
it "allows me to new my records" do
expect { get :new }.not_to raise_error
end
end

Expand Down Expand Up @@ -154,8 +154,8 @@ def pundit_user
end

describe "GET new" do
it "raises a Pundit error" do
expect { get :new }.to raise_error(Pundit::NotAuthorizedError)
it "allows me to new my records" do
expect { get :new }.not_to raise_error
end
end

Expand Down Expand Up @@ -233,6 +233,64 @@ def send_request(order:)
expect(controller.send(:authorized_action?, o, :destroy)).to be false
end
end

context "when the user is an admin" do
controller(Admin::OrdersController) do
def pundit_user
Struct.new(:admin?).new(true)
end
end

let!(:user) { create(:customer, name: "Target User") }

describe "GET new" do
it "allows me to new my records" do
expect { get :new }.not_to raise_error
end
end

describe "POST create" do
it "allows me to create my records with target user" do
post(
:create,
params: {
order: attributes_for(:order, customer_id: user.id)
}
)
expect(response).to redirect_to([:admin, (order = Order.last)])
expect(order.customer).to eq(user)
end
end
end
end

context "when the user is not an admin" do
controller(Admin::OrdersController) do
def pundit_user
Customer.find_by(name: "Current User")
end
end

let!(:user) { create(:customer, name: "Current User") }

describe "GET new" do
it "allows me to new records" do
expect { get :new }.not_to raise_error
end
end

describe "POST create" do
it "allows me to create my records with current customer" do
post(
:create,
params: {
order: attributes_for(:order)
}
)
expect(response).to redirect_to([:admin, (order = Order.last)])
expect(order.customer).to eq(user)
end
end
end
end
# standard:enable Lint/ConstantDefinitionInBlock
Loading

0 comments on commit 8ef9389

Please sign in to comment.