quickbooks_api 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ class Hash
2
+
3
+ def path_to_nested_key(key)
4
+ self.each do |k,v|
5
+ path = [k]
6
+ if k == key
7
+ return path
8
+ elsif v.is_a? Hash
9
+ nested_path = v.path_to_nested_key(key)
10
+ nested_path ? (return path + nested_path) : nil
11
+ end
12
+ end
13
+ return nil
14
+ end
15
+
16
+ def self.nest(path, value)
17
+ hash_constructor = lambda { |h, k| h[k] = Hash.new(&hash_constructor) }
18
+ nested_hash = Hash.new(&hash_constructor)
19
+
20
+ last_key = path.last
21
+ path.inject(nested_hash) { |h, k| (k == last_key) ? h[k] = value : h[k] }
22
+ nested_hash
23
+ end
24
+
25
+ end
26
+
27
+ class Class
28
+ def simple_name
29
+ self.to_s.split("::").last
30
+ end
31
+ end
32
+
33
+ class Object
34
+ def not_blank?
35
+ !self.blank?
36
+ end
37
+ end
38
+
39
+ class File
40
+ def self.read_from_unknown(file)
41
+ case file
42
+ when String
43
+ File.read(file)
44
+ when IO
45
+ file.read
46
+ end
47
+ end
48
+ end
@@ -4,29 +4,32 @@ describe Quickbooks::API do
4
4
 
5
5
  describe "interface" do
6
6
 
7
- it "should initialize" do
7
+ it "should initialize api instance" do
8
8
  end
9
9
 
10
- it "should create ruby wrapper objects for any qbxml input" do
10
+ it "should return cached instance for consecutive api requests" do
11
11
  end
12
12
 
13
- it "should convert ruby wrapper objects back to qbxml" do
13
+ it "should create qbxml object from qbxml input" do
14
14
  end
15
15
 
16
- end
17
-
18
- describe "helpers" do
16
+ it "should create qbxml object from hash input" do
17
+ end
19
18
 
20
- it "should load the schema" do
19
+ it "should convert qbxml input to hash output" do
21
20
  end
22
21
 
23
- it "should rebuild the schema" do
22
+ it "should convert hash input to qbxml output" do
24
23
  end
25
24
 
26
- it "should write the schema to disk" do
25
+ end
26
+
27
+ describe "helpers" do
28
+
29
+ it "should load the schema into memory during initialization" do
27
30
  end
28
31
 
29
- it "should find a nested qbxml hash" do
32
+ it "should load the container template into memory before initialization" do
30
33
  end
31
34
 
32
35
  end
@@ -1,6 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
2
 
3
- describe Quickbooks::Support::ClassBuilder do
3
+ describe Quickbooks::Parser::ClassBuilder do
4
4
 
5
5
  it "should add a type checked attribute accessor to a class" do
6
6
  end
@@ -0,0 +1,72 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe Quickbooks::Config do
4
+
5
+ #describe "configuration helpers" do
6
+
7
+ #it "should return the supported schema types" do
8
+ #valid_schema_types.should be_an_instance_of(Array)
9
+ #valid_schema_types.include?(:qb).should be_true
10
+ #valid_schema_types.include?(:qbpos).should be_true
11
+ #end
12
+
13
+ #it "should check if a particular schema type is supported" do
14
+ #self.stub!(:schema_type => :qb)
15
+ #valid_schema_type?.should be_true
16
+ #self.stub!(:schema_type => :qbpos)
17
+ #valid_schema_type?.should be_true
18
+ #self.stub!(:schema_type => :doesntexist)
19
+ #valid_schema_type?.should == false
20
+ #end
21
+
22
+ #it "should determine the dtd file path for any supported schema type" do
23
+ #self.stub!(:schema_type => :qb)
24
+ #File.exists?(dtd_file).should be_true
25
+ #self.stub!(:schema_type => :qbpos)
26
+ #File.exists?(dtd_file).should be_true
27
+ #end
28
+
29
+ #it "should determine the namespace for any supported schema type" do
30
+ #self.stub!(:schema_type => :qb)
31
+ #schema_namespace.should be_a_kind_of(Module)
32
+ #self.stub!(:schema_type => :qbpos)
33
+ #schema_namespace.should be_a_kind_of(Module)
34
+ #end
35
+
36
+ #it "should determine the container class for any supported schema type" do
37
+ #self.stub!(:schema_type => :qb)
38
+ #container_class.should == 'QBXML'
39
+ #self.stub!(:schema_type => :qbpos)
40
+ #schema_namespace.should == 'QBPOSXML'
41
+ #end
42
+
43
+ #end
44
+
45
+ #describe "other helpers" do
46
+
47
+ #before :all do
48
+ #@qb_api = Quickbooks::API.new(:qb)
49
+ #@qbpos_api = Quickbooks::API.new(:qbpos)
50
+ #end
51
+
52
+ #it "should return all the cached classes" do
53
+ #self.stub!(:schema_type => :qb)
54
+ #cached_classes.should be_an_instance_of(Array)
55
+ #cached_classes.empty?.should be_false
56
+ #cached_classes.include?(container_class).should be_true
57
+ #self.stub!(:schema_type => :qbpos)
58
+ #cached_classes.should be_an_instance_of(Array)
59
+ #cached_classes.empty?.should be_false
60
+ #cached_classes.include?(container_class).should be_true
61
+ #end
62
+
63
+ #it "should check if a particular class is cached" do
64
+ #self.stub!(:schema_type => :qb)
65
+ #is_cached_class?(Quickbooks::QBXML::QBXML).should be_true
66
+ #self.stub!(:schema_type => :qbpos)
67
+ #is_cached_class?(Quickbooks::QBPOSXML::QBPOSXML).should be_true
68
+ #end
69
+
70
+ #end
71
+
72
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe Quickbooks::Support::Inflection do
4
+
5
+ #before :each do
6
+ #@klass = Nokogiri::XML::NodeSet
7
+ #stub_child = stub(:class => XML_TEXT)
8
+ #@stub_xml_node = stub(:name => "SomeNodeName", :children => [stub_child])
9
+ #@stub_xml_node.stub!(:is_a?).with(anything).and_return(false)
10
+ #@stub_xml_node.stub!(:is_a?).with(XML_ELEMENT).and_return(true)
11
+ #end
12
+
13
+ #it "should convert a class or xml element name to underscored" do
14
+ #underscore(@klass).should == 'node_set'
15
+ #underscore(@stub_xml_node).should == 'some_node_name'
16
+ #end
17
+
18
+ end
@@ -1,20 +1,8 @@
1
1
  require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
2
 
3
- describe Quickbooks::Support::Logger do
3
+ describe Quickbooks::Logger do
4
4
 
5
5
  it "should initialize an ActiveSupport::BufferedLogger" do
6
6
  end
7
7
 
8
- it "should log to a thread specific buffer" do
9
- end
10
-
11
- it "should print the contents of the log buffer" do
12
- end
13
-
14
- it "should indent, unindent, and reset indentation" do
15
- end
16
-
17
- it "should change the format appropriately when the formatter is changed" do
18
- end
19
-
20
8
  end
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe "Monkey Patches" do
4
+
5
+ before :each do
6
+ end
7
+
8
+ #it "should convert a full class name to a simple class name" do
9
+ #@klass.simple_name.should == 'NodeSet'
10
+ #end
11
+ end
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe Quickbooks::Parser::QbxmlBase do
4
+
5
+ it "should have a type conversion map with all qb types" do
6
+ end
7
+
8
+ it "should initialize a qbxml object given an attribute hash" do
9
+ end
10
+
11
+ it "should generate qbxml from a qbxml object" do
12
+ end
13
+
14
+ it "should a hash of attributes for the qbxml object" do
15
+ end
16
+
17
+ it "should return the attribute names of the qbxml class" do
18
+ end
19
+
20
+ it "should return the type map of the qbxml class" do
21
+ end
22
+
23
+ end
@@ -0,0 +1,5 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe Quickbooks::Parser::XMLGeneration do
4
+
5
+ end
@@ -0,0 +1,36 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe Quickbooks::Parser::XMLParsing do
4
+
5
+ #it "should set useful parsing constants" do
6
+ #XML_DOCUMENT.should == Nokogiri::XML::Document
7
+ #XML_NODE_SET.should == Nokogiri::XML::NodeSet
8
+ #XML_NODE.should == Nokogiri::XML::Node
9
+ #XML_ELEMENT.should == Nokogiri::XML::Element
10
+ #XML_COMMENT= Nokogiri::XML::Comment
11
+ #XML_TEXT.should == Nokogiri::XML::Text
12
+ #end
13
+
14
+ #describe "xml parsing helpers" do
15
+
16
+ #before :each do
17
+ #@klass = Nokogiri::XML::NodeSet
18
+ #stub_child = stub(:class => XML_TEXT)
19
+ #@stub_xml_node = stub(:name => "SomeNodeName", :children => [stub_child])
20
+ #@stub_xml_node.stub!(:is_a?).with(anything).and_return(false)
21
+ #@stub_xml_node.stub!(:is_a?).with(XML_ELEMENT).and_return(true)
22
+ #end
23
+
24
+ #it "should check if a node is a leaf node" do
25
+ #is_leaf_node?(@stub_xml_node).should be_true
26
+ #end
27
+
28
+ #end
29
+
30
+ #it "should check if a class is already defined in a particular namespace" do
31
+ #end
32
+
33
+ #it "should cleanup qbxml" do
34
+ #end
35
+
36
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickbooks_api
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 7
10
- version: 0.0.7
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Skryl
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-27 00:00:00 -05:00
18
+ date: 2011-06-30 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -46,22 +46,6 @@ dependencies:
46
46
  version: "0"
47
47
  type: :runtime
48
48
  version_requirements: *id002
49
- - !ruby/object:Gem::Dependency
50
- name: ruby2ruby
51
- prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
53
- none: false
54
- requirements:
55
- - - "="
56
- - !ruby/object:Gem::Version
57
- hash: 29
58
- segments:
59
- - 1
60
- - 2
61
- - 1
62
- version: 1.2.1
63
- type: :runtime
64
- version_requirements: *id003
65
49
  description: A QuickBooks QBXML wrapper for Ruby
66
50
  email: rut216@gmail.com
67
51
  executables: []
@@ -72,27 +56,33 @@ extra_rdoc_files: []
72
56
 
73
57
  files:
74
58
  - lib/quickbooks/api.rb
59
+ - lib/quickbooks/config.rb
75
60
  - lib/quickbooks/dtd_parser.rb
76
- - lib/quickbooks/qbxml_base.rb
61
+ - lib/quickbooks/logger.rb
62
+ - lib/quickbooks/parser/class_builder.rb
63
+ - lib/quickbooks/parser/qbxml_base.rb
64
+ - lib/quickbooks/parser/xml_generation.rb
65
+ - lib/quickbooks/parser/xml_parsing.rb
77
66
  - lib/quickbooks/qbxml_parser.rb
78
- - lib/quickbooks/support/api.rb
79
- - lib/quickbooks/support/class_builder.rb
80
- - lib/quickbooks/support/logger.rb
81
- - lib/quickbooks/support/qbxml.rb
82
- - lib/quickbooks/support.rb
67
+ - lib/quickbooks/support/inflection.rb
68
+ - lib/quickbooks/support/monkey_patches.rb
83
69
  - lib/quickbooks.rb
84
70
  - spec/quickbooks/api_spec.rb
85
71
  - spec/quickbooks/class_builder_spec.rb
72
+ - spec/quickbooks/config_spec.rb
86
73
  - spec/quickbooks/dtd_parser_spec.rb
74
+ - spec/quickbooks/inflection_spec.rb
87
75
  - spec/quickbooks/logger_spec.rb
76
+ - spec/quickbooks/monkey_patches_spec.rb
77
+ - spec/quickbooks/qbxml_base_spec.rb
88
78
  - spec/quickbooks/qbxml_parser_spec.rb
89
- - spec/quickbooks/qbxml_spec.rb
90
79
  - spec/quickbooks/spec_helper.rb
91
- - spec/quickbooks/support_spec.rb
80
+ - spec/quickbooks/xml_generation_spec.rb
81
+ - spec/quickbooks/xml_parsing_spec.rb
92
82
  - xml_schema/qbposxmlops30.xml
93
83
  - xml_schema/qbxmlops70.xml
94
- - ruby_schema/qb/templates/.placeholder
95
- - ruby_schema/qbpos/templates/.placeholder
84
+ - README
85
+ - TODO
96
86
  has_rdoc: true
97
87
  homepage: http://github.com/skryl
98
88
  licenses: []
@@ -1,212 +0,0 @@
1
- # inheritance base for schema classes
2
- class Quickbooks::QbxmlBase
3
- include Quickbooks::Support
4
- include Quickbooks::Support::QBXML
5
-
6
- extend Quickbooks::Support
7
- extend Quickbooks::Support::API
8
-
9
- QB_TYPE_CONVERSION_MAP= {
10
- "AMTTYPE" => lambda {|d| d ? Float(d) : 0.0 },
11
- #"BOOLTYPE" => lambda {|d| d ? (d == 'True' ? true : false) : false },
12
- "BOOLTYPE" => lambda {|d| d ? String(d) : '' },
13
- "DATETIMETYPE" => lambda {|d| d ? Time.parse(d).xmlschema : Time.now.xmlschema },
14
- "DATETYPE" => lambda {|d| d ? Date.parse(d).xmlschema : Date.today.xmlschema },
15
- "ENUMTYPE" => lambda {|d| d ? String(d) : ''},
16
- "FLOATTYPE" => lambda {|d| d ? Float(d) : 0.0},
17
- "GUIDTYPE" => lambda {|d| d ? String(d) : ''},
18
- "IDTYPE" => lambda {|d| d ? String(d) : ''},
19
- "INTTYPE" => lambda {|d| d ? Integer(d) : 0 },
20
- "PERCENTTYPE" => lambda {|d| d ? Float(d) : 0.0 },
21
- "PRICETYPE" => lambda {|d| d ? Float(d) : 0.0 },
22
- "QUANTYPE" => lambda {|d| d ? Integer(d.to_i) : 0 },
23
- "STRTYPE" => lambda {|d| d ? String(d) : ''},
24
- "TIMEINTERVALTYPE" => lambda {|d| d ? String(d) : ''}
25
- }
26
-
27
-
28
- def initialize(params = nil)
29
- return unless params.is_a?(Hash)
30
- params.each do |k,v|
31
- if self.respond_to?(k)
32
- expected_type = self.class.send("#{k}_type")
33
- v = \
34
- case v
35
- when Hash
36
- expected_type.new(v)
37
- when Array
38
- v.inject([]) { |a,i| a << expected_type.new(i) }
39
- else v
40
- end
41
- self.send("#{k}=", v)
42
- end
43
- end
44
- end
45
-
46
-
47
- def to_qbxml
48
- xml_doc = Nokogiri::XML(self.class.xml_template)
49
- root = xml_doc.root
50
- log.debug "to_qbxml#nodes_size: #{root.children.size}"
51
-
52
- # replace all children nodes of the template with populated data nodes
53
- xml_nodes = []
54
- root.children.each do |xml_template|
55
- next unless xml_template.is_a? XML_ELEMENT
56
- attr_name = to_attribute_name(xml_template)
57
- log.debug "to_qbxml#attr_name: #{attr_name}"
58
-
59
- val = self.send(attr_name)
60
- next unless val && !val.blank?
61
-
62
- case val
63
- when Array
64
- xml_nodes += build_qbxml_nodes(xml_template, val)
65
- else
66
- xml_nodes << build_qbxml_node(xml_template, val)
67
- end
68
- log.debug "to_qbxml#val: #{val}"
69
- end
70
-
71
- log.debug "to_qbxml#xml_nodes_size: #{xml_nodes.size}"
72
- root.children = xml_nodes.join('')
73
- root.to_s
74
- end
75
-
76
-
77
- def self.template(recursive = false, use_disk_cache = false, reload = false)
78
- if recursive
79
- @template = (!reload && @template) || load_template(true, use_disk_cache)
80
- else build_template(false)
81
- end
82
- end
83
-
84
-
85
- def self.attribute_names
86
- instance_methods(false).reject { |m| m[-1..-1] == '=' || m =~ /_xml_class/}
87
- end
88
-
89
-
90
- def inner_attributes(parent = nil)
91
- attrs = attributes(false)
92
- values = attrs.values.compact
93
-
94
- if values.empty?
95
- {}
96
- elsif values.first.is_a?(Array)
97
- attributes
98
- elsif values.size > 1
99
- parent.attributes
100
- else
101
- first_val = values.first
102
- if first_val.respond_to?(:inner_attributes)
103
- first_val.inner_attributes(self)
104
- else
105
- parent.attributes
106
- end
107
- end
108
- end
109
-
110
-
111
- def attributes(recursive = true)
112
- self.class.attribute_names.inject({}) do |h, m|
113
- val = self.send(m)
114
- if val
115
- unless recursive
116
- h[m] = val
117
- else
118
- h[m] = nested_attributes(val)
119
- end
120
- end; h
121
- end
122
- end
123
-
124
-
125
- private
126
-
127
- # qbxml conversion
128
-
129
- def nested_attributes(val)
130
- case val
131
- when Quickbooks::QbxmlBase
132
- val.attributes
133
- when Array
134
- val.inject([]) do |a, obj|
135
- case obj
136
- when Quickbooks::QbxmlBase
137
- a << obj.attributes
138
- else a << obj
139
- end
140
- end
141
- else val
142
- end
143
- end
144
-
145
- def build_qbxml_node(node, val)
146
- case val
147
- when Quickbooks::QbxmlBase
148
- val.to_qbxml
149
- else
150
- node.children = val.to_s
151
- node
152
- end
153
- end
154
-
155
- def build_qbxml_nodes(node, val)
156
- val.inject([]) do |a, v|
157
- n = \
158
- case v
159
- when Quickbooks::QbxmlBase
160
- v.to_qbxml
161
- else
162
- clone_qbxml_node(node,v)
163
- end
164
- a << n
165
- end
166
- end
167
-
168
- def clone_qbxml_node(node, val)
169
- n = node.clone
170
- n.children = val.to_s
171
- n
172
- end
173
-
174
- # qbxml class templates
175
-
176
- def self.load_template(recursive = false, use_disk_cache = false)
177
- if use_disk_cache && File.exist?(template_cache_path)
178
- YAML.load(File.read(template_cache_path))
179
- else
180
- log.info "Warning: on disk template is missing, rebuilding..." if use_disk_cache
181
- template = build_template(recursive)
182
- dump_template(template) if use_disk_cache
183
- template
184
- end
185
- end
186
-
187
- def self.build_template(recursive = false)
188
- attribute_names.inject({}) do |h, a|
189
- attr_type = self.send("#{a}_type")
190
- h[a] = (is_cached_class?(attr_type) && recursive) ? attr_type.build_template(true): attr_type.to_s; h
191
- end
192
- end
193
-
194
- def self.dump_template(template)
195
- File.open(template_cache_path, 'w') do |f|
196
- f << template.to_yaml
197
- end
198
- end
199
-
200
- def self.template_cache_path
201
- "#{get_template_cache_path}/#{to_attribute_name(self)}.yml"
202
- end
203
-
204
- def self.schema_type
205
- namespace = self.to_s.split("::")[1]
206
- API::SCHEMA_MAP.find do |k,v|
207
- simple_class_name(v[:namespace]) == namespace
208
- end.first
209
- end
210
-
211
-
212
- end