module Sheety::Children::ClassMethods
Public Instance Methods
atom_children(symbol, options)
click to toggle source
Defines a child relationship with the given name symbol (required): the name of the child options (required): a hash of options
- klass (required): the class to use for the child instances - link (required): the url to fetch the children from -
# File lib/sheety/children.rb, line 36 def atom_children(symbol, options) if options.blank? raise ArgumentError.new("blank options #{options} are not valid options for atom_children") end if options[:klass].blank? || options[:klass].class != Class raise ArgumentError.new("#{options} must have a :klass that is a Class, not a #{options[:klass].class}") end if options[:link].blank? raise ArgumentError.new("#{options} must have a non-blank :link") end unless method_defined?(:link) raise TypeError.new("#{self} must respond to :link to use atom_children") end if options[:merge_links] && method_defined?(:add_links) == false raise TypeError.new("#{self} must respond to :add_links in atom_children with merge_links=true") end plural = symbol.to_s singular = plural.singularize inst_var_sym = :"@#{symbol}" get_method = :"#{plural}" new_method = :"new_#{singular}" enum_method = :"_enumerate_#{plural}_by_method" where_method = :"#{plural}_where" except_method = :"#{plural}_except" except_any_method = :"#{plural}_except_any" find_first_method = :"find_#{singular}" # Defines a method that instantiates a new child define_method(new_method) do |entry=nil| options[:klass].new(self, entry) end # Defines a method that fetches children from Google define_method(get_method) do |force_refetch=false| if instance_variable_get(inst_var_sym).nil? || force_refetch list = Sheety::Api.inst.get_feed(link(options[:link])) # sort of a cyclic dependency, suboptimal if list.nil? raise Sheety::SheetyFetchError.new, "Fetching #{plural} failed!" end # TODO: Create a ListFeed Object so the links we get here don't need to be worried about collisions on link ids add_links(list['link']) if !list['link'].blank? && options[:merge_links] list = (list['entry'] || []).map do |entry| method(new_method).call(entry) end instance_variable_set(inst_var_sym, list) end return instance_variable_get(inst_var_sym) end # Defines a helper-method that will iterate over children checking that each item passes all constraints given define_method(enum_method) do |constraints, enumeration_method| children = method(get_method).() if children.nil? return [] end return children.send(enumeration_method) do |item| constraints.all? do |constraint| _passes_constraint(_get_i_val(item, constraint[0], options[:accessor]), constraint[1]) end end end # Defines a method that selects the children who adhere to all constraints given define_method(where_method) do |constraints| return method(enum_method).call(constraints, :find_all) end # Defines a method that selects the first child that passes all constraints given define_method(find_first_method) do |constraints| return method(enum_method).call(constraints, :detect) end # Defines a method that selects those children who fail to meet all constraint given define_method(except_method) do |constraints| return method(enum_method).call(constraints, :reject) end # Defines a method that selects those children who fail to meet at least one constraint given define_method(except_any_method) do |constraints| children = method(get_method).() if children.nil? return [] end return children.reject do |item| constraints.any? do |constraint| _passes_constraint(_get_i_val(item, constraint[0], options[:accessor]), constraint[1]) end end end end