sell_object 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +146 -0
- data/Rakefile +1 -0
- data/lib/generators/sell_object/install_generator.rb +16 -0
- data/lib/generators/templates/sell_object.rb +5 -0
- data/lib/sell_object/buscape/formatter_proxy.rb +11 -0
- data/lib/sell_object/buscape.rb +43 -0
- data/lib/sell_object/default_mappings.rb +25 -0
- data/lib/sell_object/formatter_proxy.rb +15 -0
- data/lib/sell_object/shopping_uol.rb +30 -0
- data/lib/sell_object/version.rb +3 -0
- data/lib/sell_object/xml_formatter.rb +18 -0
- data/lib/sell_object.rb +59 -0
- data/sell_object.gemspec +28 -0
- data/spec/sell_object/buscape/formatter_proxy_spec.rb +20 -0
- data/spec/sell_object/buscape_spec.rb +81 -0
- data/spec/sell_object/default_mappings_spec.rb +51 -0
- data/spec/sell_object/formatter_proxy_spec.rb +14 -0
- data/spec/sell_object/shopping_uol_spec.rb +16 -0
- data/spec/sell_object/xml_formatter_spec.rb +31 -0
- data/spec/sell_object_spec.rb +120 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/engine_macros.rb +127 -0
- data/spec/support/shared_examples/shopping_engine.rb +76 -0
- data/spec/support/spec_macros.rb +5 -0
- metadata +141 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4275ee21382736fccb2d3d09307970eaca2b679e
|
4
|
+
data.tar.gz: 816e1a34a75ea6124086bfc8445aa1f73a905105
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 143e61bbd203fdfe73fc87f83533b57bc13048ed28980ed49f32af990da86acdd8a5823633f19c8e90a686379af3d05956ef122350582d28c2ad54751468b554
|
7
|
+
data.tar.gz: ef4d0e4f751f60fe67b8957460d6bde6d53bce205636f324af952d2ae6b8cc99c55ae4b5114c1b66bc18f889b1ee09fbec368169063fcb5386051ceaff5c0756
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Daniel Ferraz
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
# SellObject
|
2
|
+
|
3
|
+
By [Ima Bold](http://imabold.com).
|
4
|
+
|
5
|
+
[![Code Climate](https://codeclimate.com/github/imaboldcompany/sell_object.png)](https://codeclimate.com/github/imaboldcompany/sell_object)
|
6
|
+
|
7
|
+
SellObject is an extensible solution to make it easy exporting ruby objects to be used on price comparison shopping engines. The gem adds helper methods that format your objects, making them ready to be consumable by the supported price comparison engines.
|
8
|
+
|
9
|
+
Currently, the following shopping engines are supported:
|
10
|
+
|
11
|
+
* Shopping UOL (Brazil)
|
12
|
+
* Buscape (Brazil)
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'sell_object'
|
20
|
+
```
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install sell_object
|
29
|
+
|
30
|
+
After you install SellObject and add it to your Gemfile, you need to run the generator:
|
31
|
+
|
32
|
+
$ rails generate sell_object:install
|
33
|
+
|
34
|
+
This will add the SellObject initializer into your Rails config/initializers folder.
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
### Setting up the class
|
39
|
+
|
40
|
+
Suppose you have a class `Product` and want to make its objects sellable through Shopping UOL.
|
41
|
+
You do that by using `sell_through` as shown below:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
class Product
|
45
|
+
include SellObject
|
46
|
+
|
47
|
+
sell_through :shopping_uol
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
After that, to export a given `product` object into a consumable format used in Shopping UOL, just call:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
product.to_shopping_uol
|
55
|
+
```
|
56
|
+
|
57
|
+
In this case, this will generate the XML used by Shopping UOL in its search engine, based on the `product` attributes.
|
58
|
+
|
59
|
+
Now, take `products` as collection of `Product` and you want to export all the collection into a consumable format used in Shopping UOL. All you have to do is use the class method passing the `products` collection, as shown:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
Product.to_shopping_uol products
|
63
|
+
```
|
64
|
+
|
65
|
+
The same approach works for all the other supported shopping engines.
|
66
|
+
|
67
|
+
### Mapping the attributes
|
68
|
+
|
69
|
+
SellObject comes with a default mapping to be applied through the exporting process. Continuing the Shopping UOL example, the mapping is used to grab the `product` attributes and build the XML tags. The default mapping is defined in the following module:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
module SellObject
|
73
|
+
module DefaultMappings
|
74
|
+
def self.shopping_uol
|
75
|
+
{
|
76
|
+
:CODIGO => :id,
|
77
|
+
:DESCRICAO => :description,
|
78
|
+
:PRECO => :price,
|
79
|
+
:URL => :url,
|
80
|
+
:URL_IMAGEM => :image_url,
|
81
|
+
:DEPARTAMENTO => :category
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
```
|
87
|
+
If you want to use the default mapping, just make sure that the object responds to the required methods. In our example, `product` would have to respond to `:id`, `:description`, `:price` and so forth.
|
88
|
+
|
89
|
+
If you want to create your own mapping, you can define a module named with the object's class name + 'Mappings'. For our `product` example, we could define like this:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
module SellObject
|
93
|
+
module ProductMappings
|
94
|
+
def self.shopping_uol
|
95
|
+
{
|
96
|
+
:CODIGO => :code,
|
97
|
+
:DESCRICAO => :details,
|
98
|
+
:URL => :web_page
|
99
|
+
}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
104
|
+
In this case, `product` would have to respond to `:code`, `:details` and `:web_page`. Note that we didn't overwrite all the attribute mappings. The leftovers will fall back to the default mapping. So in this example, `product` would still have to respond to the `:price`, `:image_url` and `:category` methods.
|
105
|
+
|
106
|
+
When defining you own mappings, you can easily unit test them using Test::Unit, Rspec or other testing solutions.
|
107
|
+
|
108
|
+
### Store name
|
109
|
+
|
110
|
+
Some shopping engines require a store name to be included in the final output after the exporting process is over. You can define the store name globally in the SellObject initializer, for example:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
SellObject.setup do |config|
|
114
|
+
config.store_name = 'Ima Bold Store'
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
If you want to set the store name dynamically, you can pass it to the exporting methods, for example:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
Product.to_buscape products, 'Ima Bold Store'
|
122
|
+
|
123
|
+
product.to_buscape 'Ima Bold Store'
|
124
|
+
```
|
125
|
+
|
126
|
+
If you do not pass the store name neither set it up in the initializer, an error is going to be raised when calling those methods for engines that require a store name.
|
127
|
+
|
128
|
+
Here's the list of shopping engines that require a store name for the exporting process:
|
129
|
+
|
130
|
+
* Buscape (Brazil)
|
131
|
+
|
132
|
+
## Contributing
|
133
|
+
|
134
|
+
Questions or problems? Please post them on the [issue tracker](https://github.com/imaboldcompany/sell_object/issues).
|
135
|
+
|
136
|
+
You can contribute by doing the following:
|
137
|
+
|
138
|
+
1. Fork it
|
139
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
140
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
141
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
142
|
+
5. Create new Pull Request
|
143
|
+
|
144
|
+
## License
|
145
|
+
|
146
|
+
MIT License.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module SellObject
|
5
|
+
module Generators
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path("../../templates", __FILE__)
|
8
|
+
|
9
|
+
desc "Creates a SellObject initializer."
|
10
|
+
|
11
|
+
def copy_initializer
|
12
|
+
template "sell_object.rb", "config/initializers/sell_object.rb"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module SellObject
|
2
|
+
module Buscape
|
3
|
+
class FormatterProxy < SellObject::FormatterProxy
|
4
|
+
def preco(target_method)
|
5
|
+
target_value = target.send target_method
|
6
|
+
raise ArgumentError, "method expects a number, got #{target_value.class.name}: #{target_value}" unless target_value.is_a? Numeric
|
7
|
+
('%.2f' % target_value).gsub '.', ','
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module SellObject
|
2
|
+
module Buscape
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.wrap_xml(elements, store_name = nil)
|
8
|
+
store_name ||= SellObject::Config.store_name
|
9
|
+
raise ArgumentError, 'No store name found (nil). You have to either pass it as an argument or set it up in SellObject::Config' if store_name.nil?
|
10
|
+
%Q{
|
11
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
12
|
+
<!-- #{timestamp} -->
|
13
|
+
<#{store_name}>
|
14
|
+
<produtos>
|
15
|
+
#{elements}
|
16
|
+
</produtos>
|
17
|
+
</#{store_name}>
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.timestamp
|
22
|
+
now = Time.now
|
23
|
+
zone_diff = now.strftime("%z").to_i / 100
|
24
|
+
time = now.strftime "%Y-%m-%dT%H:%M:%SGMT#{'+' if zone_diff >= 0}#{zone_diff}"
|
25
|
+
"Generated at #{time}"
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
# Class methods added on inclusion
|
30
|
+
|
31
|
+
def to_buscape(objects, store_name = nil)
|
32
|
+
elements = objects.map {|obj| SellObject::XmlFormatter.format obj, :buscape, :produto, SellObject::Buscape::FormatterProxy.new(obj) }.join ''
|
33
|
+
SellObject::Buscape.wrap_xml elements, store_name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Instance methods added on inclusion
|
38
|
+
|
39
|
+
def to_buscape(store_name = nil)
|
40
|
+
self.class.to_buscape [self], store_name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SellObject
|
2
|
+
module DefaultMappings
|
3
|
+
def self.shopping_uol
|
4
|
+
{
|
5
|
+
:CODIGO => :id,
|
6
|
+
:DESCRICAO => :description,
|
7
|
+
:PRECO => :price,
|
8
|
+
:URL => :url,
|
9
|
+
:URL_IMAGEM => :image_url,
|
10
|
+
:DEPARTAMENTO => :category
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.buscape
|
15
|
+
{
|
16
|
+
:id_oferta => :id,
|
17
|
+
:descricao => :description,
|
18
|
+
:preco => :price,
|
19
|
+
:link_prod => :url,
|
20
|
+
:imagem => :image_url,
|
21
|
+
:categoria => :category
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SellObject
|
2
|
+
module ShoppingUol
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.wrap_xml(elements)
|
8
|
+
%Q{
|
9
|
+
<?xml version="1.0" encoding="iso-8859-1" ?>
|
10
|
+
<PRODUTOS>
|
11
|
+
#{elements}
|
12
|
+
</PRODUTOS>
|
13
|
+
}
|
14
|
+
end
|
15
|
+
module ClassMethods
|
16
|
+
# Class methods added on inclusion
|
17
|
+
|
18
|
+
def to_shopping_uol(objects)
|
19
|
+
elements = objects.map {|obj| SellObject::XmlFormatter.format obj, :shopping_uol, :PRODUTO }.join ''
|
20
|
+
SellObject::ShoppingUol.wrap_xml elements
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Instance methods added on inclusion
|
25
|
+
|
26
|
+
def to_shopping_uol
|
27
|
+
self.class.to_shopping_uol [self]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module SellObject
|
4
|
+
module XmlFormatter
|
5
|
+
def self.format(obj, engine, xml_root, formatter_proxy = nil)
|
6
|
+
mapping = SellObject.mapping_for obj, engine
|
7
|
+
formatter_proxy ||= SellObject::FormatterProxy.new obj
|
8
|
+
xml_builder = Nokogiri::XML::Builder.new do |xml|
|
9
|
+
xml.send xml_root do
|
10
|
+
mapping.each do |tag, mapped_method|
|
11
|
+
xml.send tag, formatter_proxy.send(tag, mapped_method)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
xml_builder.doc.root.to_xml
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/sell_object.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'sell_object/version'
|
2
|
+
require 'sell_object/default_mappings'
|
3
|
+
require 'sell_object/xml_formatter'
|
4
|
+
require 'sell_object/formatter_proxy'
|
5
|
+
require 'sell_object/buscape/formatter_proxy'
|
6
|
+
require 'sell_object/shopping_uol'
|
7
|
+
require 'sell_object/buscape'
|
8
|
+
|
9
|
+
module SellObject
|
10
|
+
def self.included(base)
|
11
|
+
base.extend ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.setup
|
15
|
+
yield SellObject::Config
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.supported_engines
|
19
|
+
%w(shopping_uol buscape)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.validate_engine(engine)
|
23
|
+
raise ArgumentError.new("invalid shopping engine #{engine}") unless supported_engines.include? engine.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.mapping_for(obj, engine)
|
27
|
+
validate_engine engine
|
28
|
+
begin
|
29
|
+
custom_mappings_hash = eval "SellObject::#{obj.class.name}Mappings.#{engine}"
|
30
|
+
rescue
|
31
|
+
custom_mappings_hash = {}
|
32
|
+
end
|
33
|
+
default_mappings_hash = SellObject::DefaultMappings.send engine
|
34
|
+
default_mappings_hash.merge custom_mappings_hash
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def sell_through(*engines)
|
39
|
+
raise ArgumentError.new('must pass at least one shopping engine') if engines.empty?
|
40
|
+
engines.each do |engine|
|
41
|
+
SellObject.validate_engine engine
|
42
|
+
camelized_engine = engine.to_s.split('_').map {|w| w.capitalize}.join
|
43
|
+
include eval("SellObject::#{camelized_engine}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module Config
|
49
|
+
@@store_name = nil
|
50
|
+
|
51
|
+
def self.store_name
|
52
|
+
@@store_name
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.store_name=(name)
|
56
|
+
@@store_name = name.gsub(/ +/, '_')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/sell_object.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sell_object/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sell_object"
|
8
|
+
spec.version = SellObject::VERSION
|
9
|
+
spec.authors = ["Daniel Ferraz"]
|
10
|
+
spec.email = ["d.ferrazm@gmail.com"]
|
11
|
+
spec.description = %q{Extensible solution to make it easy to export ruby objects to be used on price comparison shopping engines}
|
12
|
+
spec.summary = %q{Sell your Ruby on Rails objects on price comparison shopping engines}
|
13
|
+
spec.homepage = "http://github.com/imaboldcompany/sell_object"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 1.9.3p125'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
|
27
|
+
spec.add_dependency "nokogiri"
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SellObject::Buscape::FormatterProxy do
|
4
|
+
let(:target_object) { double price: 10.5, description: 'Lorem ipsum' }
|
5
|
+
let(:formatter) { SellObject::Buscape::FormatterProxy.new target_object }
|
6
|
+
|
7
|
+
it 'extends from SellObject::FormatterProxy' do
|
8
|
+
expect(formatter.is_a? SellObject::FormatterProxy).to be_true
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#preco' do
|
12
|
+
it 'formats the value from the target object to include two decimal cases with comma as sepparator' do
|
13
|
+
expect(formatter.preco :price).to eq '10,50'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns an error when the value from the target object is not a number' do
|
17
|
+
expect { formatter.preco :description }.to raise_error ArgumentError, 'method expects a number, got String: Lorem ipsum'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include EngineMacros::Buscape
|
3
|
+
|
4
|
+
class Product
|
5
|
+
include SellObject::Buscape
|
6
|
+
end
|
7
|
+
|
8
|
+
describe SellObject::Buscape do
|
9
|
+
it_behaves_like 'shopping_engine', :buscape
|
10
|
+
|
11
|
+
context 'still behaving as shopping_engine' do
|
12
|
+
let(:product) { Product.new }
|
13
|
+
|
14
|
+
before do
|
15
|
+
SellObject::XmlFormatter.stub(:format).and_return 'xml element'
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'class_methods' do
|
19
|
+
describe "to_buscape" do
|
20
|
+
context 'passing the store name' do
|
21
|
+
it 'generates the XML with the given store name as root' do
|
22
|
+
expect(remove_xml_noise Product.to_buscape([product], 'great')).to match /<great><produtos>.*<\/produtos><\/great>/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'instance methods' do
|
29
|
+
describe "to_buscape" do
|
30
|
+
context 'passing the store name' do
|
31
|
+
it 'generates the XML with the given store name as root' do
|
32
|
+
expect(remove_xml_noise product.to_buscape('great')).to match /<great><produtos>.*<\/produtos><\/great>/
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#wrap_xml' do
|
40
|
+
before do
|
41
|
+
SellObject::Config.stub(:store_name).and_return 'awesome'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'inserts the timestamp into the xml' do
|
45
|
+
timestamp = Time.now.to_s
|
46
|
+
subject.stub(:timestamp).and_return '2014-03-29 13:28:32 -0300'
|
47
|
+
expect(subject.wrap_xml 'xml elements').to include '<!-- 2014-03-29 13:28:32 -0300 -->'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'inserts the given elements inside the <produtos> tag' do
|
51
|
+
expect(remove_xml_noise subject.wrap_xml('xml elements')).to include '<produtos>xml elements</produtos>'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'wraps the <produtos> tag with the store name set up in config' do
|
55
|
+
SellObject::Config.stub(:store_name).and_return 'awesome'
|
56
|
+
expect(remove_xml_noise subject.wrap_xml('elements')).to match /<awesome><produtos>.*<\/produtos><\/awesome>/
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'raises an error if theres no store name set up' do
|
60
|
+
SellObject::Config.stub(:store_name).and_return nil
|
61
|
+
expect { subject.wrap_xml 'elements' }.to raise_error ArgumentError, 'No store name found (nil). You have to either pass it as an argument or set it up in SellObject::Config'
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when passing the store name as an argument' do
|
65
|
+
it 'wraps the <produtos> tag with the given store name' do
|
66
|
+
expect(remove_xml_noise subject.wrap_xml('elements', 'boring')).to match /<boring><produtos>.*<\/produtos><\/boring>/
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#timestamp' do
|
72
|
+
it 'returns the time now correctly formatted' do
|
73
|
+
Time.stub(:now).and_return Time.new(2014,3,28,10,42,48,'-03:00')
|
74
|
+
expect(subject.timestamp).to eq 'Generated at 2014-03-28T10:42:48GMT-3'
|
75
|
+
Time.stub(:now).and_return Time.new(2011,1,4,17,22,58,'+01:00')
|
76
|
+
expect(subject.timestamp).to eq 'Generated at 2011-01-04T17:22:58GMT+1'
|
77
|
+
Time.stub(:now).and_return Time.new(2011,1,4,17,22,58,'+00:00')
|
78
|
+
expect(subject.timestamp).to eq 'Generated at 2011-01-04T17:22:58GMT+0'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SellObject::DefaultMappings do
|
4
|
+
describe '#shopping_uol' do
|
5
|
+
let(:mapping) { subject.shopping_uol }
|
6
|
+
|
7
|
+
it 'maps :CODIGO to :id' do
|
8
|
+
expect(mapping[:CODIGO]).to eq :id
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'maps :DESCRICAO to :description' do
|
12
|
+
expect(mapping[:DESCRICAO]).to eq :description
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'maps :PRECO to :price' do
|
16
|
+
expect(mapping[:PRECO]).to eq :price
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'maps :URL to :url' do
|
20
|
+
expect(mapping[:URL]).to eq :url
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#buscape' do
|
25
|
+
let(:mapping) { subject.buscape }
|
26
|
+
|
27
|
+
it 'maps :id_oferta to :id' do
|
28
|
+
expect(mapping[:id_oferta]).to eq :id
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'maps :descricao to :description' do
|
32
|
+
expect(mapping[:descricao]).to eq :description
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'maps :preco to :price' do
|
36
|
+
expect(mapping[:preco]).to eq :price
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'maps :link_prod to :url' do
|
40
|
+
expect(mapping[:link_prod]).to eq :url
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'maps :imagem to :image_url' do
|
44
|
+
expect(mapping[:imagem]).to eq :image_url
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'maps :categoria to :category' do
|
48
|
+
expect(mapping[:categoria]).to eq :category
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SellObject::FormatterProxy do
|
4
|
+
let(:target_object) { double description: 'Lorem ipsum' }
|
5
|
+
let(:formatter) { SellObject::FormatterProxy.new target_object }
|
6
|
+
|
7
|
+
it 'sets the target object on initialization' do
|
8
|
+
expect(formatter.target).to eq target_object
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'delegates any method missing to the target method' do
|
12
|
+
expect(formatter.foo :description).to eq 'Lorem ipsum'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include EngineMacros::ShoppingUol
|
3
|
+
|
4
|
+
class Product
|
5
|
+
include SellObject::ShoppingUol
|
6
|
+
end
|
7
|
+
|
8
|
+
describe SellObject::ShoppingUol do
|
9
|
+
it_behaves_like 'shopping_engine', :shopping_uol
|
10
|
+
|
11
|
+
describe '#wrap_xml' do
|
12
|
+
it 'inserts the given elements inside the <PRODUTOS> tag' do
|
13
|
+
expect(remove_xml_noise subject.wrap_xml('xml elements')).to include '<PRODUTOS>xml elements</PRODUTOS>'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SellObject::XmlFormatter do
|
4
|
+
describe '#format' do
|
5
|
+
let(:target_object) { double some_value: 'some value' }
|
6
|
+
|
7
|
+
before do
|
8
|
+
SellObject.stub(:mapping_for).with(target_object, :foo).and_return({some_tag: :some_value})
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'formats an object into a xml element based on its mapping, given an engine and a xml root' do
|
12
|
+
expect(remove_xml_noise subject.format(target_object, :foo, :xml_root)).to eq remove_xml_noise %q{
|
13
|
+
<xml_root>
|
14
|
+
<some_tag>some value</some_tag>
|
15
|
+
</xml_root>
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'passing a formatter proxy' do
|
20
|
+
let(:proxy) { double some_tag: 'proxied value' }
|
21
|
+
|
22
|
+
it 'uses the proxy on the format process' do
|
23
|
+
expect(remove_xml_noise subject.format(target_object, :foo, :xml_root, proxy)).to eq remove_xml_noise %q{
|
24
|
+
<xml_root>
|
25
|
+
<some_tag>proxied value</some_tag>
|
26
|
+
</xml_root>
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SellObject do
|
4
|
+
context 'on inclusion' do
|
5
|
+
before do
|
6
|
+
class TargetClass
|
7
|
+
extend SellObject::ClassMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
Object.send :remove_const, :TargetClass
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'makes the target class extend SellObject::ClassMethods' do
|
16
|
+
expect(TargetClass.is_a? SellObject::ClassMethods).to be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'ClassMethods' do
|
20
|
+
describe '#sell_through' do
|
21
|
+
context 'passing invalid arguments' do
|
22
|
+
it 'raises ArgumentError with an invalid engine' do
|
23
|
+
expect { TargetClass.sell_through :foo }.to raise_error ArgumentError, 'invalid shopping engine foo'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'raises ArgumentError with a blank arguments' do
|
27
|
+
expect { TargetClass.sell_through }.to raise_error ArgumentError, 'must pass at least one shopping engine'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'buscape' do
|
32
|
+
it 'includes the module SellObject::Buscape in the target class' do
|
33
|
+
TargetClass.sell_through :buscape
|
34
|
+
expect(TargetClass.included_modules).to include SellObject::Buscape
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'shopping_uol' do
|
39
|
+
it 'includes the module SellObject::ShoppingUol in the target class' do
|
40
|
+
TargetClass.sell_through :shopping_uol
|
41
|
+
expect(TargetClass.included_modules).to include SellObject::ShoppingUol
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#supported_engines' do
|
49
|
+
it 'returns the supported shopping engines array' do
|
50
|
+
expect(subject.supported_engines).to match_array %w(shopping_uol buscape)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#setup' do
|
55
|
+
it 'yields the SellObject::Config module' do
|
56
|
+
config_module = nil
|
57
|
+
subject.setup do |config|
|
58
|
+
config_module = config
|
59
|
+
end
|
60
|
+
expect(config_module.name).to eq 'SellObject::Config'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#mapping_for' do
|
65
|
+
before do
|
66
|
+
SellObject.stub(:supported_engines).and_return %w(bar)
|
67
|
+
SellObject::DefaultMappings.stub(:bar).and_return({t1: :v1, t2: :v2})
|
68
|
+
|
69
|
+
class TargetObject
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
after do
|
74
|
+
Object.send :remove_const, :TargetObject
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'raises an error if the given engine is invalid' do
|
78
|
+
expect { subject.mapping_for TargetObject.new, :foo }.to raise_error ArgumentError, 'invalid shopping engine foo'
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when there\s no custom mapping defined' do
|
82
|
+
it 'returns the default mapping hash for the given object' do
|
83
|
+
expect(subject.mapping_for TargetObject.new, :bar).to eq({t1: :v1, t2: :v2})
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when there\s a custom mapping defined' do
|
88
|
+
before do
|
89
|
+
module SellObject::TargetObjectMappings
|
90
|
+
def self.bar
|
91
|
+
{t2: :v2_custom, t3: :v3}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
after do
|
97
|
+
SellObject.send :remove_const, :TargetObjectMappings
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'returns the default mapping hash merged with the custom mapping for the given object' do
|
101
|
+
expect(subject.mapping_for TargetObject.new, :bar).to eq({t1: :v1, t2: :v2_custom, t3: :v3})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'Config' do
|
107
|
+
let(:subject) { SellObject::Config }
|
108
|
+
|
109
|
+
describe '#store_name' do
|
110
|
+
it 'initializes it with nil' do
|
111
|
+
expect(subject.store_name).to be_nil
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'underscores the given assigned name' do
|
115
|
+
subject.store_name = 'My Store Name'
|
116
|
+
expect(subject.store_name).to eq 'My_Store_Name'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'sell_object'
|
2
|
+
|
3
|
+
ENV["RAILS_ENV"] ||= 'test'
|
4
|
+
|
5
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
6
|
+
# in spec/support/ and its subdirectories.
|
7
|
+
Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.include SpecMacros
|
11
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module EngineMacros
|
2
|
+
module Buscape
|
3
|
+
DEFAULT_MAPPING_FIXTURE_ONE = %q{
|
4
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
5
|
+
<awesome_store>
|
6
|
+
<produtos>
|
7
|
+
<produto>
|
8
|
+
<id_oferta>PR1</id_oferta>
|
9
|
+
<descricao>Some lame product</descricao>
|
10
|
+
<preco>10,50</preco>
|
11
|
+
<link_prod>http://example.com/lame-product</link_prod>
|
12
|
+
<imagem>http://example.com/images/lame-product.png</imagem>
|
13
|
+
<categoria>Electronics</categoria>
|
14
|
+
</produto>
|
15
|
+
</produtos>
|
16
|
+
</awesome_store>
|
17
|
+
}
|
18
|
+
|
19
|
+
DEFAULT_MAPPING_FIXTURE_MANY = %q{
|
20
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
21
|
+
<awesome_store>
|
22
|
+
<produtos>
|
23
|
+
<produto>
|
24
|
+
<id_oferta>PR1</id_oferta>
|
25
|
+
<descricao>Some lame product</descricao>
|
26
|
+
<preco>10,50</preco>
|
27
|
+
<link_prod>http://example.com/lame-product</link_prod>
|
28
|
+
<imagem>http://example.com/images/lame-product.png</imagem>
|
29
|
+
<categoria>Electronics</categoria>
|
30
|
+
</produto>
|
31
|
+
<produto>
|
32
|
+
<id_oferta>PR2</id_oferta>
|
33
|
+
<descricao>Some boring product</descricao>
|
34
|
+
<preco>7,00</preco>
|
35
|
+
<link_prod>http://example.com/boring-product</link_prod>
|
36
|
+
<imagem>http://example.com/images/boring-product.png</imagem>
|
37
|
+
<categoria>Kitchenware</categoria>
|
38
|
+
</produto>
|
39
|
+
</produtos>
|
40
|
+
</awesome_store>
|
41
|
+
}
|
42
|
+
|
43
|
+
CUSTOM_MAPPING_FIXTURE_MANY = %q{
|
44
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
45
|
+
<awesome_store>
|
46
|
+
<produtos>
|
47
|
+
<produto>
|
48
|
+
<id_oferta>PR1</id_oferta>
|
49
|
+
<descricao>My custom lame product description</descricao>
|
50
|
+
<preco>10,50</preco>
|
51
|
+
<link_prod>http://example.com/custom-lame-product</link_prod>
|
52
|
+
<imagem>http://example.com/images/lame-product.png</imagem>
|
53
|
+
<categoria>Electronics</categoria>
|
54
|
+
</produto>
|
55
|
+
<produto>
|
56
|
+
<id_oferta>PR2</id_oferta>
|
57
|
+
<descricao>My custom boring product description</descricao>
|
58
|
+
<preco>7,00</preco>
|
59
|
+
<link_prod>http://example.com/custom-boring-product</link_prod>
|
60
|
+
<imagem>http://example.com/images/boring-product.png</imagem>
|
61
|
+
<categoria>Kitchenware</categoria>
|
62
|
+
</produto>
|
63
|
+
</produtos>
|
64
|
+
</awesome_store>
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
module ShoppingUol
|
69
|
+
DEFAULT_MAPPING_FIXTURE_ONE = %q{
|
70
|
+
<?xml version="1.0" encoding="iso-8859-1" ?>
|
71
|
+
<PRODUTOS>
|
72
|
+
<PRODUTO>
|
73
|
+
<CODIGO>PR1</CODIGO>
|
74
|
+
<DESCRICAO>Some lame product</DESCRICAO>
|
75
|
+
<PRECO>10.5</PRECO>
|
76
|
+
<URL>http://example.com/lame-product</URL>
|
77
|
+
<URL_IMAGEM>http://example.com/images/lame-product.png</URL_IMAGEM>
|
78
|
+
<DEPARTAMENTO>Electronics</DEPARTAMENTO>
|
79
|
+
</PRODUTO>
|
80
|
+
</PRODUTOS>
|
81
|
+
}
|
82
|
+
|
83
|
+
DEFAULT_MAPPING_FIXTURE_MANY = %q{
|
84
|
+
<?xml version="1.0" encoding="iso-8859-1" ?>
|
85
|
+
<PRODUTOS>
|
86
|
+
<PRODUTO>
|
87
|
+
<CODIGO>PR1</CODIGO>
|
88
|
+
<DESCRICAO>Some lame product</DESCRICAO>
|
89
|
+
<PRECO>10.5</PRECO>
|
90
|
+
<URL>http://example.com/lame-product</URL>
|
91
|
+
<URL_IMAGEM>http://example.com/images/lame-product.png</URL_IMAGEM>
|
92
|
+
<DEPARTAMENTO>Electronics</DEPARTAMENTO>
|
93
|
+
</PRODUTO>
|
94
|
+
<PRODUTO>
|
95
|
+
<CODIGO>PR2</CODIGO>
|
96
|
+
<DESCRICAO>Some boring product</DESCRICAO>
|
97
|
+
<PRECO>7</PRECO>
|
98
|
+
<URL>http://example.com/boring-product</URL>
|
99
|
+
<URL_IMAGEM>http://example.com/images/boring-product.png</URL_IMAGEM>
|
100
|
+
<DEPARTAMENTO>Kitchenware</DEPARTAMENTO>
|
101
|
+
</PRODUTO>
|
102
|
+
</PRODUTOS>
|
103
|
+
}
|
104
|
+
|
105
|
+
CUSTOM_MAPPING_FIXTURE_MANY = %q{
|
106
|
+
<?xml version="1.0" encoding="iso-8859-1" ?>
|
107
|
+
<PRODUTOS>
|
108
|
+
<PRODUTO>
|
109
|
+
<CODIGO>PR1</CODIGO>
|
110
|
+
<DESCRICAO>My custom lame product description</DESCRICAO>
|
111
|
+
<PRECO>10.5</PRECO>
|
112
|
+
<URL>http://example.com/custom-lame-product</URL>
|
113
|
+
<URL_IMAGEM>http://example.com/images/lame-product.png</URL_IMAGEM>
|
114
|
+
<DEPARTAMENTO>Electronics</DEPARTAMENTO>
|
115
|
+
</PRODUTO>
|
116
|
+
<PRODUTO>
|
117
|
+
<CODIGO>PR2</CODIGO>
|
118
|
+
<DESCRICAO>My custom boring product description</DESCRICAO>
|
119
|
+
<PRECO>7</PRECO>
|
120
|
+
<URL>http://example.com/custom-boring-product</URL>
|
121
|
+
<URL_IMAGEM>http://example.com/images/boring-product.png</URL_IMAGEM>
|
122
|
+
<DEPARTAMENTO>Kitchenware</DEPARTAMENTO>
|
123
|
+
</PRODUTO>
|
124
|
+
</PRODUTOS>
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
shared_examples_for 'shopping_engine' do |engine|
|
2
|
+
camelized_engine = engine.to_s.split('_').map {|w| w.capitalize}.join
|
3
|
+
|
4
|
+
let(:macros) { eval("EngineMacros::#{camelized_engine}") }
|
5
|
+
let(:lame_product) { Product.new }
|
6
|
+
let(:boring_product) { Product.new }
|
7
|
+
let(:products) { [lame_product, boring_product] }
|
8
|
+
|
9
|
+
before do
|
10
|
+
lame_product.stub(:id).and_return 'PR1'
|
11
|
+
lame_product.stub(:description).and_return 'Some lame product'
|
12
|
+
lame_product.stub(:price).and_return 10.5
|
13
|
+
lame_product.stub(:category).and_return 'Electronics'
|
14
|
+
lame_product.stub(:url).and_return 'http://example.com/lame-product'
|
15
|
+
lame_product.stub(:image_url).and_return 'http://example.com/images/lame-product.png'
|
16
|
+
|
17
|
+
boring_product.stub(:id).and_return 'PR2'
|
18
|
+
boring_product.stub(:description).and_return 'Some boring product'
|
19
|
+
boring_product.stub(:price).and_return 7
|
20
|
+
boring_product.stub(:category).and_return 'Kitchenware'
|
21
|
+
boring_product.stub(:url).and_return 'http://example.com/boring-product'
|
22
|
+
boring_product.stub(:image_url).and_return 'http://example.com/images/boring-product.png'
|
23
|
+
|
24
|
+
SellObject::Config.stub(:store_name).and_return 'awesome_store'
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'class_methods' do
|
28
|
+
describe "#to_#{engine}" do
|
29
|
+
context 'using default mappings' do
|
30
|
+
it 'generates the XML accordingly with all the objects attributes' do
|
31
|
+
expect(remove_xml_noise Product.send("to_#{engine}", products)).to eq remove_xml_noise macros::DEFAULT_MAPPING_FIXTURE_MANY
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'using custom mappings' do
|
36
|
+
before do
|
37
|
+
lame_product.stub(:custom_description).and_return 'My custom lame product description'
|
38
|
+
lame_product.stub(:custom_url).and_return 'http://example.com/custom-lame-product'
|
39
|
+
boring_product.stub(:custom_description).and_return 'My custom boring product description'
|
40
|
+
boring_product.stub(:custom_url).and_return 'http://example.com/custom-boring-product'
|
41
|
+
|
42
|
+
module SellObject::ProductMappings
|
43
|
+
def self.buscape
|
44
|
+
{ :descricao => :custom_description, :link_prod => :custom_url }
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.shopping_uol
|
48
|
+
{ :DESCRICAO => :custom_description, :URL => :custom_url }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
after do
|
54
|
+
SellObject.send :remove_const, :ProductMappings
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'generates the XML accordingly with all the objects attributes and the custom mappings' do
|
58
|
+
expect(remove_xml_noise Product.send("to_#{engine}", products)).to eq remove_xml_noise macros::CUSTOM_MAPPING_FIXTURE_MANY
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'instance methods' do
|
65
|
+
describe "#to_#{engine}" do
|
66
|
+
it 'generates the XML accordingly with the object attributes' do
|
67
|
+
expect(remove_xml_noise lame_product.send("to_#{engine}")).to eq remove_xml_noise macros::DEFAULT_MAPPING_FIXTURE_ONE
|
68
|
+
end
|
69
|
+
|
70
|
+
# it "calls the #to_#{engine} class method passing the instance wrapped in an array" do
|
71
|
+
# Product.should_receive(:"to_#{engine}").with [lame_product]
|
72
|
+
# lame_product.send "to_#{engine}"
|
73
|
+
# end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sell_object
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Ferraz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: nokogiri
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Extensible solution to make it easy to export ruby objects to be used
|
70
|
+
on price comparison shopping engines
|
71
|
+
email:
|
72
|
+
- d.ferrazm@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- .rspec
|
79
|
+
- CHANGELOG.md
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE.txt
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- lib/generators/sell_object/install_generator.rb
|
85
|
+
- lib/generators/templates/sell_object.rb
|
86
|
+
- lib/sell_object.rb
|
87
|
+
- lib/sell_object/buscape.rb
|
88
|
+
- lib/sell_object/buscape/formatter_proxy.rb
|
89
|
+
- lib/sell_object/default_mappings.rb
|
90
|
+
- lib/sell_object/formatter_proxy.rb
|
91
|
+
- lib/sell_object/shopping_uol.rb
|
92
|
+
- lib/sell_object/version.rb
|
93
|
+
- lib/sell_object/xml_formatter.rb
|
94
|
+
- sell_object.gemspec
|
95
|
+
- spec/sell_object/buscape/formatter_proxy_spec.rb
|
96
|
+
- spec/sell_object/buscape_spec.rb
|
97
|
+
- spec/sell_object/default_mappings_spec.rb
|
98
|
+
- spec/sell_object/formatter_proxy_spec.rb
|
99
|
+
- spec/sell_object/shopping_uol_spec.rb
|
100
|
+
- spec/sell_object/xml_formatter_spec.rb
|
101
|
+
- spec/sell_object_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
- spec/support/engine_macros.rb
|
104
|
+
- spec/support/shared_examples/shopping_engine.rb
|
105
|
+
- spec/support/spec_macros.rb
|
106
|
+
homepage: http://github.com/imaboldcompany/sell_object
|
107
|
+
licenses:
|
108
|
+
- MIT
|
109
|
+
metadata: {}
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 1.9.3p125
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 2.0.14
|
127
|
+
signing_key:
|
128
|
+
specification_version: 4
|
129
|
+
summary: Sell your Ruby on Rails objects on price comparison shopping engines
|
130
|
+
test_files:
|
131
|
+
- spec/sell_object/buscape/formatter_proxy_spec.rb
|
132
|
+
- spec/sell_object/buscape_spec.rb
|
133
|
+
- spec/sell_object/default_mappings_spec.rb
|
134
|
+
- spec/sell_object/formatter_proxy_spec.rb
|
135
|
+
- spec/sell_object/shopping_uol_spec.rb
|
136
|
+
- spec/sell_object/xml_formatter_spec.rb
|
137
|
+
- spec/sell_object_spec.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
- spec/support/engine_macros.rb
|
140
|
+
- spec/support/shared_examples/shopping_engine.rb
|
141
|
+
- spec/support/spec_macros.rb
|