foxy_sync 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,23 @@
1
1
  module FoxySync::Api
2
2
  #
3
3
  # Intended for subclassing, +Base+ forms the foundation
4
- # for ::Api:: classes that wrap an ::Api::Response object
5
- # to provide behavior around specific data in the +Response+
4
+ # for ::Api:: classes that wrap a +FoxySync::Xml::Document+
5
+ # composed of API reply XML to provide behavior around
6
+ # specific elements
6
7
  class Base
7
- attr_accessor :api_response
8
+ attr_reader :api_response
8
9
 
9
10
  #
10
11
  # [_api_response_]
11
- # A +FoxySync::Api::Response+ instance
12
+ # A +FoxySync::Xml::Document+ that holds API reply XML
12
13
  def initialize(api_response)
13
- self.api_response = api_response
14
+ @api_response = api_response
14
15
  end
15
16
 
16
17
  #
17
18
  # Delegates to #api_response
18
19
  def respond_to?(method_name, include_private = false)
19
- api_response.respond_to? method_name, include_private
20
+ super || api_response.respond_to?(method_name, include_private)
20
21
  end
21
22
 
22
23
 
@@ -27,8 +28,8 @@ module FoxySync::Api
27
28
  end
28
29
 
29
30
 
30
- def fc_api
31
- @_fc_api ||= FoxySync::Api::Messenger.new
31
+ def messenger
32
+ @_messenger ||= FoxySync::Api::Messenger.new
32
33
  end
33
34
  end
34
35
  end
@@ -20,21 +20,22 @@ module FoxySync::Api
20
20
  # that work with authentication systems like +Devise+
21
21
  def initialize(user)
22
22
  self.user = user
23
- super fc_api.customer_get :customer_email => user.email
23
+ super messenger.customer_get :customer_email => user.email
24
24
  end
25
25
 
26
26
 
27
27
  #
28
28
  # Sends the customer_save command to the FoxyCart API.
29
- # Returns a FoxySync::Api::Response
29
+ # Returns a FoxySync::Xml::Document
30
30
  def save
31
31
  salt = user.password_salt
32
32
  hash = OpenSSL::HMAC.hexdigest 'sha256', salt, user.encrypted_password + salt
33
- fc_api.customer_save(
33
+ messenger.customer_save(
34
34
  :customer_email => user.email,
35
35
  :customer_password_hash => hash,
36
36
  :customer_password_salt => salt
37
37
  )
38
38
  end
39
39
  end
40
+
40
41
  end
@@ -7,7 +7,7 @@ module FoxySync::Api
7
7
  # the FoxyCart API (http://wiki.foxycart.com/v/1.0/api).
8
8
  # To use it create a new instance and then send it a message
9
9
  # that corresponds to the FoxyCart API. All messages
10
- # return an instance of +FoxySync::Api::Response+. For Example:
10
+ # return an instance of +FoxySync::Xml::Document+. For Example:
11
11
  #
12
12
  # api = FoxySync::Api::Messenger.new
13
13
  # reply = api.customer_get :customer_email => 'foo@bar.com'
@@ -49,7 +49,7 @@ module FoxySync::Api
49
49
  def method_missing(method_name, *args, &block)
50
50
  return super unless respond_to? method_name
51
51
  xml = api_request method_name, args.first || {}
52
- FoxySync::Api::Response.new xml
52
+ FoxySync::Xml::Document.new xml
53
53
  end
54
54
 
55
55
 
@@ -9,8 +9,8 @@ module FoxySync
9
9
  module Datafeed
10
10
 
11
11
  #
12
- # Handles the decoding and decrypting of a datafeed request.
13
- # Returns a +FoxySync::Api::Response+ whose document is the datafeed XML
12
+ # Handles the decoding and decrypting of a datafeed.
13
+ # Returns a +FoxySync::Xml::Document+ whose #xml is the datafeed XML
14
14
  #[_params_]
15
15
  # Something that responds_to? [] and has a key 'FoxyData'. In Rails
16
16
  # that would be the +params+ object
@@ -18,7 +18,7 @@ module FoxySync
18
18
  encrypted = params['FoxyData']
19
19
  rc4 = RC4.new FoxySync.api_key
20
20
  xml = rc4.decrypt CGI::unescape(encrypted)
21
- FoxySync::Api::Response.new xml
21
+ FoxySync::Xml::Document.new xml
22
22
  end
23
23
 
24
24
 
@@ -0,0 +1,48 @@
1
+ module FoxySync::Xml
2
+ #
3
+ # Allows querying of the given +Nokogiri::XML::Node+.
4
+ # Every message returns:
5
+ #
6
+ # * nil if no matching element is found in the XML or
7
+ # if the matched element(s) do not contain text or cdata.
8
+ # * A +String+ if there is one matching element in the reply.
9
+ # * An +Array+ with all element values if there is more than one
10
+ # matching element in the XML.
11
+ class Base
12
+
13
+ attr_reader :node
14
+
15
+
16
+ #
17
+ # [_node_]
18
+ # A +Nokogiri::XML::Node+
19
+ def initialize(node)
20
+ @node = node
21
+ end
22
+
23
+
24
+ def respond_to?(method_name, include_private = false)
25
+ true # respond to everything; we don't know what will be in the response doc
26
+ end
27
+
28
+
29
+ private
30
+
31
+ def method_missing(method_name, *args, &block)
32
+ node_set = node.xpath "//#{method_name}"
33
+ return nil if node_set.nil? || node_set.empty?
34
+
35
+ contents = []
36
+
37
+ node_set.children.each do |child|
38
+ next if child.element?
39
+ content = child.content.strip
40
+ contents << content unless content.empty?
41
+ end
42
+
43
+ contents.empty? ? nil : contents.size == 1 ? contents.first : contents
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,22 @@
1
+ require 'nokogiri'
2
+
3
+ module FoxySync::Xml
4
+ #
5
+ # Encapsulates a FoxyCart XML doc. To use it simply send a
6
+ # message that corresponds to an element in the XML. For example,
7
+ #
8
+ # api = FoxySync::Api::Messenger.new
9
+ # reply = api.customer_get :customer_email => 'foo@bar.com'
10
+ # reply.customer_id # is the customer's FoxyCart id
11
+ class Document < Base
12
+ #
13
+ # The raw XML used to create this +Document+
14
+ attr_reader :xml
15
+
16
+
17
+ def initialize(xml)
18
+ @xml = xml
19
+ super Nokogiri::XML(xml) {|config| config.strict.nonet }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ module FoxySync::Xml
2
+ #
3
+ # Provides methods to easily query the transaction_detail
4
+ # elements found in a FoxyCart transaction XML datafeed
5
+ class TransactionDetail < Base
6
+
7
+ #
8
+ # Returns an +Array+ of the +TransactionDetail+s in +xml_base+
9
+ # [_xml_base_]
10
+ # A +FoxySync::Xml::Base+ that has a transaction_details element
11
+ def self.all(xml_base)
12
+ transactions = []
13
+
14
+ xml_base.node.xpath('//transaction_details').each do |detail|
15
+ transactions << new(detail)
16
+ end
17
+
18
+ transactions
19
+ end
20
+
21
+
22
+ #
23
+ # Returns custom product options in a 'name' => 'value' +Hash+
24
+ def custom_product_options
25
+ options = {}
26
+ options_xml = node.xpath '//transaction_detail_option'
27
+
28
+ options_xml.each do |node|
29
+ name = node.at_css('product_option_name').content.strip
30
+ value = node.at_css('product_option_value').content.strip
31
+ options[name] = value
32
+ end
33
+
34
+ options
35
+ end
36
+
37
+ end
38
+
39
+ end
data/lib/foxy_sync.rb CHANGED
@@ -4,10 +4,16 @@ module FoxySync
4
4
  autoload :CartValidation, 'foxy_sync/cart_validation'
5
5
 
6
6
  module Api
7
- autoload :Messenger, 'foxy_sync/api/messenger'
8
- autoload :Response, 'foxy_sync/api/response'
9
7
  autoload :Base, 'foxy_sync/api/base'
10
8
  autoload :Customer, 'foxy_sync/api/customer'
9
+ autoload :Messenger, 'foxy_sync/api/messenger'
10
+ end
11
+
12
+ module Xml
13
+ autoload :Base, 'foxy_sync/xml/base'
14
+ autoload :Document, 'foxy_sync/xml/document'
15
+ autoload :Transaction, 'foxy_sync/xml/transaction'
16
+ autoload :TransactionDetail, 'foxy_sync/xml/transaction_detail'
11
17
  end
12
18
 
13
19
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foxy_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-10 00:00:00.000000000 Z
12
+ date: 2013-03-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -65,14 +65,26 @@ executables: []
65
65
  extensions: []
66
66
  extra_rdoc_files: []
67
67
  files:
68
- - ./lib/foxy_sync/api/base.rb
69
- - ./lib/foxy_sync/api/customer.rb
70
- - ./lib/foxy_sync/api/messenger.rb
71
- - ./lib/foxy_sync/api/response.rb
72
- - ./lib/foxy_sync/cart_validation.rb
73
- - ./lib/foxy_sync/datafeed.rb
74
- - ./lib/foxy_sync/sso.rb
75
- - ./lib/foxy_sync.rb
68
+ - !binary |-
69
+ Li9saWIvZm94eV9zeW5jL2FwaS9iYXNlLnJi
70
+ - !binary |-
71
+ Li9saWIvZm94eV9zeW5jL2FwaS9jdXN0b21lci5yYg==
72
+ - !binary |-
73
+ Li9saWIvZm94eV9zeW5jL2FwaS9tZXNzZW5nZXIucmI=
74
+ - !binary |-
75
+ Li9saWIvZm94eV9zeW5jL2NhcnRfdmFsaWRhdGlvbi5yYg==
76
+ - !binary |-
77
+ Li9saWIvZm94eV9zeW5jL2RhdGFmZWVkLnJi
78
+ - !binary |-
79
+ Li9saWIvZm94eV9zeW5jL3Nzby5yYg==
80
+ - !binary |-
81
+ Li9saWIvZm94eV9zeW5jL3htbC9iYXNlLnJi
82
+ - !binary |-
83
+ Li9saWIvZm94eV9zeW5jL3htbC9kb2N1bWVudC5yYg==
84
+ - !binary |-
85
+ Li9saWIvZm94eV9zeW5jL3htbC90cmFuc2FjdGlvbl9kZXRhaWwucmI=
86
+ - !binary |-
87
+ Li9saWIvZm94eV9zeW5jLnJi
76
88
  homepage: https://github.com/tablexi/foxy_sync
77
89
  licenses: []
78
90
  post_install_message:
@@ -93,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
105
  version: '0'
94
106
  requirements: []
95
107
  rubyforge_project:
96
- rubygems_version: 1.8.25
108
+ rubygems_version: 1.8.24
97
109
  signing_key:
98
110
  specification_version: 3
99
111
  summary: Synchronizes your Ruby application with FoxyCart
@@ -1,47 +0,0 @@
1
- require 'nokogiri'
2
-
3
- module FoxySync::Api
4
- #
5
- # A +Response+ represents an XML reply
6
- # sent by the FoxyCart API. To use it simply
7
- # send an instance a message that corresponds
8
- # to an element in the XML. For example,
9
- #
10
- # api = FoxySync::Api::Messenger.new
11
- # reply = api.customer_get :customer_email => 'foo@bar.com'
12
- # reply.customer_id # is the customer's FoxyCart id
13
- #
14
- # Every message will return +nil+ if no matching
15
- # element is found in the XML reply, a +String+ if
16
- # there is one matching element in the reply, or an
17
- # +Array+ with all element values if there is more than one
18
- # element in the XML reply.
19
- class Response
20
- #
21
- # A +Nokogiri::XML::Document+ of the API reply
22
- attr_reader :document
23
-
24
-
25
- def initialize(xml)
26
- @document = Nokogiri::XML(xml) {|config| config.strict.nonet }
27
- end
28
-
29
-
30
- def respond_to?(method_name, include_private = false)
31
- true # respond to everything; we don't know what will be in the response doc
32
- end
33
-
34
-
35
- private
36
-
37
- def method_missing(method_name, *args, &block)
38
- node_set = document.xpath "//#{method_name}"
39
- return nil if node_set.nil? || node_set.empty?
40
-
41
- contents = node_set.to_a
42
- contents.map!{|node| node.content }
43
- contents.delete_if{|content| content.empty? }
44
- contents.size == 1 ? contents.first : contents
45
- end
46
- end
47
- end