Module: Layered::Resource::Controller

Extended by:
ActiveSupport::Concern
Included in:
ResourcesController
Defined in:
app/controllers/layered/resource/controller.rb

Overview

All the controller behaviour for a layered resource. Concern so that host engines can declare their own ResourcesController inheriting from their own ApplicationController and still pick up the full DSL:

class Layered::Assistant::ResourcesController < Layered::Assistant::ApplicationController
include Layered::Resource::Controller
end

The default Layered::Resource::ResourcesController < ::ApplicationController exists for non-engine host apps that just want everything wired up.

Instance Method Summary collapse

Instance Method Details

#_prefixesObject

View lookup chain:

1. layered/<resource_name>/                 — host-app per-resource override (e.g. `app/views/layered/posts/`)
2. <controller's own inheritance prefixes>  — host's own layout chain
3. layered/resource/resources/              — gem-shipped defaults (always last)

The trailing default ensures custom subclasses (like CustomNamespace::ResourcesController including Layered::Resource::Controller) still find the gem's templates without re-declaring view paths.



154
155
156
157
158
159
160
161
# File 'app/controllers/layered/resource/controller.rb', line 154

def _prefixes
  base = super
  prefixes = []
  prefixes << "layered/#{@layered_resource_name}" if @layered_resource_name
  prefixes.concat(base)
  prefixes << "layered/resource/resources" unless prefixes.include?("layered/resource/resources")
  prefixes
end

#createObject



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/controllers/layered/resource/controller.rb', line 71

def create
  @record = @resource.build_record(self)
  authorize_layered_record(@record)
  @record.assign_attributes(layered_resource_params)

  if @record.save
    redirect_to @resource.after_save_path(self, @record),
                notice: t("layered.resource.flash.created", model: @resource.model.model_name.human)
  else
    @form_url = layered_collection_path
    render :new, status: :unprocessable_entity
  end
end

#destroyObject



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'app/controllers/layered/resource/controller.rb', line 105

def destroy
  @record = @resource.scope(self).find(params[:id])
  authorize_layered_record(@record)
  redirect_path = @resource.after_save_path(self, @record)
  model_name = @resource.model.model_name.human
  begin
    if @record.destroy
      redirect_to redirect_path, notice: t("layered.resource.flash.deleted", model: model_name)
    else
      redirect_to redirect_path, alert: t("layered.resource.flash.not_deleted", model: model_name)
    end
  rescue ActiveRecord::InvalidForeignKey, ActiveRecord::DeleteRestrictionError
    redirect_to redirect_path,
                alert: t("layered.resource.flash.dependent_records", model: model_name)
  end
end

#editObject



85
86
87
88
89
90
# File 'app/controllers/layered/resource/controller.rb', line 85

def edit
  @record = @resource.scope(self).find(params[:id])
  authorize_layered_record(@record)
  @form_url = layered_member_path(@record)
  @page_title = "Edit #{layered_record_label(@record)}"
end

#indexObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'app/controllers/layered/resource/controller.rb', line 42

def index
  apply_layered_filter_defaults
  @q = @resource.scope(self).ransack(params[:q], auth_object: @resource)
  if @q.sorts.empty?
    ds = @resource.default_sort
    @q.sorts = "#{ds[:attribute]} #{ds[:direction]}"
  end
  scope = @q.result(distinct: @resource.requires_distinct?)

  # Pagy rebuilds page links from the full request query; `fo` (the
  # one-shot open-this-tag's-popover param from the add-filter link)
  # must not ride along or paginating would reopen the popover.
  @pagy, @records = pagy(scope, limit: @resource.per_page,
                                querify: ->(query) { query.delete("fo") })
  decorate_columns
end

#newObject



65
66
67
68
69
# File 'app/controllers/layered/resource/controller.rb', line 65

def new
  @record = @resource.build_record(self)
  authorize_layered_record(@record)
  @form_url = layered_collection_path
end

#resource_can?(action, record = nil) ⇒ Boolean

Composes the route-exposure flag for an action with the per-record Pundit policy when use_pundit is enabled. action is one of :new, :create, :show, :edit, :update, :destroy. Each key gates the route of the same name and runs the matching Pundit query (new?, create?, etc.). Pass a record to gate on an individual record (e.g. inside the index row); omit it to fall back to the class-level policy (policy(@resource.model)). Without use_pundit this just returns the @resource_can_* flag.

Returns:

  • (Boolean)


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/controllers/layered/resource/controller.rb', line 130

def resource_can?(action, record = nil)
  flag = case action
         when :new     then @resource_can_new
         when :create  then @resource_can_create
         when :show    then @resource_can_show
         when :edit    then @resource_can_edit
         when :update  then @resource_can_update
         when :destroy then @resource_can_destroy
         else raise ArgumentError, "unknown action #{action.inspect}"
         end
  return false unless flag
  return true unless @resource.pundit_enabled?

  policy(record || @resource.model).public_send(:"#{action}?")
end

#showObject



59
60
61
62
63
# File 'app/controllers/layered/resource/controller.rb', line 59

def show
  @record = @resource.scope(self).find(params[:id])
  authorize_layered_record(@record)
  @page_title = layered_record_label(@record)
end

#updateObject



92
93
94
95
96
97
98
99
100
101
102
103
# File 'app/controllers/layered/resource/controller.rb', line 92

def update
  @record = @resource.scope(self).find(params[:id])
  authorize_layered_record(@record)
  if @record.update(layered_resource_params)
    redirect_to @resource.after_save_path(self, @record),
                notice: t("layered.resource.flash.updated", model: @resource.model.model_name.human)
  else
    @form_url = layered_member_path(@record)
    @page_title = "Edit #{layered_record_label(@record)}"
    render :edit, status: :unprocessable_entity
  end
end