sifiapi 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/Gemfile +8 -0
- data/LICENSE +22 -0
- data/README.md +83 -0
- data/Rakefile +7 -0
- data/examples/complete_workflow.rb +93 -0
- data/lib/faraday/request/convert_file_to_upload_io.rb +37 -0
- data/lib/faraday/request/json_encode.rb +11 -0
- data/lib/faraday/response/parse_json.rb +32 -0
- data/lib/faraday/response/raise_sifi_error.rb +37 -0
- data/lib/sifi_api/ad.rb +2 -0
- data/lib/sifi_api/ad_file_type.rb +2 -0
- data/lib/sifi_api/ad_size.rb +2 -0
- data/lib/sifi_api/bid_type.rb +2 -0
- data/lib/sifi_api/branded_datum.rb +2 -0
- data/lib/sifi_api/browser.rb +2 -0
- data/lib/sifi_api/campaign.rb +2 -0
- data/lib/sifi_api/campaign_stat.rb +2 -0
- data/lib/sifi_api/campaign_type.rb +2 -0
- data/lib/sifi_api/change.rb +2 -0
- data/lib/sifi_api/client.rb +2 -0
- data/lib/sifi_api/company.rb +2 -0
- data/lib/sifi_api/connection.rb +59 -0
- data/lib/sifi_api/context.rb +2 -0
- data/lib/sifi_api/dayparting.rb +2 -0
- data/lib/sifi_api/device.rb +2 -0
- data/lib/sifi_api/dma.rb +2 -0
- data/lib/sifi_api/domain.rb +2 -0
- data/lib/sifi_api/error.rb +15 -0
- data/lib/sifi_api/geo_target.rb +2 -0
- data/lib/sifi_api/ip_range.rb +2 -0
- data/lib/sifi_api/keyword.rb +2 -0
- data/lib/sifi_api/keyword_category.rb +2 -0
- data/lib/sifi_api/operating_system.rb +2 -0
- data/lib/sifi_api/recency.rb +2 -0
- data/lib/sifi_api/recurring_report.rb +2 -0
- data/lib/sifi_api/report.rb +2 -0
- data/lib/sifi_api/report_asset.rb +2 -0
- data/lib/sifi_api/report_type.rb +2 -0
- data/lib/sifi_api/resource.rb +150 -0
- data/lib/sifi_api/user.rb +2 -0
- data/lib/sifi_api/version.rb +9 -0
- data/lib/sifi_api.rb +41 -0
- data/lib/sifiapi.rb +1 -0
- data/sifiapi.gemspec +22 -0
- data/spec/sifi_api/ad_file_type_spec.rb +7 -0
- data/spec/sifi_api/ad_size_spec.rb +7 -0
- data/spec/sifi_api/ad_spec.rb +7 -0
- data/spec/sifi_api/bid_type_spec.rb +7 -0
- data/spec/sifi_api/branded_datum_spec.rb +7 -0
- data/spec/sifi_api/browser_spec.rb +7 -0
- data/spec/sifi_api/campaign_spec.rb +7 -0
- data/spec/sifi_api/campaign_stat_spec.rb +7 -0
- data/spec/sifi_api/campaign_type_spec.rb +7 -0
- data/spec/sifi_api/change_spec.rb +7 -0
- data/spec/sifi_api/client_spec.rb +7 -0
- data/spec/sifi_api/company_spec.rb +7 -0
- data/spec/sifi_api/context_spec.rb +7 -0
- data/spec/sifi_api/dayparting_spec.rb +7 -0
- data/spec/sifi_api/device_spec.rb +7 -0
- data/spec/sifi_api/dma_spec.rb +7 -0
- data/spec/sifi_api/domain_spec.rb +7 -0
- data/spec/sifi_api/geo_target_spec.rb +7 -0
- data/spec/sifi_api/ip_range_spec.rb +8 -0
- data/spec/sifi_api/keyword_category_spec.rb +7 -0
- data/spec/sifi_api/keyword_spec.rb +8 -0
- data/spec/sifi_api/operating_system_spec.rb +8 -0
- data/spec/sifi_api/recency_spec.rb +7 -0
- data/spec/sifi_api/recurring_report_spec.rb +8 -0
- data/spec/sifi_api/report_asset_spec.rb +8 -0
- data/spec/sifi_api/report_spec.rb +8 -0
- data/spec/sifi_api/report_type_spec.rb +8 -0
- data/spec/sifi_api/user_spec.rb +7 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/resource_shared_example.rb +97 -0
- metadata +200 -0
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
class SifiApi::Resource
|
4
|
+
include ActiveSupport::Rescuable
|
5
|
+
|
6
|
+
def initialize(json, connection, user_key)
|
7
|
+
@json = json
|
8
|
+
@connection = connection
|
9
|
+
@user_key = user_key
|
10
|
+
@cache = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def raw_json
|
14
|
+
@json
|
15
|
+
end
|
16
|
+
|
17
|
+
def update(params={})
|
18
|
+
params = { resource_name.singularize => params }
|
19
|
+
execute_with_rescue do
|
20
|
+
response = @connection.put(@user_key, self.resource, params)
|
21
|
+
if response && response.body
|
22
|
+
@json = response.body[resource_name].first
|
23
|
+
end
|
24
|
+
end
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def create(resource, params={})
|
29
|
+
params = { resource => params }
|
30
|
+
execute_with_rescue do
|
31
|
+
resource_name = resource.to_s.pluralize
|
32
|
+
response = @connection.post(@user_key, self.resource + "/#{resource_name}", params)
|
33
|
+
if response && response.body
|
34
|
+
record = response.body[resource_name].first
|
35
|
+
SifiApi.const_get(resource.to_s.classify).new(record, @connection, @user_key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def find(resource, id)
|
41
|
+
execute_with_rescue do
|
42
|
+
resource_name = resource.to_s.pluralize
|
43
|
+
record = @connection.get(@user_key, self.resource + "/#{resource_name}").body[resource_name].select{|x| x["id"].to_i == id.to_i }.first
|
44
|
+
record ? SifiApi.const_get(resource.to_s.classify).new(record, @connection, @user_key) : []
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete
|
49
|
+
execute_with_rescue do
|
50
|
+
@connection.delete(@user_key, self.resource)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def reload(params={})
|
55
|
+
execute_with_rescue do
|
56
|
+
response = @connection.get(@user_key, self.resource, params)
|
57
|
+
if response && response.body
|
58
|
+
@json = response.body[resource_name].first
|
59
|
+
@cache = {}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.get_via_uri(connection, user_key, uri='', params={})
|
66
|
+
a = []
|
67
|
+
response = connection.get(user_key, uri, params)
|
68
|
+
if response && response.body
|
69
|
+
response.body[resource_name].each do |record|
|
70
|
+
resource = self.new(record, connection, user_key)
|
71
|
+
a << resource
|
72
|
+
end
|
73
|
+
end
|
74
|
+
a
|
75
|
+
end
|
76
|
+
|
77
|
+
def method_missing(sym, *args, &block)
|
78
|
+
if @json.respond_to?(sym)
|
79
|
+
@json.send(sym, *args, &block)
|
80
|
+
elsif val = (@json["resources"] || []).select { |r| r[sym.to_s] }.first
|
81
|
+
return get_resource(sym.to_s, val[sym.to_s], *args)
|
82
|
+
elsif @json.has_key?(sym.to_s)
|
83
|
+
return @json[sym.to_s]
|
84
|
+
elsif val = (@json["actions"] || []).select { |a| a[sym.to_s] }.first
|
85
|
+
return do_action(val[sym.to_s])
|
86
|
+
else
|
87
|
+
super(sym, *args, &block)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def do_action(action)
|
93
|
+
execute_with_rescue do
|
94
|
+
response = @connection.send(action["method"].downcase, @user_key, action["href"])
|
95
|
+
if response && response.status == 200
|
96
|
+
if response[:content_type] == "application/json"
|
97
|
+
@json = response.body[resource_name].first
|
98
|
+
elsif ["text/csv", "application/zip"].include?(response[:content_type])
|
99
|
+
filename = response.headers[:content_disposition].match(/filename="(.+)"/)[1]
|
100
|
+
file = Tempfile.new(filename)
|
101
|
+
file.write(response.body)
|
102
|
+
file.rewind
|
103
|
+
return file
|
104
|
+
end
|
105
|
+
end
|
106
|
+
response
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def resource_name
|
111
|
+
self.class.name.split("::").last.underscore.pluralize.downcase
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.resource_name
|
115
|
+
self.name.split("::").last.underscore.pluralize.downcase
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_s
|
119
|
+
@json.inspect
|
120
|
+
end
|
121
|
+
|
122
|
+
protected
|
123
|
+
|
124
|
+
def get_resource(name, uri, params={})
|
125
|
+
execute_with_rescue do
|
126
|
+
force = params.delete(:ignore_cache)
|
127
|
+
if @cache[name] && @cache[name][:params] == params && force != true
|
128
|
+
@cache[name][:records]
|
129
|
+
else
|
130
|
+
@cache[name] = { :params => params }
|
131
|
+
if params == {} && @json[name]
|
132
|
+
records = []
|
133
|
+
@json[name].each do |record|
|
134
|
+
records << SifiApi.const_get(name.classify).new(record, @connection, @user_key)
|
135
|
+
end
|
136
|
+
else
|
137
|
+
records = SifiApi.const_get(name.classify).get_via_uri(@connection, @user_key, uri, params)
|
138
|
+
end
|
139
|
+
@cache[name][:records] = records
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def execute_with_rescue(&block)
|
145
|
+
yield
|
146
|
+
rescue Exception => exception
|
147
|
+
rescue_with_handler(exception) || raise
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
data/lib/sifi_api.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require "faraday"
|
4
|
+
require "multi_json"
|
5
|
+
require "active_support/inflector"
|
6
|
+
require "active_support/rescuable"
|
7
|
+
require "sifi_api/error"
|
8
|
+
|
9
|
+
module SifiApi
|
10
|
+
autoload :Ad, "sifi_api/ad"
|
11
|
+
autoload :AdFileType, "sifi_api/ad_file_type"
|
12
|
+
autoload :AdSize, "sifi_api/ad_size"
|
13
|
+
autoload :BidType, "sifi_api/bid_type"
|
14
|
+
autoload :BrandedDatum, "sifi_api/branded_datum"
|
15
|
+
autoload :Browser, "sifi_api/browser"
|
16
|
+
autoload :Campaign, "sifi_api/campaign"
|
17
|
+
autoload :CampaignStat, "sifi_api/campaign_stat"
|
18
|
+
autoload :CampaignType, "sifi_api/campaign_type"
|
19
|
+
autoload :Change, "sifi_api/change"
|
20
|
+
autoload :Client, "sifi_api/client"
|
21
|
+
autoload :Company, "sifi_api/company"
|
22
|
+
autoload :Connection, "sifi_api/connection"
|
23
|
+
autoload :Context, "sifi_api/context"
|
24
|
+
autoload :Dayparting, "sifi_api/dayparting"
|
25
|
+
autoload :Device, "sifi_api/device"
|
26
|
+
autoload :Dma, "sifi_api/dma"
|
27
|
+
autoload :Domain, "sifi_api/domain"
|
28
|
+
autoload :GeoTarget, "sifi_api/geo_target"
|
29
|
+
autoload :IpRange, "sifi_api/ip_range"
|
30
|
+
autoload :Keyword, "sifi_api/keyword"
|
31
|
+
autoload :KeywordCategory, "sifi_api/keyword_category"
|
32
|
+
autoload :OperatingSystem, "sifi_api/operating_system"
|
33
|
+
autoload :Recency, "sifi_api/recency"
|
34
|
+
autoload :RecurringReport, "sifi_api/recurring_report"
|
35
|
+
autoload :Report, "sifi_api/report"
|
36
|
+
autoload :ReportAsset, "sifi_api/report_asset"
|
37
|
+
autoload :ReportType, "sifi_api/report_type"
|
38
|
+
autoload :Resource, "sifi_api/resource"
|
39
|
+
autoload :User, "sifi_api/user"
|
40
|
+
autoload :VERSION, "sifi_api/version"
|
41
|
+
end
|
data/lib/sifiapi.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sifi_api'
|
data/sifiapi.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/sifi_api/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Brandon Aaron"]
|
6
|
+
gem.email = ["brandon@simpli.fi"]
|
7
|
+
gem.description = ""
|
8
|
+
gem.summary = "Ruby wrapper for the Simpli.fi API"
|
9
|
+
gem.homepage = "http://simpli.fi"
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "sifiapi"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = SifiApi::VERSION::STRING
|
17
|
+
|
18
|
+
gem.add_dependency 'faraday', '~> 0.7.6'
|
19
|
+
gem.add_dependency 'multi_json', '~> 1.0.3'
|
20
|
+
gem.add_dependency 'activesupport', '~> 3.0.10'
|
21
|
+
gem.add_dependency 'i18n', '~> 0.5.0'
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
$:.unshift File.expand_path('..', __FILE__)
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'sifi_api'
|
4
|
+
|
5
|
+
require 'support/resource_shared_example'
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
|
9
|
+
def connection
|
10
|
+
SifiApi::Connection.new("app_key")
|
11
|
+
end
|
12
|
+
|
13
|
+
def fake_resource
|
14
|
+
{
|
15
|
+
"resource" => "https://app.simpli.fi/api/fake_resources/1",
|
16
|
+
"id" => 1,
|
17
|
+
"name" => "Fake Resource 1",
|
18
|
+
"actions" => [
|
19
|
+
{ "do_something" => { "method" => "GET", "href" => "https://app.simpli.fi/api/fake_resources/1/do_something" } }
|
20
|
+
],
|
21
|
+
"resources" => [
|
22
|
+
{ "fake_resources" => "https://app.simpli.fi/api/fake_resources/1/fake_resources" }
|
23
|
+
]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class SifiApi::FakeResource < SifiApi::Resource
|
4
|
+
end
|
5
|
+
|
6
|
+
shared_examples_for 'SifiApi::Resource' do |resource|
|
7
|
+
before(:all) do
|
8
|
+
@connection = connection
|
9
|
+
@user_key = "user_key"
|
10
|
+
@resource = resource.new(fake_resource, @connection, @user_key)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should expose the raw json" do
|
14
|
+
@resource.raw_json.should == fake_resource
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should expose properties of the json as methods of the class" do
|
18
|
+
@resource.name.should == fake_resource["name"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should support hash methods run directly against the raw json" do
|
22
|
+
@resource.keys.should == fake_resource.keys
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should call action if method is an action" do
|
26
|
+
action = fake_resource["actions"].first["do_something"]
|
27
|
+
begin
|
28
|
+
@connection.should_receive(action["method"].downcase.to_sym).with(@user_key, action["href"])
|
29
|
+
rescue SifiApi::NotFound => e
|
30
|
+
end
|
31
|
+
@resource.do_something
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should load the resource if the method is a resource" do
|
35
|
+
resource = fake_resource["resources"].first
|
36
|
+
begin
|
37
|
+
@connection.should_receive(:get).with(@user_key, resource["fake_resources"], {})
|
38
|
+
rescue SifiApi::NotFound => e
|
39
|
+
end
|
40
|
+
@resource.fake_resources
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should pass along params passed to a resource method call" do
|
44
|
+
resource = fake_resource["resources"].first
|
45
|
+
params = { :include => "testing" }
|
46
|
+
begin
|
47
|
+
@connection.should_receive(:get).with(@user_key, resource["fake_resources"], params)
|
48
|
+
rescue SifiApi::NotFound => e
|
49
|
+
end
|
50
|
+
@resource.fake_resources(params)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not pass along the 'ignore_cache' param to a resource method call" do
|
54
|
+
resource = fake_resource["resources"].first
|
55
|
+
params = { :include => "testing" }
|
56
|
+
begin
|
57
|
+
@connection.should_receive(:get).with(@user_key, resource["fake_resources"], params)
|
58
|
+
rescue SifiApi::NotFound => e
|
59
|
+
end
|
60
|
+
@resource.fake_resources(params.merge!(:ignore_cache => true))
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should provide a method to update the resource" do
|
64
|
+
params = { :name => "Plain Resource" }
|
65
|
+
begin
|
66
|
+
@connection.should_receive(:put).with(@user_key, fake_resource["resource"], { @resource.resource_name.singularize => params})
|
67
|
+
rescue SifiApi::NotFound => e
|
68
|
+
end
|
69
|
+
@resource.update(params)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should provide a method to create a nested resource" do
|
73
|
+
params = { :name => "Nested Resource" }
|
74
|
+
begin
|
75
|
+
@connection.should_receive(:post).with(@user_key, "#{fake_resource["resource"]}/fake_resources", { "fake_resource" => params})
|
76
|
+
rescue SifiApi::NotFound => e
|
77
|
+
end
|
78
|
+
@resource.create("fake_resource", params)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should provide a method to delete a resource" do
|
82
|
+
begin
|
83
|
+
@connection.should_receive(:delete).with(@user_key, fake_resource["resource"])
|
84
|
+
rescue SifiApi::NotFound => e
|
85
|
+
end
|
86
|
+
@resource.delete
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should provide a method to reload a resource" do
|
90
|
+
begin
|
91
|
+
@connection.should_receive(:get).with(@user_key, fake_resource["resource"], {})
|
92
|
+
rescue SifiApi::NotFound => e
|
93
|
+
end
|
94
|
+
@resource.reload
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|