Skip to content
36 changes: 26 additions & 10 deletions app/controllers/administrate/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def index
resources = paginate_resources(resources)
@resources = resources
page = Administrate::Page::Collection.new(dashboard, order: order)
page.context = self
Comment thread
pablobm marked this conversation as resolved.
filters = Administrate::Search.new(scoped_resource, dashboard, search_term).valid_filters

render locals: {
Expand All @@ -24,29 +25,38 @@ def index

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

def new
@resource = resource = new_resource
authorize_resource(resource)
@resource = resource = new_resource.tap do |resource|
authorize_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
@resource = resource = requested_resource
page = Administrate::Page::Form.new(dashboard, resource)
page.context = self
render locals: {
page: Administrate::Page::Form.new(dashboard, resource)
page: page
}
end

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

if resource.save
yield(resource) if block_given?
Expand All @@ -55,8 +65,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 @@ -70,8 +82,10 @@ def update
status: :see_other
)
else
page = Administrate::Page::Form.new(dashboard, resource)
page.context = self
render :edit, locals: {
page: Administrate::Page::Form.new(dashboard, resource)
page: page
}, status: :unprocessable_entity
end
end
Expand Down Expand Up @@ -178,7 +192,9 @@ def sorting_params
end

def dashboard
@dashboard ||= dashboard_class.new
@dashboard ||= dashboard_class.new.tap do |d|
d.context = self
end
end

def requested_resource
Expand Down
4 changes: 2 additions & 2 deletions docs/customizing_controller_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class Admin::FoosController < Admin::ApplicationController
# Foo.find_by!(slug: param)
# end

# Override this if you have certain roles that require a subset
# this will be used to set the records shown on the `index` action.
# Override this if you have certain roles that require a subset.
# This will be used in all actions except for the `new` and `create` actions
#
# def scoped_resource
# if current_user.super_admin?
Expand Down
4 changes: 3 additions & 1 deletion lib/administrate/base_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def specific_form_attributes_for(action)
end

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

if attributes.is_a? Hash
attributes = attributes.values.flatten
Expand Down Expand Up @@ -120,6 +120,8 @@ def item_associations
attribute_associated attributes
end

attr_accessor :context

private

def attribute_not_found_message(attr)
Expand Down
4 changes: 3 additions & 1 deletion lib/administrate/field/associative.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ def html_controller
private

def associated_dashboard
"#{associated_class_name}Dashboard".constantize.new
"#{associated_class_name}Dashboard".constantize.new.tap do |d|
d.context = context
end
end

def association_primary_key
Expand Down
11 changes: 8 additions & 3 deletions lib/administrate/field/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,22 @@ def self.local_partial_prefixes(look: :default)
end
end

def initialize(attribute, data, page, options = {})
def initialize(attribute, raw_data, page, options = {})
@attribute = attribute
@page = page
@resource = options.delete(:resource)
@options = options
@data = read_value(data)
@raw_data = raw_data
end

def html_class
self.class.html_class
end

def data
read_value(@raw_data)
end

def html_controller
nil
end
Expand Down Expand Up @@ -133,7 +137,8 @@ def required?
end
end

attr_reader :attribute, :data, :options, :page, :resource
attr_reader :attribute, :options, :page, :resource
attr_accessor :context
end
end
end
17 changes: 9 additions & 8 deletions lib/administrate/field/has_many.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ def associated_collection(order = self.order)
associated_dashboard,
order: order,
collection_attributes: options[:collection_attributes]
)
).tap do |page|
page.context = context
end
end

def attribute_key
Expand Down Expand Up @@ -76,7 +78,7 @@ def more_than_limit?
end

def data
@data ||= associated_class.none
super || associated_class.none
end

def order_from_params(params)
Expand Down Expand Up @@ -106,12 +108,11 @@ def includes
end

def candidate_resources
if options.key?(:includes)
includes = options.fetch(:includes)
associated_class.includes(*includes).all
else
associated_class.all
end
scope = options[:scope] ? options[:scope].call(self) : associated_class.all
scope = scope.includes(options.fetch(:includes, []))

order = options[:order]
order ? scope.reorder(order) : scope
end

def display_candidate_resource(resource)
Expand Down
8 changes: 6 additions & 2 deletions lib/administrate/field/has_one.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ def nested_form
@nested_form ||= Administrate::Page::Form.new(
resolver.dashboard_class.new,
data || resolver.resource_class.new
)
).tap do |page|
page.context = context
end
end

def nested_show
@nested_show ||= Administrate::Page::Show.new(
resolver.dashboard_class.new,
data || resolver.resource_class.new
)
) do |page|
page.context = context
end
end

def linkable?
Expand Down
6 changes: 4 additions & 2 deletions lib/administrate/field/polymorphic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ def selected_global_id
private

def associated_dashboard(klass = data.class)
"#{klass.name}Dashboard".constantize.new
"#{klass.name}Dashboard".constantize.new.tap do |d|
d.context = context
end
end

def classes
klasses = options.fetch(:classes, [])
klasses.respond_to?(:call) ? klasses.call : klasses
klasses.respond_to?(:call) ? klasses.call(self) : klasses
end

private
Expand Down
6 changes: 5 additions & 1 deletion lib/administrate/page/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ def item_associations
dashboard.try(:item_associations) || []
end

attr_accessor :context

private

def attribute_field(dashboard, resource, attribute_name, page)
field = dashboard.attribute_type_for(attribute_name)
field.new(attribute_name, nil, page, resource: resource)
field.new(attribute_name, nil, page, resource: resource).tap do |f|
f.context = context
end
end

attr_reader :dashboard, :options
Expand Down
20 changes: 18 additions & 2 deletions spec/controllers/admin/customers_controller_spec.rb

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the changes to this file? They seem unrelated.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unreliable to get the "last" customer, which you expect to be the customer = create(:customer) but won't always be because order is not guaranteed by SQL unless there's an explicit ORDER BY. This test may fail randomly.

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
33 changes: 31 additions & 2 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 access to /new" do
expect { get :new }.not_to raise_error

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something that I'm not sure about with this is that it removes a place where this type of authorization error is tested. Although the specs are a mess anyway already so things like this are difficult to avoid.

Perhaps a case for Pundit::NotAuthorizedError could be created somewhere else? For example test payments/new.

Also, the context setup at the top (context "with namespaced Punditize concern" do) can now lose the include and the def policy_namespace as I don't think they affect the test any more. (I think this was the case with the include already).

end
end

Expand Down Expand Up @@ -106,5 +106,34 @@ def send_request(order:)
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 access to /new" do
expect { get :new }.not_to raise_error
end
end

describe "POST create" do
it "allows creating records with the 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