refactor api and fix bugs (#1088)
* fix weird double-embed issue * fix users/current api if not logged in * turbocharge the api * fix docs
This commit is contained in:
parent
780e66632b
commit
e544d6a6db
4 changed files with 33 additions and 33 deletions
|
@ -3,6 +3,7 @@ module Api
|
||||||
module V2
|
module V2
|
||||||
class UsersController < RestfulController
|
class UsersController < RestfulController
|
||||||
def current
|
def current
|
||||||
|
raise Pundit::NotAuthorizedError if current_user.nil?
|
||||||
@user = current_user
|
@user = current_user
|
||||||
authorize @user
|
authorize @user
|
||||||
show # delegate to the normal show function
|
show # delegate to the normal show function
|
||||||
|
|
|
@ -13,50 +13,49 @@ module Api
|
||||||
@embeds ||= (scope[:embeds] || []).select { |e| self.class.embeddable.keys.include?(e) }
|
@embeds ||= (scope[:embeds] || []).select { |e| self.class.embeddable.keys.include?(e) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# self.embeddable might look like this:
|
# Here's an example object that could be passed in self.embeddable: {
|
||||||
# creator: { attr: :first_creator, serializer: UserSerializer }
|
# creator: {
|
||||||
# contributors: { serializer: UserSerializer}
|
# serializer: UserSerializer,
|
||||||
# This method will remove the :attr key if the underlying attribute name
|
# },
|
||||||
# is different than the name provided in the final json output. All other keys
|
# collaborators: {
|
||||||
# in the hash will be passed to the ActiveModel::Serializer `attribute` method
|
# serializer: UserSerializer
|
||||||
# directly (e.g. serializer in the examples will be passed).
|
# },
|
||||||
#
|
# topic: {},
|
||||||
# This setup means if you passed this self.embeddable config and sent no
|
# synapses: {}
|
||||||
# ?embed= query param with your API request, you would get the regular attributes
|
# }
|
||||||
# plus creator_id and contributor_ids. If you passed ?embed=creator,contributors
|
# The key has to be in embeddable or it won't show in the response, and the serializer is
|
||||||
# then instead of an id and an array of ids, you would get a serialized user
|
# only needed if the key doesn't match a serializer
|
||||||
# (the first_creator) and an array of serialized users (the contributors).
|
|
||||||
def self.embed_dat
|
def self.embed_dat
|
||||||
embeddable.each_pair do |key, opts|
|
embeddable.each_pair do |key, opts|
|
||||||
attr = opts.delete(:attr) || key
|
is_plural = key.to_s.pluralize == key.to_s
|
||||||
if attr.to_s.pluralize == attr.to_s
|
id_key = key.to_s.singularize + (is_plural ? '_ids' : '_id')
|
||||||
attribute("#{attr.to_s.singularize}_ids".to_sym,
|
serializer = opts.delete(:serializer) || "Api::V2::#{key.to_s.singularize.camelize}Serializer".constantize
|
||||||
opts.merge(unless: -> { embeds.include?(key) })) do
|
if is_plural
|
||||||
Pundit.policy_scope(scope[:current_user], object.send(attr))&.map(&:id) || []
|
attribute(id_key.to_sym, opts.merge(unless: -> { embeds.include?(key) })) do
|
||||||
|
Pundit.policy_scope(scope[:current_user], object.send(key))&.map(&:id) || []
|
||||||
end
|
end
|
||||||
has_many(attr, opts.merge(if: -> { embeds.include?(key) })) do
|
has_many(key, opts.merge(if: -> { embeds.include?(key) })) do
|
||||||
list = Pundit.policy_scope(scope[:current_user], object.send(attr)) || []
|
list = Pundit.policy_scope(scope[:current_user], object.send(key)) || []
|
||||||
child_serializer = "Api::V2::#{attr.to_s.singularize.camelize}Serializer".constantize
|
|
||||||
resource = ActiveModelSerializers::SerializableResource.new(
|
resource = ActiveModelSerializers::SerializableResource.new(
|
||||||
list,
|
list,
|
||||||
each_serializer: child_serializer,
|
each_serializer: serializer,
|
||||||
scope: scope.merge(embeds: [])
|
scope: scope.merge(embeds: [])
|
||||||
)
|
)
|
||||||
resource.as_json
|
# resource.as_json will return e.g. { users: [ ... ] } for collaborators
|
||||||
|
# since we can't get the :users key, convert to an array and use .first.second to get the needed values
|
||||||
|
resource&.as_json&.to_a&.first&.second
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
id_opts = opts.merge(key: "#{key}_id")
|
attribute(id_key.to_sym, opts.merge(unless: -> { embeds.include?(key) }))
|
||||||
attribute("#{attr}_id".to_sym,
|
attribute(key, opts.merge(if: -> { embeds.include?(key) })) do |parent_serializer|
|
||||||
id_opts.merge(unless: -> { embeds.include?(key) }))
|
object = parent_serializer.object.send(key)
|
||||||
attribute(key, opts.merge(if: -> { embeds.include?(key) })) do |serializer|
|
next nil if object.nil?
|
||||||
object = serializer.object.send(key)
|
|
||||||
child_serializer = "Api::V2::#{object.class.name}Serializer".constantize
|
|
||||||
resource = ActiveModelSerializers::SerializableResource.new(
|
resource = ActiveModelSerializers::SerializableResource.new(
|
||||||
object,
|
object,
|
||||||
serializer: child_serializer,
|
serializer: serializer,
|
||||||
scope: scope.merge(embeds: [])
|
scope: scope.merge(embeds: [])
|
||||||
)
|
)
|
||||||
resource.as_json
|
resource&.as_json&.to_a&.first&.second
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Api
|
||||||
def self.embeddable
|
def self.embeddable
|
||||||
{
|
{
|
||||||
user: {},
|
user: {},
|
||||||
source: {},
|
source: { serializer: MapSerializer },
|
||||||
topics: {},
|
topics: {},
|
||||||
synapses: {},
|
synapses: {},
|
||||||
mappings: {},
|
mappings: {},
|
||||||
|
|
|
@ -14,7 +14,7 @@ module Api
|
||||||
def self.embeddable
|
def self.embeddable
|
||||||
{
|
{
|
||||||
user: {},
|
user: {},
|
||||||
updated_by: {},
|
updated_by: { serializer: UserSerializer },
|
||||||
map: {}
|
map: {}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue