module HaveAPI::Fs::Components class ResourceDir < Directory component :resource_dir attr_reader :resource def initialize(resource) super() @resource = resource end def setup super @index = use(:actions, :index) @data = nil end def contents load_contents if @index && (!@data || @refresh) ret = super + %w(actions) + subresources.map(&:to_s) ret.concat(@data.map { |v| v.id.to_s }) if @data ret << 'create.yml' if find(:actions).find(:create) if @index ret.concat(@index.action.input_params.keys.map { |v| "by-#{v}" }) end ret end def refresh @refresh = true end def delete(id) return unless @data i = @data.index { |v| v.id == id } @data.delete_at(i) if i end def title "Resource #{@resource._name.to_s.capitalize}" end protected def new_child(name) if child = super child elsif name == :actions [ResourceActionDir, @resource] elsif subresources.include?(name) [ResourceDir, @resource.send(name)] elsif /^\d+$/ =~ name id = name.to_s.to_i if @data r = @data.detect { |v| v.id == id } [ResourceInstanceDir, r] if r else # The directory contents have not been loaded yet. We don't necessarily # need to load it all, a single query should be sufficient. begin obj = @resource.show(id, meta: meta_params) [ResourceInstanceDir, obj] rescue HaveAPI::Client::ActionFailed # Not found end end elsif name == :'create.yml' && create_dir = use(:actions, :create) [InstanceCreate, create_dir] elsif @index && name.to_s.start_with?('by-') by_param = name.to_s[3..-1].to_sym return nil unless @index.action.input_params.has_key?(by_param) [IndexFilter, self, by_param] else nil end end def subresources return @subresources if @subresources @subresources = [] @resource.resources.each do |r_name, r| r.actions.each do |a_name, a| if a.url.index(":#{@resource._name}_id").nil? @subresources << r_name break end end end @subresources end def meta_params { includes: @resource.actions[:show].params.select do |n, p| p[:type] == 'Resource' end.map do |n, p| n end.join(',') } end def load_contents if context.opts[:index_limit] && file = @index.find(:input).find(:limit) limit = context.opts[:index_limit].to_i v = file.value param = @index.action.input_params[:limit] if (!v && !param[:default]) \ || (v && v > limit) \ || (param[:default] && param[:default] > limit) file.write_safe(limit) end end @index.exec(meta: meta_params) new_data = @index.output.data if @data current_map = id_map(@data) res = [] new_data.each do |v| if current_map.has_key?(v.id) # TODO: if old object is not modified, use the new object instead res << current_map[v.id] else res << v end end @data = res else @data = new_data end changed @refresh = false end def id_map(list) ret = {} list.each { |v| ret[v.id] = v } ret end end end