Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 36 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
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.

Following on my comment about contextualize_resource, I wonder if this is what it should be doing instead? Acting on the page instead of the resource here:

Suggested change
page.context = self
contextualize_page(page)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the Controller object is almost essential as a Context for the Page, so how about passing it to the initializer? Like the following:

page = Administrate::Page::Collection.new(dashboard, context: self, order: order)
or
page = Administrate::Page::Collection.new(dashboard, controller: self, order: order)

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.

Initially that makes sense, but then the developers wouldn't be able to alter the context easily with a hook like contextualize_page. Having said that, perhaps there isn't a use case for that...? I have no idea yet. I'm experimenting now to see the possibilities of your PR.

filters = Administrate::Search.new(scoped_resource, dashboard, search_term).valid_filters

render locals: {
Expand All @@ -24,29 +25,40 @@ 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)
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
@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)
contextualize_resource(resource)
end

if resource.save
yield(resource) if block_given?
Expand All @@ -55,8 +67,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 +84,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,12 +194,15 @@ 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
@requested_resource ||= find_resource(params[:id]).tap do |resource|
authorize_resource(resource)
contextualize_resource(resource)
end
end

Expand Down Expand Up @@ -277,6 +296,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
16 changes: 13 additions & 3 deletions docs/customizing_controller_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@ class Admin::FoosController < Admin::ApplicationController
# send_foo_updated_email
# end

# Override this method to specify custom lookup behavior.
# This will be used to set the resource for the `show`, `edit`, and `update`
# actions.
#
# def find_resource(param)
# 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 All @@ -41,6 +40,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
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)) if options.key?(:includes)

order = options.delete(: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
10 changes: 9 additions & 1 deletion lib/administrate/page/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,19 @@ 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

def get_attribute_value(resource, attribute_name)
resource.public_send(attribute_name)
end

attr_reader :dashboard, :options
Expand Down
Loading
Loading