foxy_sync 0.1.1 → 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.
@@ -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