neuron-client 0.1.0 → 0.2.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.
Files changed (85) hide show
  1. data/README.md +34 -8
  2. data/lib/neuron-client.rb +61 -12
  3. data/lib/neuron-client/{connection.rb → admin_connection.rb} +7 -7
  4. data/lib/neuron-client/api.rb +48 -31
  5. data/lib/neuron-client/membase_connection.rb +18 -0
  6. data/lib/neuron-client/model/admin/ad.rb +22 -0
  7. data/lib/neuron-client/model/admin/ad_zone.rb +15 -0
  8. data/lib/neuron-client/model/admin/base.rb +91 -0
  9. data/lib/neuron-client/model/admin/blocked_referer.rb +12 -0
  10. data/lib/neuron-client/model/admin/blocked_user_agent.rb +12 -0
  11. data/lib/neuron-client/model/admin/geo_target.rb +16 -0
  12. data/lib/neuron-client/model/admin/report.rb +15 -0
  13. data/lib/neuron-client/model/admin/s3_file.rb +12 -0
  14. data/lib/neuron-client/model/admin/zone.rb +15 -0
  15. data/lib/neuron-client/model/base.rb +38 -0
  16. data/lib/neuron-client/model/common/ad.rb +40 -0
  17. data/lib/neuron-client/model/common/ad_calculations.rb +329 -0
  18. data/lib/neuron-client/model/common/ad_zone.rb +17 -0
  19. data/lib/neuron-client/model/common/base.rb +67 -0
  20. data/lib/neuron-client/model/common/blocked_referer.rb +16 -0
  21. data/lib/neuron-client/model/common/blocked_user_agent.rb +16 -0
  22. data/lib/neuron-client/model/common/geo_target.rb +16 -0
  23. data/lib/neuron-client/model/common/report.rb +21 -0
  24. data/lib/neuron-client/model/common/s3_file.rb +16 -0
  25. data/lib/neuron-client/model/common/zone.rb +22 -0
  26. data/lib/neuron-client/model/common/zone_calculations.rb +41 -0
  27. data/lib/neuron-client/model/membase/ad.rb +31 -0
  28. data/lib/neuron-client/model/membase/ad_zone.rb +11 -0
  29. data/lib/neuron-client/model/membase/blocked_referer.rb +18 -0
  30. data/lib/neuron-client/model/membase/blocked_user_agent.rb +18 -0
  31. data/lib/neuron-client/model/membase/geo_target.rb +11 -0
  32. data/lib/neuron-client/model/membase/report.rb +11 -0
  33. data/lib/neuron-client/model/membase/s3_file.rb +11 -0
  34. data/lib/neuron-client/model/membase/zone.rb +19 -0
  35. data/lib/neuron-client/model/models.rb +14 -0
  36. data/lib/neuron-client/version.rb +1 -1
  37. data/neuron-client.gemspec +18 -11
  38. data/spec/fixtures/vcr_cassettes/s3_file.yml +186 -4
  39. data/spec/lib/admin_connection_spec.rb +82 -0
  40. data/spec/lib/api_spec.rb +80 -0
  41. data/spec/lib/membase_connection_spec.rb +27 -0
  42. data/spec/lib/model/admin/ad_spec.rb +34 -0
  43. data/spec/lib/model/admin/ad_zone_spec.rb +19 -0
  44. data/spec/lib/model/admin/base_spec.rb +11 -0
  45. data/spec/lib/model/admin/blocked_referer_spec.rb +11 -0
  46. data/spec/lib/model/admin/blocked_user_agent_spec.rb +11 -0
  47. data/spec/lib/model/admin/geo_target_spec.rb +30 -0
  48. data/spec/lib/model/admin/report_spec.rb +21 -0
  49. data/spec/lib/model/admin/s3_spec.rb +11 -0
  50. data/spec/lib/model/admin/zone_spec.rb +21 -0
  51. data/spec/lib/model/base_spec.rb +89 -0
  52. data/spec/lib/model/common/ad_calculations_spec.rb +1148 -0
  53. data/spec/lib/model/common/ad_spec.rb +11 -0
  54. data/spec/lib/model/common/ad_zone_spec.rb +11 -0
  55. data/spec/lib/model/common/base_spec.rb +11 -0
  56. data/spec/lib/model/common/blocked_referer_spec.rb +11 -0
  57. data/spec/lib/model/common/blocked_user_agent_spec.rb +11 -0
  58. data/spec/lib/model/common/geo_target_spec.rb +11 -0
  59. data/spec/lib/model/common/report_spec.rb +11 -0
  60. data/spec/lib/model/common/s3_spec.rb +11 -0
  61. data/spec/lib/model/common/zone_calculations_spec.rb +54 -0
  62. data/spec/lib/model/common/zone_spec.rb +11 -0
  63. data/spec/lib/model/membase/ad_spec.rb +50 -0
  64. data/spec/lib/model/membase/ad_zone_spec.rb +11 -0
  65. data/spec/lib/model/membase/base_spec.rb +11 -0
  66. data/spec/lib/model/membase/blocked_referer_spec.rb +30 -0
  67. data/spec/lib/model/membase/blocked_user_agent_spec.rb +30 -0
  68. data/spec/lib/model/membase/geo_target_spec.rb +11 -0
  69. data/spec/lib/model/membase/report_spec.rb +11 -0
  70. data/spec/lib/model/membase/s3_spec.rb +11 -0
  71. data/spec/lib/model/membase/zone_spec.rb +28 -0
  72. data/spec/lib/old_spec.rb +192 -149
  73. data/spec/lib/s3_file_spec.rb +45 -42
  74. data/spec/spec_helper.rb +2 -1
  75. metadata +296 -57
  76. data/lib/neuron-client/ad.rb +0 -39
  77. data/lib/neuron-client/ad_zone.rb +0 -16
  78. data/lib/neuron-client/blocked_referer.rb +0 -12
  79. data/lib/neuron-client/blocked_user_agent.rb +0 -12
  80. data/lib/neuron-client/connected.rb +0 -138
  81. data/lib/neuron-client/geo_target.rb +0 -16
  82. data/lib/neuron-client/real_time_stats.rb +0 -0
  83. data/lib/neuron-client/report.rb +0 -20
  84. data/lib/neuron-client/s3_file.rb +0 -10
  85. data/lib/neuron-client/zone.rb +0 -16
data/README.md CHANGED
@@ -5,31 +5,57 @@ Neuron Client Gem
5
5
  Setup
6
6
  =====
7
7
 
8
- Neuron::Client::API.configure do |config|
9
- config.admin_url = "https://example.com"
10
- config.admin_key = "secret"
11
- end
8
+ Connect to the admin server for read/write access to exposed models:
12
9
 
10
+ Neuron::Client::API.default_api.configure do |config|
11
+ config.connection_type = :admin
12
+ config.admin_url = "https://example.com"
13
+ config.admin_key = "secret"
14
+ end
15
+
16
+ Short form to copy and paste into console:
17
+
18
+ Neuron::Client::API.default_api.configure {|config| config.connection_type = :admin; config.admin_url = 'http://localhost:3000'; config.admin_key = 'secret'}
19
+
20
+
21
+ Connect to the Membase (or Memcached) Server for limited read access to some exposed models:
22
+
23
+ Neuron::Client::API.default_api.configure do |config|
24
+ config.connection_type = :membase
25
+ config.membase_servers = "127.0.0.1:11211"
26
+ end
27
+
28
+ Short form to copy and paste into console:
29
+
30
+ Neuron::Client::API.default_api.configure {|config| config.connection_type = :membase; config.membase_servers = '127.0.0.1:11211'}
31
+
32
+ Create a new API, configure and use it for one specific model:
33
+
34
+ api = Neuron::Client::API.new
35
+ api.configure {|config| config.connection_type = :membase; config.membase_servers = '127.0.0.1:11211'}
36
+ Neuron::Client::Model::Ad.api = api
13
37
 
14
38
  Zones
15
39
  =====
16
40
 
41
+ *Note: many finder methods are not available when using a Membase connection. Objects are read-only when using a Membase connection.
42
+
17
43
  Create a zone:
18
44
 
19
- zone = Neuron::Client::Zone.new(:slug => 'test', :response_type => 'Redirect')
45
+ zone = Neuron::Client::Model::Zone.new(:slug => 'test', :response_type => 'Redirect')
20
46
  zone.save
21
47
 
22
48
  ... or simply:
23
49
 
24
- Neuron::Client::Zone.create(:slug => 'test', :response_type => 'Redirect')
50
+ Neuron::Client::Model::Zone.create(:slug => 'test', :response_type => 'Redirect')
25
51
 
26
52
  List all zones:
27
53
 
28
- Neuron::Client::Zone.all # => Array of Zone objects (with limited attributes)
54
+ Neuron::Client::Model::Zone.all # => Array of Zone objects (with limited attributes)
29
55
 
30
56
  Find a zone by ID:
31
57
 
32
- Neuron::Client::Zone.find(zone_id)
58
+ Neuron::Client::Model::Zone.find(zone_id)
33
59
 
34
60
  Update a zone:
35
61
 
data/lib/neuron-client.rb CHANGED
@@ -1,16 +1,42 @@
1
+ require "active_support/core_ext"
1
2
  require "neuron-client/version"
3
+ require "neuron-client/admin_connection"
4
+ require "neuron-client/membase_connection"
2
5
  require "neuron-client/api"
3
- require "neuron-client/connection"
4
- require "neuron-client/connected"
5
- require "neuron-client/ad"
6
- require "neuron-client/ad_zone"
7
- require "neuron-client/blocked_referer"
8
- require "neuron-client/blocked_user_agent"
9
- require "neuron-client/geo_target"
10
- require "neuron-client/real_time_stats"
11
- require "neuron-client/report"
12
- require "neuron-client/s3_file"
13
- require "neuron-client/zone"
6
+
7
+ require "neuron-client/model/common/base"
8
+ require "neuron-client/model/common/ad_calculations"
9
+ require "neuron-client/model/common/ad"
10
+ require "neuron-client/model/common/ad_zone"
11
+ require "neuron-client/model/common/blocked_referer"
12
+ require "neuron-client/model/common/blocked_user_agent"
13
+ require "neuron-client/model/common/geo_target"
14
+ require "neuron-client/model/common/report"
15
+ require "neuron-client/model/common/s3_file"
16
+ require "neuron-client/model/common/zone_calculations"
17
+ require "neuron-client/model/common/zone"
18
+
19
+ require "neuron-client/model/admin/base"
20
+ require "neuron-client/model/admin/ad"
21
+ require "neuron-client/model/admin/ad_zone"
22
+ require "neuron-client/model/admin/blocked_referer"
23
+ require "neuron-client/model/admin/blocked_user_agent"
24
+ require "neuron-client/model/admin/geo_target"
25
+ require "neuron-client/model/admin/report"
26
+ require "neuron-client/model/admin/s3_file"
27
+ require "neuron-client/model/admin/zone"
28
+
29
+ require "neuron-client/model/membase/ad"
30
+ require "neuron-client/model/membase/ad_zone"
31
+ require "neuron-client/model/membase/blocked_referer"
32
+ require "neuron-client/model/membase/blocked_user_agent"
33
+ require "neuron-client/model/membase/geo_target"
34
+ require "neuron-client/model/membase/report"
35
+ require "neuron-client/model/membase/s3_file"
36
+ require "neuron-client/model/membase/zone"
37
+
38
+ require "neuron-client/model/base"
39
+ require "neuron-client/model/models"
14
40
 
15
41
  class Object
16
42
  def blank?
@@ -22,4 +48,27 @@ class Object
22
48
  def present?
23
49
  !self.blank?
24
50
  end
25
- end
51
+ end
52
+
53
+ # lifted completely from the ruby facets gem source:
54
+ # /lib/core-uncommon/facets/module/cattr.rb
55
+ def Module
56
+ def cattr_writer(*syms)
57
+ syms.flatten.each do |sym|
58
+ module_eval(<<-EOS, __FILE__, __LINE__)
59
+ unless defined? @@#{sym}
60
+ @@#{sym} = nil
61
+ end
62
+
63
+ def self.#{sym}=(obj)
64
+ @@#{sym} = obj
65
+ end
66
+
67
+ def #{sym}=(obj)
68
+ @@#{sym}=(obj)
69
+ end
70
+ EOS
71
+ end
72
+ return syms
73
+ end
74
+ end
@@ -3,7 +3,7 @@ require 'yajl'
3
3
 
4
4
  module Neuron
5
5
  module Client
6
- class Connection
6
+ class AdminConnection
7
7
  def initialize(url, key)
8
8
  @url = url
9
9
  @key = key
@@ -19,7 +19,7 @@ module Neuron
19
19
 
20
20
  def get(path="", attrs={})
21
21
  format = attrs.delete(:format) || :json
22
- RestClient.get("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string(attrs)}",
22
+ RestClient.get("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string(attrs)}",
23
23
  format.present? ? {:content_type => format, :accept => format} : {}) do |response, request, result, &block|
24
24
  # follow redirection
25
25
  if [301, 302, 307].include? response.code
@@ -37,8 +37,8 @@ module Neuron
37
37
 
38
38
  def post(path="", form={}, attrs={})
39
39
  format = attrs.delete(:format) || :json
40
- RestClient.post("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string(attrs)}",
41
- (format == :json ? Yajl.dump(form) : form),
40
+ RestClient.post("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string(attrs)}",
41
+ (format == :json ? Yajl.dump(form) : form),
42
42
  format.present? ? {:content_type => format, :accept => format} : {}) do |response, request, result, &block|
43
43
  case response.code
44
44
  when 201
@@ -53,8 +53,8 @@ module Neuron
53
53
 
54
54
  def put(path="", form={}, attrs={})
55
55
  format = attrs.delete(:format) || :json
56
- RestClient.put("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string}",
57
- (format == :json ? Yajl.dump(form) : form),
56
+ RestClient.put("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string}",
57
+ (format == :json ? Yajl.dump(form) : form),
58
58
  format.present? ? {:content_type => format, :accept => format} : {}) do |response, request, result, &block|
59
59
  case response.code
60
60
  when 200
@@ -69,7 +69,7 @@ module Neuron
69
69
 
70
70
  def delete(path="", attrs={})
71
71
  format = attrs.delete(:format) || :json
72
- RestClient.delete("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string(attrs)}",
72
+ RestClient.delete("#{@url}/#{[path, format].select(&:present?).join(".")}?#{query_string(attrs)}",
73
73
  format.present? ? {:content_type => format, :accept => format} : {}) do |response, request, result, &block|
74
74
  case response.code
75
75
  when 200
@@ -1,45 +1,62 @@
1
1
  module Neuron
2
2
  module Client
3
-
4
- # Neuron::Client::API.configure do |config|
5
- # config.admin_url = "https://example.com"
6
- # config.admin_key = "secret"
7
- # end
8
- #
9
- # Neuron::Client::API.connection
10
3
  class API
11
4
  autoload :OpenStruct, "ostruct"
12
- class << self
13
- attr_accessor :connection
5
+ attr_accessor :connection
14
6
 
15
- def reset!
16
- self.connection = nil
17
- @config = nil
18
- end
7
+ def configure
8
+ yield config
9
+ inclusion(config, :connection_type, [:admin, :membase])
10
+
11
+ configure_admin_connection if config.connection_type == :admin
12
+ configure_membase_connection if config.connection_type == :membase
13
+
14
+ self
15
+ end
16
+
17
+ def connection_type
18
+ @config.connection_type
19
+ end
19
20
 
20
- def configure
21
- @config ||= OpenStruct.new
22
- yield @config
23
- required(@config, :admin_url)
24
- required(@config, :admin_key)
25
- begin
26
- URI.parse(@config.admin_url)
27
- rescue
28
- raise "Invalid admin_url: #{@config.admin_url}"
29
- end
30
- self.connection = Connection.new(@config.admin_url, @config.admin_key)
31
- true
21
+ private
22
+
23
+ def config
24
+ @config ||= OpenStruct.new
25
+ end
26
+
27
+ def required(obj, attrib)
28
+ val = obj.send(attrib)
29
+ if val.nil? || (val.respond_to?(:empty?) && val.empty?)
30
+ raise "Missing: #{attrib}"
32
31
  end
32
+ end
33
33
 
34
- private
34
+ def inclusion(obj, attrib, valid_values)
35
+ val = obj.send(attrib)
36
+ raise "Inclusion: #{attrib} must be one of #{valid_values.join(', ')}" if !valid_values.include?(val)
37
+ end
35
38
 
36
- def required(obj, attrib)
37
- val = obj.send(attrib)
38
- if val.nil? || (val.respond_to?(:empty?) && val.empty?)
39
- raise "Missing: #{attrib}"
40
- end
39
+ def configure_admin_connection
40
+ required(config, :admin_url)
41
+ required(config, :admin_key)
42
+ begin
43
+ URI.parse(config.admin_url)
44
+ rescue
45
+ raise "Invalid admin_url: #{config.admin_url}"
41
46
  end
47
+ self.connection = AdminConnection.new(config.admin_url, config.admin_key)
48
+ end
49
+
50
+ def configure_membase_connection
51
+ required(@config, :membase_servers)
52
+ self.connection = MembaseConnection.new(config.membase_servers)
53
+ end
54
+
55
+ class << self
56
+ attr_accessor :default_api
42
57
  end
43
58
  end
59
+
60
+ API.default_api = API.new
44
61
  end
45
62
  end
@@ -0,0 +1,18 @@
1
+ require 'dalli'
2
+
3
+ module Neuron
4
+ module Client
5
+ class MembaseConnection
6
+
7
+ attr_reader :client
8
+
9
+ def initialize(servers)
10
+ @client = Dalli::Client.new(servers)
11
+ end
12
+
13
+ def get(key)
14
+ @client.get(key)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Neuron
2
+ module Client
3
+ module Model
4
+ module Admin
5
+ class Ad < Common::Ad
6
+ include Base
7
+
8
+ # deliveries
9
+ attr_accessor :total_impressed, :today_impressed
10
+
11
+ def recent(statistic, parameters)
12
+ self.class.connection.get("ads/#{id}/recent/#{statistic}", parameters)
13
+ end
14
+
15
+ def unlink(zone_id)
16
+ self.class.connection.delete("ads/#{id}/zones/#{zone_id}")
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module Neuron
2
+ module Client
3
+ module Model
4
+ module Admin
5
+ class AdZone < Common::AdZone
6
+ include Base
7
+
8
+ def self.unlink(ad_id, zone_id)
9
+ self.connection.delete("zones/#{zone_id}/ads/#{ad_id}")
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,91 @@
1
+ module Neuron
2
+ module Client
3
+ module Model
4
+ module Admin
5
+ module Base
6
+ def attributes
7
+ self.class.attributes || []
8
+ end
9
+
10
+ def to_hash(*except)
11
+ hash = {}
12
+ attributes.reject{|a| except.collect(&:to_sym).include?(a.to_sym)}.each do |attribute|
13
+ value = send(attribute)
14
+ hash[attribute] = value unless value.nil?
15
+ end
16
+ hash
17
+ end
18
+
19
+ def new_record?
20
+ id.nil?
21
+ end
22
+
23
+ def save
24
+ @errors = catch :errors do
25
+ if new_record?
26
+ response = self.class.connection.post("#{self.class.superclass.resources_name}", {self.class.superclass.resource_name => self.to_hash(:errors, :updated_at, :created_at)})
27
+ self.id = response[self.class.superclass.resource_name][self.class.remote_id]
28
+ else
29
+ response = self.class.connection.put("#{self.class.superclass.resources_name}/#{id}", {self.class.superclass.resource_name => self.to_hash(:errors, :updated_at, :created_at)})
30
+ end
31
+ []
32
+ end
33
+
34
+ @errors.empty?
35
+ end
36
+
37
+ def update_attributes(attrs={})
38
+ @errors = catch :errors do
39
+ response = self.class.connection.put("#{self.class.superclass.resources_name}/#{id}", {self.class.superclass.resource_name => attrs})
40
+ attrs.each do |key, value|
41
+ self.send("#{key}=", value) if self.respond_to?("#{key}=")
42
+ end
43
+ []
44
+ end
45
+
46
+ @errors.empty?
47
+ end
48
+
49
+ def valid?
50
+ @errors.empty?
51
+ end
52
+
53
+ def destroy
54
+ self.class.connection.delete("#{superclass.resources_name}/#{id}")
55
+ end
56
+
57
+ def self.included(base)
58
+ base.send(:attr_accessor, :errors)
59
+ base.extend(ClassMethods)
60
+ end
61
+
62
+ module ClassMethods
63
+ def find(id)
64
+ response = self.connection.get("#{superclass.resources_name}/#{id}")
65
+ model = nil
66
+ model = self.new(response[superclass.resource_name]) if response.present?
67
+ model
68
+ end
69
+
70
+ def all
71
+ response = self.connection.get("#{superclass.resources_name}")
72
+ response.map{|hash| self.new(hash[superclass.resource_name])}
73
+ end
74
+
75
+ def create(attrs={})
76
+ @errors = catch (:errors) do
77
+ return create!(attrs)
78
+ end
79
+ nil
80
+ end
81
+
82
+ def create!(attrs={})
83
+ response = self.connection.post("#{superclass.resources_name}", {superclass.resource_name => attrs})
84
+ self.new(response[superclass.resource_name])
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,12 @@
1
+ module Neuron
2
+ module Client
3
+ module Model
4
+ module Admin
5
+ class BlockedReferer < Common::BlockedReferer
6
+ include Base
7
+
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end