populr 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +43 -0
- data/LICENSE.md +21 -0
- data/README.rdoc +19 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/lib/asset.rb +24 -0
- data/lib/document_asset.rb +10 -0
- data/lib/domain.rb +7 -0
- data/lib/image_asset.rb +12 -0
- data/lib/pop.rb +93 -0
- data/lib/populr.rb +70 -0
- data/lib/restful_model.rb +64 -0
- data/lib/restful_model_collection.rb +85 -0
- data/lib/template.rb +10 -0
- data/lib/tracer.rb +58 -0
- data/spec/pop_spec.rb +157 -0
- data/spec/populr_spec.rb +89 -0
- data/spec/restful_model_collection_spec.rb +119 -0
- data/spec/restful_model_spec.rb +20 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/tracer_spec.rb +107 -0
- metadata +153 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
gem "rest-client", ">= 1.6"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "shoulda", ">= 0"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "bundler", "~> 1.3.5"
|
12
|
+
gem "jeweler", "~> 1.8.4"
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (3.2.8)
|
5
|
+
i18n (~> 0.6)
|
6
|
+
multi_json (~> 1.0)
|
7
|
+
bourne (1.4.0)
|
8
|
+
mocha (~> 0.13.2)
|
9
|
+
git (1.2.5)
|
10
|
+
i18n (0.6.1)
|
11
|
+
jeweler (1.8.4)
|
12
|
+
bundler (~> 1.0)
|
13
|
+
git (>= 1.2.5)
|
14
|
+
rake
|
15
|
+
rdoc
|
16
|
+
json (1.7.5)
|
17
|
+
metaclass (0.0.1)
|
18
|
+
mime-types (1.19)
|
19
|
+
mocha (0.13.3)
|
20
|
+
metaclass (~> 0.0.1)
|
21
|
+
multi_json (1.3.6)
|
22
|
+
rake (10.0.3)
|
23
|
+
rdoc (3.12)
|
24
|
+
json (~> 1.4)
|
25
|
+
rest-client (1.6.7)
|
26
|
+
mime-types (>= 1.16)
|
27
|
+
shoulda (3.4.0)
|
28
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
29
|
+
shoulda-matchers (~> 1.0, >= 1.4.1)
|
30
|
+
shoulda-context (1.1.1)
|
31
|
+
shoulda-matchers (1.5.6)
|
32
|
+
activesupport (>= 3.0.0)
|
33
|
+
bourne (~> 1.3)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
bundler (~> 1.3.5)
|
40
|
+
jeweler (~> 1.8.4)
|
41
|
+
rdoc (~> 3.12)
|
42
|
+
rest-client (>= 1.6)
|
43
|
+
shoulda
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2011- Project 10k, Inc. (https://populr.me)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= Populr.me Ruby Gem
|
2
|
+
|
3
|
+
A rubygem for interacting with the Populr.me API from Ruby apps.
|
4
|
+
|
5
|
+
== Contributing to the Populr.me Ruby Gem
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
+
* Fork the project.
|
10
|
+
* Start a feature/bugfix branch.
|
11
|
+
* Commit and push until you are happy with your contribution.
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2013 Project 10K. See LICENSE.md for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "populr"
|
18
|
+
gem.homepage = "http://github.com/bengotow/populr"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Gem for interacting with the Populr.me API}
|
21
|
+
gem.description = %Q{Gem for interacting with the Populr.me API}
|
22
|
+
gem.email = "ben@populr.me"
|
23
|
+
gem.authors = ["Ben Gotow"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
require 'rdoc/task'
|
37
|
+
Rake::RDocTask.new do |rdoc|
|
38
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
39
|
+
|
40
|
+
rdoc.rdoc_dir = 'rdoc'
|
41
|
+
rdoc.title = "populr #{version}"
|
42
|
+
rdoc.rdoc_files.include('README*')
|
43
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
44
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/lib/asset.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'restful_model'
|
2
|
+
|
3
|
+
class Asset < RestfulModel
|
4
|
+
|
5
|
+
attr_accessor :description
|
6
|
+
attr_accessor :title
|
7
|
+
|
8
|
+
# as an alternative to calling Asset.new, you can call populr.images.build
|
9
|
+
def initialize(api, file, title = nil, description = nil)
|
10
|
+
super(api)
|
11
|
+
|
12
|
+
@file = file
|
13
|
+
self.title = title
|
14
|
+
self.description = description
|
15
|
+
self.link = link
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(options = {})
|
19
|
+
hash = super(options)
|
20
|
+
hash[:file] = @file if options[:api_representation] && @file
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/domain.rb
ADDED
data/lib/image_asset.rb
ADDED
data/lib/pop.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'restful_model'
|
2
|
+
require 'tracer'
|
3
|
+
|
4
|
+
class Pop < RestfulModel
|
5
|
+
|
6
|
+
class TemplateRequired < StandardError; end
|
7
|
+
|
8
|
+
attr_accessor :template_id
|
9
|
+
attr_accessor :name
|
10
|
+
attr_accessor :title
|
11
|
+
attr_accessor :slug
|
12
|
+
attr_accessor :label_names
|
13
|
+
attr_accessor :tracers
|
14
|
+
attr_accessor :published_pop_url
|
15
|
+
attr_accessor :unpopulated_api_regions
|
16
|
+
attr_accessor :unpopulated_api_tags
|
17
|
+
attr_accessor :domain
|
18
|
+
attr_accessor :password
|
19
|
+
|
20
|
+
attr_reader :newly_populated_regions
|
21
|
+
attr_reader :newly_populated_tags
|
22
|
+
|
23
|
+
def initialize(api_or_template, template = nil)
|
24
|
+
template = template || api_or_template
|
25
|
+
|
26
|
+
if template.is_a?(Template)
|
27
|
+
self.template_id = template._id
|
28
|
+
@_api = template._api
|
29
|
+
else
|
30
|
+
@_api = api_or_template
|
31
|
+
end
|
32
|
+
|
33
|
+
@newly_populated_regions = {}
|
34
|
+
@newly_populated_tags = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def inflate(json)
|
38
|
+
super(json)
|
39
|
+
|
40
|
+
collection = RestfulModelCollection.new(Tracer, @_api, self)
|
41
|
+
collection.inflate_collection(self.tracers) if self.tracers
|
42
|
+
self.tracers = collection
|
43
|
+
|
44
|
+
@newly_populated_regions = {}
|
45
|
+
@newly_populated_tags = {}
|
46
|
+
end
|
47
|
+
|
48
|
+
def as_json(options = {})
|
49
|
+
raise TemplateRequired.new unless template_id
|
50
|
+
|
51
|
+
if options[:api_representation]
|
52
|
+
hash = {}
|
53
|
+
hash[:pop] = super(options)
|
54
|
+
hash[:populate_tags] = @newly_populated_tags
|
55
|
+
hash[:populate_regions] = @newly_populated_regions
|
56
|
+
hash
|
57
|
+
else
|
58
|
+
super(options)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def publish!
|
64
|
+
update('POST', 'publish')
|
65
|
+
end
|
66
|
+
|
67
|
+
def unpublish!
|
68
|
+
update('POST', 'unpublish')
|
69
|
+
end
|
70
|
+
|
71
|
+
def has_unpopulated_region(region_identifier)
|
72
|
+
self.unpopulated_api_regions.include?(region_identifier)
|
73
|
+
end
|
74
|
+
|
75
|
+
def populate_region(region_identifier, assets)
|
76
|
+
assets = [assets] unless assets.is_a?(Array)
|
77
|
+
|
78
|
+
@newly_populated_regions[region_identifier] ||= []
|
79
|
+
@newly_populated_regions[region_identifier].concat(assets.map {|a| a._id })
|
80
|
+
self.unpopulated_api_regions.delete(region_identifier)
|
81
|
+
end
|
82
|
+
|
83
|
+
def has_unpopulated_tag(tag_identifier)
|
84
|
+
self.unpopulated_api_tags.include?(tag_identifier)
|
85
|
+
end
|
86
|
+
|
87
|
+
def populate_tag(tag_identifier, tag_contents)
|
88
|
+
@newly_populated_tags[tag_identifier] = tag_contents
|
89
|
+
self.unpopulated_api_tags.delete(tag_identifier)
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
data/lib/populr.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'restful_model_collection'
|
3
|
+
require 'template'
|
4
|
+
require 'document_asset'
|
5
|
+
require 'image_asset'
|
6
|
+
require 'json'
|
7
|
+
require 'pop'
|
8
|
+
require 'domain'
|
9
|
+
|
10
|
+
|
11
|
+
class Populr
|
12
|
+
|
13
|
+
class AccessDenied < StandardError; end
|
14
|
+
class ResourceNotFound < StandardError; end
|
15
|
+
class UnexpectedResponse < StandardError; end
|
16
|
+
|
17
|
+
attr_accessor :api_server
|
18
|
+
attr_reader :api_key
|
19
|
+
|
20
|
+
|
21
|
+
def self.interpret_response(result, options = {})
|
22
|
+
# Handle HTTP errors and RestClient errors
|
23
|
+
raise ResourceNotFound.new if result.code.to_i == 404
|
24
|
+
raise AccessDenied.new if result.code.to_i == 403
|
25
|
+
raise UnexpectedResponse.new(result.msg) if result.is_a?(Net::HTTPClientError)
|
26
|
+
|
27
|
+
# Hande content expectation errors
|
28
|
+
raise UnexpectedResponse.new if options[:expected_class] && result.body.empty?
|
29
|
+
json = JSON.parse(result.body)
|
30
|
+
raise UnexpectedResponse.new if options[:expected_class] && !json.is_a?(options[:expected_class])
|
31
|
+
json
|
32
|
+
|
33
|
+
rescue JSON::ParserError => e
|
34
|
+
# Handle parsing errors
|
35
|
+
raise UnexpectedResponse.new(e.message)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
def initialize(api_key)
|
41
|
+
@api_server = "api.lvh.me:3000"
|
42
|
+
@api_key = api_key
|
43
|
+
end
|
44
|
+
|
45
|
+
def templates
|
46
|
+
RestfulModelCollection.new(Template, self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def pops
|
50
|
+
RestfulModelCollection.new(Pop, self)
|
51
|
+
end
|
52
|
+
|
53
|
+
def domains
|
54
|
+
RestfulModelCollection.new(Domain, self)
|
55
|
+
end
|
56
|
+
|
57
|
+
def documents
|
58
|
+
RestfulModelCollection.new(DocumentAsset, self)
|
59
|
+
end
|
60
|
+
|
61
|
+
def images
|
62
|
+
RestfulModelCollection.new(ImageAsset, self)
|
63
|
+
end
|
64
|
+
|
65
|
+
def url_for_path(path)
|
66
|
+
"http://#{@api_key}:@#{api_server}#{path}"
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class RestfulModel
|
2
|
+
|
3
|
+
attr_accessor :_id
|
4
|
+
attr_accessor :created_at
|
5
|
+
|
6
|
+
def self.collection_name
|
7
|
+
"#{self.to_s.downcase}s"
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def initialize(api)
|
12
|
+
@_api = api
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(comparison_object)
|
16
|
+
comparison_object.equal?(self) || (comparison_object.instance_of?(self.class) && comparison_object._id == _id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def inflate(json)
|
20
|
+
setters = methods.grep(/^\w+=$/)
|
21
|
+
setters.each do |setter|
|
22
|
+
property_name = setter.to_s[0..setter.to_s.index('=')-1]
|
23
|
+
self.send(setter, json[property_name]) if json.has_key?(property_name)
|
24
|
+
end
|
25
|
+
self.created_at = Time.new(self.created_at) if self.created_at
|
26
|
+
end
|
27
|
+
|
28
|
+
def save!
|
29
|
+
if _id
|
30
|
+
update('PUT', '', self.as_json(:api_representation => true))
|
31
|
+
else
|
32
|
+
update('POST', '', self.as_json(:api_representation => true))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def as_json(options = {})
|
37
|
+
hash = {}
|
38
|
+
setters = methods.grep(/^\w+=$/)
|
39
|
+
setters.each do |setter|
|
40
|
+
getter = setter.to_s[0..setter.to_s.index('=')-1]
|
41
|
+
hash[getter] = self.send(getter)
|
42
|
+
end
|
43
|
+
hash
|
44
|
+
end
|
45
|
+
|
46
|
+
def update(http_method, action, data = {})
|
47
|
+
http_method = http_method.downcase
|
48
|
+
action_url = @_api.url_for_path(self.path(action))
|
49
|
+
|
50
|
+
RestClient.send(http_method, action_url, data){ |response,request,result|
|
51
|
+
json = Populr.interpret_response(result, {:expected_class => Object})
|
52
|
+
inflate(json)
|
53
|
+
}
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def path(action = "")
|
58
|
+
action = "/#{action}" unless action.empty?
|
59
|
+
prefix = @_parent ? @_parent.path : ''
|
60
|
+
"#{prefix}/#{self.class.collection_name}/#{_id}#{action}"
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'restful_model'
|
2
|
+
|
3
|
+
class RestfulModelCollection
|
4
|
+
|
5
|
+
def initialize(model_class, api, parent = nil)
|
6
|
+
@model_class = model_class
|
7
|
+
@_parent = parent
|
8
|
+
@_collection = nil
|
9
|
+
@_api = api
|
10
|
+
end
|
11
|
+
|
12
|
+
def all
|
13
|
+
return @_collection if @_collection
|
14
|
+
get_restful_model_collection
|
15
|
+
end
|
16
|
+
|
17
|
+
def first
|
18
|
+
all.first
|
19
|
+
end
|
20
|
+
|
21
|
+
def find(id)
|
22
|
+
get_restful_model(id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def build(*args)
|
26
|
+
@model_class.new(@_api, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def as_json(options = {})
|
30
|
+
objects = []
|
31
|
+
for model in self.all
|
32
|
+
objects.push(model.as_json(options))
|
33
|
+
end
|
34
|
+
objects
|
35
|
+
end
|
36
|
+
|
37
|
+
def inflate_collection(items = [])
|
38
|
+
@_collection = []
|
39
|
+
items.each do |json|
|
40
|
+
if @model_class < RestfulModel
|
41
|
+
model = @model_class.new(self)
|
42
|
+
model.instance_variable_set(:@_parent, @_parent)
|
43
|
+
model.inflate(json)
|
44
|
+
else
|
45
|
+
model = @model_class.new(json)
|
46
|
+
end
|
47
|
+
@_collection.push(model)
|
48
|
+
end
|
49
|
+
@_collection
|
50
|
+
end
|
51
|
+
|
52
|
+
def path(id = "")
|
53
|
+
prefix = @_parent ? @_parent.path : ''
|
54
|
+
"#{prefix}/#{@model_class.collection_name}/#{id}"
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def get_restful_model(id)
|
60
|
+
model = nil
|
61
|
+
url = @_api.url_for_path(self.path(id))
|
62
|
+
|
63
|
+
RestClient.get(url){ |response,request,result|
|
64
|
+
json = Populr.interpret_response(result, {:expected_class => Object})
|
65
|
+
if @model_class < RestfulModel
|
66
|
+
model = @model_class.new(self)
|
67
|
+
model.inflate(json)
|
68
|
+
else
|
69
|
+
model = @model_class.new(json)
|
70
|
+
end
|
71
|
+
}
|
72
|
+
model
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_restful_model_collection
|
76
|
+
url = @_api.url_for_path(self.path)
|
77
|
+
|
78
|
+
RestClient.get(url){ |response,request,result|
|
79
|
+
items = Populr.interpret_response(result, {:expected_class => Array})
|
80
|
+
inflate_collection(items)
|
81
|
+
}
|
82
|
+
@_collection
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/lib/template.rb
ADDED
data/lib/tracer.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'restful_model'
|
2
|
+
|
3
|
+
class Tracer < RestfulModel
|
4
|
+
|
5
|
+
class CodeCannotBeModified < StandardError; end
|
6
|
+
|
7
|
+
attr_accessor :name
|
8
|
+
attr_accessor :code
|
9
|
+
attr_accessor :notify_on_open
|
10
|
+
attr_accessor :notify_webhook
|
11
|
+
attr_accessor :analytics
|
12
|
+
|
13
|
+
def views
|
14
|
+
return analytics["views"].to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def clicks
|
18
|
+
return analytics["clicks"].to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def clicks_for_region(region_id)
|
22
|
+
return 0 unless analytics["assets"] && analytics["assets"][region_id]
|
23
|
+
|
24
|
+
clicks = 0
|
25
|
+
for key, asset in analytics["assets"][region_id]
|
26
|
+
clicks += asset["clicks"].to_i
|
27
|
+
end
|
28
|
+
clicks
|
29
|
+
end
|
30
|
+
|
31
|
+
def clicks_for_link(link)
|
32
|
+
return 0 unless analytics["links"] && analytics["links"][link]
|
33
|
+
return analytics["links"][link]["clicks"].to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
def clicks_for_asset(asset_or_id)
|
37
|
+
return 0 unless analytics["assets"]
|
38
|
+
asset_id = asset_or_id.is_a?(Asset) ? asset_or_id._id : asset_or_id
|
39
|
+
|
40
|
+
for region, assets in analytics["assets"]
|
41
|
+
for key, asset in assets
|
42
|
+
return asset["clicks"].to_i if key == asset_id
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def code=(c)
|
49
|
+
raise CodeCannotBeModified.new if self.code && c != self.code
|
50
|
+
@code = c
|
51
|
+
end
|
52
|
+
|
53
|
+
def enable_webhook(url)
|
54
|
+
self.notify_on_open = true
|
55
|
+
self.notify_webhook = url
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/spec/pop_spec.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
::ENV['RACK_ENV'] = 'test'
|
2
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe 'Pop' do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
before (:each) do
|
8
|
+
@api = Populr.new('key')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#inflate" do
|
12
|
+
it "should inflate tracers into embedded tracer objects" do
|
13
|
+
pop = Pop.new(@api)
|
14
|
+
pop.inflate(JSON.parse("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}"))
|
15
|
+
pop.tracers.first.is_a?(Tracer).should == true
|
16
|
+
pop.tracers.first.name.should == 'Facebook'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should set the tracer collection's _parent so the tracer's path returns the full nested path" do
|
20
|
+
pop = Pop.new(@api)
|
21
|
+
pop.inflate(JSON.parse("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}"))
|
22
|
+
pop.tracers.path.should == "/pops/#{pop._id}/tracers/"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#path_for_model" do
|
27
|
+
it "should lowercase the classname and pluralize it to create the path" do
|
28
|
+
pop = Pop.new(@api)
|
29
|
+
pop._id = '123'
|
30
|
+
pop.path.should == '/pops/123'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#publish!" do
|
35
|
+
before (:each) do
|
36
|
+
@pop = Pop.new(@api)
|
37
|
+
@pop.inflate(JSON.parse("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}"))
|
38
|
+
|
39
|
+
@result = double('result')
|
40
|
+
@result.stub(:code).and_return(200)
|
41
|
+
@result.stub(:body).and_return("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}")
|
42
|
+
RestClient.stub(:post).and_yield(nil, nil, @result)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should call update with the publish action" do
|
46
|
+
@pop.should_receive(:update).with('POST', 'publish')
|
47
|
+
@pop.publish!
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return the pop" do
|
51
|
+
@pop.publish!.should == @pop
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should set the published_pop_url" do
|
55
|
+
@pop.published_pop_url.empty?.should == true
|
56
|
+
@pop.publish!
|
57
|
+
@pop.published_pop_url.empty?.should == false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
describe "#unpublish!" do
|
63
|
+
before (:each) do
|
64
|
+
@pop = Pop.new(@api)
|
65
|
+
@pop.inflate(JSON.parse("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}"))
|
66
|
+
|
67
|
+
@result = double('result')
|
68
|
+
@result.stub(:code).and_return(200)
|
69
|
+
@result.stub(:body).and_return("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}")
|
70
|
+
RestClient.stub(:post).and_yield(nil, nil, @result)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should call update with the unpublish action" do
|
74
|
+
@pop.should_receive(:update).with('POST', 'unpublish')
|
75
|
+
@pop.unpublish!
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return the pop" do
|
79
|
+
@pop.unpublish!.should == @pop
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should set the published_pop_url" do
|
83
|
+
@pop.published_pop_url.empty?.should == false
|
84
|
+
@pop.unpublish!
|
85
|
+
@pop.published_pop_url.empty?.should == true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
describe "Populating Assets and Regions" do
|
91
|
+
before (:each) do
|
92
|
+
@pop = Pop.new(@api)
|
93
|
+
@pop.inflate(JSON.parse("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[\"tag1\"],\"unpopulated_api_regions\":[\"region1\"],\"label_names\":[]}"))
|
94
|
+
|
95
|
+
@asset = double('asset')
|
96
|
+
@asset.stub(:_id).and_return('asset_id')
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#populate_region" do
|
100
|
+
context "when a single asset is provided" do
|
101
|
+
it "should add the ID of the provided asset to the newly_populated_regions hash" do
|
102
|
+
@pop.populate_region('region1', @asset)
|
103
|
+
@pop.newly_populated_regions['region1'].should == ['asset_id']
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when an array of assets is provided" do
|
108
|
+
it "should add the IDs of the provided assets to the newly_populated_regions hash" do
|
109
|
+
@pop.populate_region('region1', [@asset])
|
110
|
+
@pop.newly_populated_regions['region1'].should == ['asset_id']
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should remove the region identifier from the list of unpopulated regions" do
|
115
|
+
@pop.unpopulated_api_regions.include?('region1').should == true
|
116
|
+
@pop.populate_region('region1', @asset)
|
117
|
+
@pop.unpopulated_api_regions.include?('region1').should == false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
describe "#has_unpopulated_region" do
|
123
|
+
it "should return true if the region identifier is unpopulated" do
|
124
|
+
@pop.has_unpopulated_region('region1').should == true
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should return false otherwise" do
|
128
|
+
@pop.has_unpopulated_region('region2').should == false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
describe "#populate_tag" do
|
134
|
+
it "should add the identifier -> value pair to the newly populated tags array" do
|
135
|
+
@pop.populate_tag('tag1', 'content')
|
136
|
+
@pop.newly_populated_tags.should == {'tag1' => 'content'}
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should remove the identifier from the unpopulated_api_tags array" do
|
140
|
+
@pop.unpopulated_api_tags.include?('tag1').should == true
|
141
|
+
@pop.populate_tag('tag1', 'content')
|
142
|
+
@pop.unpopulated_api_tags.include?('tag1').should == false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#has_unpopulated_tag" do
|
147
|
+
it "should return true if the tag identifier is unpopulated" do
|
148
|
+
@pop.has_unpopulated_tag('tag1').should == true
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should return false otherwise" do
|
152
|
+
@pop.has_unpopulated_tag('tag2').should == false
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
data/spec/populr_spec.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
::ENV['RACK_ENV'] = 'test'
|
2
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe 'Populr' do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
before (:each) do
|
9
|
+
@api_key = 'UXXMOCJW-BKSLPCFI-UQAQFWLO'
|
10
|
+
@populr = Populr.new(@api_key)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#templates' do
|
14
|
+
it "should return a model collection" do
|
15
|
+
@populr.templates.is_a?(RestfulModelCollection).should == true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe '#pops' do
|
21
|
+
it "should return a model collection" do
|
22
|
+
@populr.templates.is_a?(RestfulModelCollection).should == true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#url_for_path" do
|
27
|
+
it "should return the url for a provided path" do
|
28
|
+
@populr.url_for_path('/wobble').should == "http://#{@populr.api_key}:@#{@populr.api_server}/wobble"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#self.interpret_response" do
|
33
|
+
before (:each) do
|
34
|
+
@result = double('result')
|
35
|
+
@result.stub(:body).and_return("")
|
36
|
+
@result.stub(:code).and_return(200)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when an expected_class is provided" do
|
40
|
+
context "when the server responds with a 200 but unknown, invalid body" do
|
41
|
+
it "should raise an UnexpectedResponse" do
|
42
|
+
@result.stub(:body).and_return("I AM NOT JSON")
|
43
|
+
lambda {
|
44
|
+
Populr.interpret_response(@result, {:expected_class => Array})
|
45
|
+
}.should raise_error(Populr::UnexpectedResponse)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when the server responds with JSON that does not represent an array" do
|
50
|
+
it "should raise an UnexpectedResponse" do
|
51
|
+
@result.stub(:body).and_return("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}")
|
52
|
+
@result.stub(:code).and_return(500)
|
53
|
+
lambda {
|
54
|
+
Populr.interpret_response(@result, {:expected_class => Array})
|
55
|
+
}.should raise_error(Populr::UnexpectedResponse)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when the server responds with a 403" do
|
61
|
+
it "should raise AccessDenied" do
|
62
|
+
@result.stub(:code).and_return(403)
|
63
|
+
lambda {
|
64
|
+
Populr.interpret_response(@result)
|
65
|
+
}.should raise_error(Populr::AccessDenied)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when the server responds with a 404" do
|
70
|
+
it "should raise ResourceNotFound" do
|
71
|
+
@result.stub(:code).and_return(404)
|
72
|
+
lambda {
|
73
|
+
Populr.interpret_response(@result)
|
74
|
+
}.should raise_error(Populr::ResourceNotFound)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when the server responds with another status code" do
|
79
|
+
it "should raise an UnexpectedResponse" do
|
80
|
+
@result.stub(:code).and_return(500)
|
81
|
+
lambda {
|
82
|
+
Populr.interpret_response(@result)
|
83
|
+
}.should raise_error(Populr::UnexpectedResponse)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
::ENV['RACK_ENV'] = 'test'
|
2
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe 'RestfulModelCollection' do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
before (:each) do
|
9
|
+
@api_key = 'UXXMOCJW-BKSLPCFI-UQAQFWLO'
|
10
|
+
@populr = Populr.new(@api_key)
|
11
|
+
@collection = @populr.pops
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#all" do
|
15
|
+
it "should call interpret_response to handle standard error cases" do
|
16
|
+
Populr.should_receive(:interpret_response).and_return([])
|
17
|
+
templates = @populr.templates.all
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when the model class is a RestfulModel" do
|
21
|
+
context "when the server responds correctly" do
|
22
|
+
before (:each) do
|
23
|
+
result = double('result')
|
24
|
+
result.stub(:body).and_return("[{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}]")
|
25
|
+
result.stub(:code).and_return(200)
|
26
|
+
RestClient.should_receive(:get).and_yield(nil, nil, result)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return an array of model objects" do
|
30
|
+
pops = @collection.all
|
31
|
+
pops.count.should == 1
|
32
|
+
pops.first.is_a?(RestfulModel).should == true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should call inflate on each model object" do
|
36
|
+
Pop.any_instance.should_receive(:inflate)
|
37
|
+
pops = @collection.all
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when the model class is not a restfulModel" do
|
43
|
+
it "should return the same data type in the JSON" do
|
44
|
+
result = double('result')
|
45
|
+
result.stub(:body).and_return("[\"a\",\"b\",\"c\"]")
|
46
|
+
result.stub(:code).and_return(200)
|
47
|
+
RestClient.should_receive(:get).and_yield(nil, nil, result)
|
48
|
+
@populr.domains.all.should == ['a','b','c']
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#first" do
|
54
|
+
it "should return the first item in the all collection" do
|
55
|
+
@collection.first.should == @collection.all.first
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#find" do
|
60
|
+
it "should call interpret_response to handle standard error cases" do
|
61
|
+
Populr.should_receive(:interpret_response).and_return({})
|
62
|
+
@populr.pops.find('123')
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when the server responds correctly" do
|
66
|
+
before (:each) do
|
67
|
+
result = double('result')
|
68
|
+
result.stub(:body).and_return("{\"_id\":\"5107089add02dcaecc000003\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}")
|
69
|
+
result.stub(:code).and_return(200)
|
70
|
+
RestClient.should_receive(:get).and_yield(nil, nil, result)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return a pop" do
|
74
|
+
pop = @collection.find('5107089add02dcaecc000003')
|
75
|
+
pop.is_a?(Pop).should == true
|
76
|
+
pop._id.should == '5107089add02dcaecc000003'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#build" do
|
82
|
+
it "should create a new instance of the model object" do
|
83
|
+
parameter1 = double('parameter1')
|
84
|
+
image = @populr.images.build(parameter1)
|
85
|
+
image.is_a?(ImageAsset).should == true
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should pass the api reference, and then any provided arguments" do
|
89
|
+
parameter1 = double('parameter1')
|
90
|
+
ImageAsset.any_instance.should_receive(:initialize).with(@populr, parameter1)
|
91
|
+
@populr.images.build(parameter1)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#as_json" do
|
96
|
+
before (:each) do
|
97
|
+
result = double('result')
|
98
|
+
result.stub(:body).and_return("[{\"_id\":\"5107089add02dcaecc000003\",\"template_id\":\"5107089add02dcaecc000001\",\"created_at\":\"2013-01-28T23:24:10Z\",\"domain\":\"generic\",\"name\":\"Untitled\",\"password\":null,\"slug\":\"\",\"tracers\":[{\"_id\":\"5109b5e0dd02dc5976000001\",\"created_at\":\"2013-01-31T00:08:00Z\",\"name\":\"Facebook\"},{\"_id\":\"5109b5f5dd02dc4c43000002\",\"created_at\":\"2013-01-31T00:08:21Z\",\"name\":\"Twitter\"}],\"published_pop_url\":\"http://group3.lvh.me\",\"unpopulated_api_tags\":[],\"unpopulated_api_regions\":[],\"label_names\":[]}]")
|
99
|
+
result.stub(:code).and_return(200)
|
100
|
+
RestClient.should_receive(:get).and_yield(nil, nil, result)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should call as_json for each model in the collection" do
|
104
|
+
Pop.any_instance.should_receive(:as_json)
|
105
|
+
@collection.as_json
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should return an array of hashes" do
|
109
|
+
@collection.as_json.count.should == 1
|
110
|
+
@collection.as_json.first['_id'].should == '5107089add02dcaecc000003'
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should forward options to each model" do
|
114
|
+
Pop.any_instance.should_receive(:as_json).with(:bla => true)
|
115
|
+
@collection.as_json(:bla => true)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
::ENV['RACK_ENV'] = 'test'
|
2
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe 'RestfulModel' do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
before (:each) do
|
8
|
+
@api = Populr.new('key')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#as_json" do
|
12
|
+
it "should return a hash with the attr_accessor properties" do
|
13
|
+
r = RestfulModel.new(@api)
|
14
|
+
r._id = '1'
|
15
|
+
r.created_at = Time.new
|
16
|
+
r.as_json.should == {"_id" => "1", "created_at" => r.created_at}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'pry'
|
5
|
+
require 'pry-nav'
|
6
|
+
require 'pry-stack_explorer'
|
7
|
+
require 'populr'
|
8
|
+
|
9
|
+
# Requires supporting files with custom matchers and macros, etc,
|
10
|
+
# in ./support/ and its subdirectories.
|
11
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
|
15
|
+
end
|
data/spec/tracer_spec.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
::ENV['RACK_ENV'] = 'test'
|
2
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe 'Pop' do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
before (:each) do
|
8
|
+
@api = Populr.new('key')
|
9
|
+
@tracer = Tracer.new(@api)
|
10
|
+
@tracer.inflate(JSON.parse("{\"code\":\"tc\",\"name\":\"Twitter\",\"notify_on_open\":false,\"analytics\":{\"views\":6,\"clicks\":24,\"links\":{\"http://www.populr.me/\":{\"clicks\":4}},\"assets\":{\"empty_region\":{},\"unnamed_region_0\":{\"132213ae12bc1312\":{\"clicks\":10}},\"my_image_region\":{\"132213ae21f4812f\":{\"clicks\":10},\"f48121f48121f421\":{\"clicks\":3}}}}}"))
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
describe "#views" do
|
15
|
+
it "should retrieve the total views from analytics" do
|
16
|
+
@tracer.views.should == 6
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#clicks" do
|
21
|
+
it "should retrieve the total clicks from analytics" do
|
22
|
+
@tracer.clicks.should == 24
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#clicks_for_region" do
|
27
|
+
it "should sum the clicks for all assets in the region" do
|
28
|
+
@tracer.clicks_for_region('my_image_region').should == 13
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return 0 if the region does not exist" do
|
32
|
+
@tracer.clicks_for_region('nonexistent_region').should == 0
|
33
|
+
end
|
34
|
+
|
35
|
+
it "shoud return 0 if the region has no assets" do
|
36
|
+
@tracer.clicks_for_region('empty_region').should == 0
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return 0 if the assets section of analytics is not present" do
|
40
|
+
@tracer.inflate(JSON.parse("{\"code\":\"tc\",\"name\":\"Twitter\",\"notify_on_open\":false,\"analytics\":{\"views\":6,\"clicks\":24,\"links\":{\"http://www.populr.me/\":{\"clicks\":4}}}}"))
|
41
|
+
@tracer.clicks_for_region('my_image_region').should == 0
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#clicks_for_link" do
|
46
|
+
it "should return the analytics clicks value if the link exists" do
|
47
|
+
@tracer.clicks_for_link('http://www.populr.me/').should == 4
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return 0 if the link does not exist" do
|
51
|
+
@tracer.clicks_for_link('http://www.nonexistent.com/').should == 0
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should return 0 if the link hash is not present" do
|
55
|
+
@tracer.inflate(JSON.parse("{\"code\":\"tc\",\"name\":\"Twitter\",\"notify_on_open\":false,\"analytics\":{\"views\":6,\"clicks\":24}}"))
|
56
|
+
@tracer.clicks_for_link('http://www.populr.com/').should == 0
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#clicks_for_asset" do
|
61
|
+
it "should scan through the regions in the analytics hash and return the asset clicks" do
|
62
|
+
@tracer.clicks_for_asset('132213ae21f4812f').should == 10
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return 0 if the assets section of analytics is not present" do
|
66
|
+
@tracer.inflate(JSON.parse("{\"code\":\"tc\",\"name\":\"Twitter\",\"notify_on_open\":false,\"analytics\":{\"views\":6,\"clicks\":24,\"links\":{\"http://www.populr.me/\":{\"clicks\":4}}}}"))
|
67
|
+
@tracer.clicks_for_asset('132213ae21f4812f').should == 0
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should return 0 if there is no matching asset" do
|
71
|
+
@tracer.clicks_for_asset('asd').should == 0
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should accept an asset object as a parameter" do
|
75
|
+
asset = ImageAsset.new(@api, nil)
|
76
|
+
asset._id = '132213ae21f4812f'
|
77
|
+
@tracer.clicks_for_asset(asset).should == 10
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should accept an asset id as a parameter" do
|
81
|
+
@tracer.clicks_for_asset('132213ae21f4812f').should == 10
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#enable_webhook" do
|
86
|
+
it "should set the webhook and enable notify_on_open" do
|
87
|
+
@webhook = 'http://mycallback.com'
|
88
|
+
|
89
|
+
@tracer.notify_on_open.should == false
|
90
|
+
@tracer.enable_webhook(@webhook)
|
91
|
+
@tracer.notify_on_open.should == true
|
92
|
+
@tracer.notify_webhook.should == @webhook
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#code=" do
|
97
|
+
it "should only allow the tracer code to be set if there isn't a value" do
|
98
|
+
@tracer = Tracer.new(@api)
|
99
|
+
@tracer.code.should == nil
|
100
|
+
@tracer.code = 'as'
|
101
|
+
|
102
|
+
lambda {
|
103
|
+
@tracer.code = 'bb'
|
104
|
+
}.should raise_error(Tracer::CodeCannotBeModified)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: populr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Gotow
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.6'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.6'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: shoulda
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rdoc
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.12'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.12'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.3.5
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.3.5
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: jeweler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.8.4
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.8.4
|
94
|
+
description: Gem for interacting with the Populr.me API
|
95
|
+
email: ben@populr.me
|
96
|
+
executables: []
|
97
|
+
extensions: []
|
98
|
+
extra_rdoc_files:
|
99
|
+
- LICENSE.md
|
100
|
+
- README.rdoc
|
101
|
+
files:
|
102
|
+
- .document
|
103
|
+
- Gemfile
|
104
|
+
- Gemfile.lock
|
105
|
+
- LICENSE.md
|
106
|
+
- README.rdoc
|
107
|
+
- Rakefile
|
108
|
+
- VERSION
|
109
|
+
- lib/asset.rb
|
110
|
+
- lib/document_asset.rb
|
111
|
+
- lib/domain.rb
|
112
|
+
- lib/image_asset.rb
|
113
|
+
- lib/pop.rb
|
114
|
+
- lib/populr.rb
|
115
|
+
- lib/restful_model.rb
|
116
|
+
- lib/restful_model_collection.rb
|
117
|
+
- lib/template.rb
|
118
|
+
- lib/tracer.rb
|
119
|
+
- spec/pop_spec.rb
|
120
|
+
- spec/populr_spec.rb
|
121
|
+
- spec/restful_model_collection_spec.rb
|
122
|
+
- spec/restful_model_spec.rb
|
123
|
+
- spec/spec_helper.rb
|
124
|
+
- spec/tracer_spec.rb
|
125
|
+
homepage: http://github.com/bengotow/populr
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
hash: -1796578390559359755
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ! '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 1.8.24
|
150
|
+
signing_key:
|
151
|
+
specification_version: 3
|
152
|
+
summary: Gem for interacting with the Populr.me API
|
153
|
+
test_files: []
|