Class: Scimitar::ActiveRecordBackedResourcesController

Inherits:
ResourcesController show all
Defined in:
app/controllers/scimitar/active_record_backed_resources_controller.rb

Overview

An ActiveRecord-centric subclass of Scimitar::ResourcesController. See that class’s documentation first, as it describes things that your subclass must do which apply equally to subclasses of this ActiveRecord-focused code.

In addition to requirements mentioned above, your subclass MUST override protected method #storage_scope, returning an ActiveRecord::Relation which is used as a starting scope for any ‘index’ (list) views. This gives you an opportunity to apply things like is-active filters, apply soft deletion scopes, apply security scopes and so-on. For example:

protected
  def storage_scope
    self.storage_class().where(is_deleted: false)
  end

Instance Method Summary collapse

Instance Method Details

#create(&block) ⇒ Object

POST (create)

Calls #save! on the new record if no block is given, else invokes the block, passing it the new ActiveRecord model instance to be saved. It is up to the block to make any further changes and persist the record.

Blocks are invoked from within a wrapping database transaction. ActiveRecord::RecordInvalid exceptions are handled for you, rendering an appropriate SCIM error.



71
72
73
74
75
76
77
78
79
80
# File 'app/controllers/scimitar/active_record_backed_resources_controller.rb', line 71

def create(&block)
  super do |scim_resource|
    self.storage_class().transaction do
      record = self.storage_class().new
      record.from_scim!(scim_hash: scim_resource.as_json())
      self.save!(record, &block)
      record_to_scim(record)
    end
  end
end

#destroy(&block) ⇒ Object

DELETE (remove)

Deletion methods can vary quite a lot with ActiveRecord objects. If you just let this superclass handle things, it’ll call:

https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-destroy-21

…i.e. the standard delete-record-with-callbacks method. If you pass a block, then this block is invoked and passed the ActiveRecord model instance to be destroyed. You can then do things like soft-deletions, updating an “active” flag, perform audit-related operations and so-on.



128
129
130
131
132
133
134
135
136
137
138
# File 'app/controllers/scimitar/active_record_backed_resources_controller.rb', line 128

def destroy(&block)
  super do |record_id|
    record = self.find_record(record_id)

    if block_given?
      yield(record)
    else
      record.destroy!
    end
  end
end

#indexObject

GET (list)



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'app/controllers/scimitar/active_record_backed_resources_controller.rb', line 28

def index
  query = if params[:filter].blank?
    self.storage_scope()
  else
    attribute_map = storage_class().new.scim_queryable_attributes()
    parser        = ::Scimitar::Lists::QueryParser.new(attribute_map)

    parser.parse(params[:filter])
    parser.to_activerecord_query(self.storage_scope())
  end

  pagination_info = scim_pagination_info(query.count())

  page_of_results = query
    .order(@id_column => :asc)
    .offset(pagination_info.offset)
    .limit(pagination_info.limit)
    .to_a()

  super(pagination_info, page_of_results) do | record |
    record_to_scim(record)
  end
end

#replace(&block) ⇒ Object

PUT (replace)

Calls #save! on the updated record if no block is given, else invokes the block, passing the updated record which the block must persist, with the same rules as for #create.



88
89
90
91
92
93
94
95
96
97
# File 'app/controllers/scimitar/active_record_backed_resources_controller.rb', line 88

def replace(&block)
  super do |record_id, scim_resource|
    self.storage_class().transaction do
      record = self.find_record(record_id)
      record.from_scim!(scim_hash: scim_resource.as_json())
      self.save!(record, &block)
      record_to_scim(record)
    end
  end
end

#showObject

GET/id (show)



54
55
56
57
58
59
# File 'app/controllers/scimitar/active_record_backed_resources_controller.rb', line 54

def show
  super do |record_id|
    record = self.find_record(record_id)
    record_to_scim(record)
  end
end

#update(&block) ⇒ Object

PATCH (update)

Calls #save! on the updated record if no block is given, else invokes the block, passing the updated record which the block must persist, with the same rules as for #create.



105
106
107
108
109
110
111
112
113
114
# File 'app/controllers/scimitar/active_record_backed_resources_controller.rb', line 105

def update(&block)
  super do |record_id, patch_hash|
    self.storage_class().transaction do
      record = self.find_record(record_id)
      record.from_scim_patch!(patch_hash: patch_hash)
      self.save!(record, &block)
      record_to_scim(record)
    end
  end
end