Class: CurrentScope::SubjectsController
- Inherits:
-
ApplicationController
- Object
- ApplicationController
- CurrentScope::SubjectsController
- Defined in:
- app/controllers/current_scope/subjects_controller.rb
Constant Summary collapse
- PER_PAGE =
50- SEARCH_COLUMNS =
Identity columns searched by ?q=, in the same preference order as current_scope_subject_label's default chain. Intersected with the subject table's real column_names before use, so a query never spans a page.
%w[email email_address name first_name last_name].freeze
Instance Method Summary collapse
Instance Method Details
#index ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'app/controllers/current_scope/subjects_controller.rb', line 10 def index @query = params[:q].to_s.strip scope = filter_subjects(subject_class.order(:id), @query) @page = [ params[:page].to_i, 1 ].max @subjects = scope.limit(PER_PAGE).offset((@page - 1) * PER_PAGE) @has_next_page = scope.offset(@page * PER_PAGE).exists? @roles = Role.order(:name) # Match on the ids as strings: `where(subject: @subjects)` would build # `subject_id IN (SELECT id ...)`, comparing a varchar column to a bigint # subquery, which PostgreSQL refuses (#151). # Group by each subject's OWN polymorphic_name, not the configured class's: # an STI subclass that overrides it stores grants under a different token, so # a single where(subject_type:) would omit them (#151). One type in the # common case; the per-type OR keeps the STI case correct for one extra WHERE. subject_ids_by_type = @subjects.group_by { |subject| subject.class.polymorphic_name } .transform_values { |subjects| subjects.map { |subject| subject.id.to_s } } assignment_scope = subject_ids_by_type.reduce(RoleAssignment.none) do |relation, (type, ids)| relation.or(RoleAssignment.where(subject_type: type, subject_id: ids)) end @assignments = assignment_scope .index_by { |a| [ a.subject_type, a.subject_id.to_s ] } # Safe polymorphic resource preload (resolvable types only) — full # includes(:resource) NameErrors on a stale resource_type and 500s the # page; skip-unresolvable + label as inert instead (#90 / PR #104). scoped_scope = subject_ids_by_type.reduce(ScopedRoleAssignment.none) do |relation, (type, ids)| relation.or(ScopedRoleAssignment.where(subject_type: type, subject_id: ids)) end scoped_rows = scoped_scope.includes(:role).to_a ScopedRoleAssignment.preload_resolvable_resources!(scoped_rows) # to_s to match the view's key: subject_id is a string column (#151). @scoped = scoped_rows.group_by { |a| [ a.subject_type, a.subject_id.to_s ] } end |