templates/ruby/lib/facebook_ads/edge.rb (124 lines of code) (raw):
# Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
#
# You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
# copy, modify, and distribute this software in source code or binary form for use
# in connection with the web services and APIs provided by Facebook.
#
# As with any software that integrates with the Facebook platform, your use of
# this software is subject to the Facebook Platform Policy
# [http://developers.facebook.com/policy/]. This copyright notice shall be
# included in all copies or substantial portions of the software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
module FacebookAds
module EdgeHasGet
include Enumerable
extend Forwardable
def_delegators :@collection, :length, :count
DEFAULT_PAGE_SIZE = 10
attr_accessor :has_next_page, :next_page_cursor
def [](idx)
# TODO Handle delegate
fetch_next_page until idx < collection.length || !has_next_page?
collection[idx]
end
def all
fetch_next_page until !has_next_page?
collection
end
def each
return enum_for(:each) unless block_given?
idx = 0
while (e = self[idx])
yield e
idx += 1
end
self
end
def reload!
@collection = Array.new
self.has_next_page = true
self.next_page_cursor = nil
end
private
def fetch_next_page
fetch_options = {limit: DEFAULT_PAGE_SIZE}.merge(serialized_options)
fetch_options = fetch_options.merge({after: next_page_cursor}) if next_page_cursor
node.get_edge(name, fetch_options) do |response|
response["data"].each do |data|
field_type = self.class.return_types[:get]
obj = field_type.deserialize(data, node.session)
collection << obj
end
self.next_page_cursor = response.dig('paging', 'cursors', 'after')
self.has_next_page = !(response['data'].length < fetch_options[:limit])
end
end
def collection
@collection ||= Array.new
end
def has_next_page?
self.has_next_page.nil? ? (self.has_next_page = true) : self.has_next_page
end
def loaded?
@loaded
end
end
module EdgeHasPost
def create(params)
if self.class.param_set_for_post
params = self.class.param_set_for_post.to_params(params)
end
node.post_edge(name, graph_params.merge(params)) do |response|
# TODO params check
# TODO Add new object to collection?
field_type = self.class.return_types[:post]
obj = field_type.deserialize(response, node.session)
yield obj if block_given?
obj
end
end
end
module EdgeHasDelete
def destroy(params)
params = @param_set_for_delete.to_params(params) if @param_set_for_delete
node.delete_edge(name, params) do |response|
yield response if block_given?
response
end
end
end
class Edge
attr_reader :name, :node, :options, :should_delegate
def initialize(name, node, should_delegate, options)
@name = name
@node = node
@options = options || {}
@should_delegate = should_delegate
end
def serialized_options
Hash[options.map { |k,v|
v = (k == :fields && v.is_a?(Array)) ?
v.join(',') : v
[k,v]
}]
end
# TODO refactor
# sending this along with params to leverage read-after-write
def graph_params
{fields: options[:fields]}.compact
end
class << self
attr_reader :param_set_for_get, :param_set_for_post, :param_set_for_delete
def get(return_type = 'AdObject')
include EdgeHasGet
yield (@param_set_for_get = ParamSet.new) if block_given?
return_types(:get, return_type)
end
def post(return_type = 'AdObject')
include EdgeHasPost
yield (@param_set_for_post = ParamSet.new) if block_given?
return_types(:post, return_type)
end
def delete(return_type = 'AdObject')
include EdgeHasDelete
yield (@param_set_for_delete = ParamSet.new) if block_given?
return_types(:delete, return_type)
end
# TODO refactor?
def return_types(action = nil, return_type = nil)
if action
if return_type
@return_types ||= {}
@return_types[action] = FieldTypes.for(return_type)
end
@return_types[action]
else
@return_types
end
end
end
end
end