class HaveAPI::ModelAdapters::ActiveRecord::Output
Public Class Methods
used_by(action)
click to toggle source
# File lib/haveapi/model_adapters/active_record.rb, line 156 def self.used_by(action) action.meta(:object) do output do custom :path_params, label: 'URL parameters', desc: 'An array of parameters needed to resolve URL to this object' bool :resolved, label: 'Resolved', desc: 'True if the association is resolved' end end return unless %i[object object_list].include?(action.input.layout) clean = proc do |raw| if raw.is_a?(String) raw.strip.split(',') elsif raw.is_a?(Array) raw end end desc = <<~END A list of names of associated resources separated by a comma. Nested associations are declared with '__' between resource names. For example, 'user,node' will resolve the two associations. To resolve further associations of node, use e.g. 'user,node__location', to go even deeper, use e.g. 'user,node__location__environment'. END action.meta(:global) do input do custom :includes, label: 'Included associations', desc:, &clean end end action.send(:include, Action::InstanceMethods) end
Public Instance Methods
[](name)
click to toggle source
# File lib/haveapi/model_adapters/active_record.rb, line 198 def [](name) param = @context.action.output[name] v = @object.send(param.db_name) if v.is_a?(::ActiveRecord::Base) resourcify(param, v) else v end end
has_param?(name)
click to toggle source
# File lib/haveapi/model_adapters/active_record.rb, line 193 def has_param?(name) param = @context.action.output[name] param && @object.respond_to?(param.db_name) end
meta()
click to toggle source
# File lib/haveapi/model_adapters/active_record.rb, line 209 def meta res = @context.action.resource params = if @context.action.name.demodulize == 'Index' \ && !@context.action.resolve \ && res.const_defined?(:Show) res::Show.resolve_path_params(@object) else @context.action.resolve_path_params(@object) end { path_params: params.is_a?(Array) ? params : [params], resolved: true } end
Protected Instance Methods
includes_include?(name)
click to toggle source
Should an association with ‘name` be resolved?
# File lib/haveapi/model_adapters/active_record.rb, line 286 def includes_include?(name) includes = @context.action_instance.meta[:includes] return false unless includes name = name.to_sym if @context.action_instance.flags[:inner_assoc] # This action is called as an association of parent resource. # Meta includes are already parsed and can be accessed directly. else # This action is the one that was called by the user. # Meta includes contains an array of strings as was sent # by the user. The parsed includes must be fetched from # the action itself. includes = @context.action_instance.ar_parse_includes([]) end includes.each do |v| if v.is_a?(::Hash) return true if v.has_key?(name) elsif v == name return true end end false end
includes_pass_on_to(assoc)
click to toggle source
Create an array of includes that is passed to child association.
# File lib/haveapi/model_adapters/active_record.rb, line 315 def includes_pass_on_to(assoc) parsed = if @context.action_instance.flags[:inner_assoc] @context.action_instance.meta[:includes] else @context.action_instance.ar_parse_includes([]) end ret = [] parsed.each do |v| if v.is_a?(::Hash) v.each { |k, v| ret << v if k == assoc } end end ret.flatten(1) end
resourcify(param, val)
click to toggle source
Return representation of an associated resource ‘param` with its instance in `val`.
By default, it returns an unresolved resource, which contains only object id and label. Resource
will be resolved if it is set in meta includes field.
# File lib/haveapi/model_adapters/active_record.rb, line 235 def resourcify(param, val) res_show = param.show_action res_output = res_show.output args = res_show.resolve_path_params(val) if includes_include?(param.name) push_cls = @context.action push_ins = @context.action_instance pass_includes = includes_pass_on_to(param.name) show = res_show.new( push_ins.request, push_ins.version, {}, nil, @context ) show.meta[:includes] = pass_includes # This flag is used to tell the action that it is being used # as a nested association, that it wasn't called directly by the user. show.flags[:inner_assoc] = true show.authorized?(push_ins.current_user) # FIXME: handle false ret = show.safe_output(val) @context.action_instance = push_ins @context.action = push_cls raise "#{res_show} resolve failed" unless ret[0] ret[1][res_show.output.namespace].update({ _meta: ret[1][:_meta].update(resolved: true) }) else { param.value_id => val.send(res_output[param.value_id].db_name), param.value_label => val.send(res_output[param.value_label].db_name), _meta: { path_params: args.is_a?(Array) ? args : [args], resolved: false } } end end