simpex 0.0.1
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.
- data/.bundle/config +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +14 -0
- data/Rakefile +22 -0
- data/lib/simpex.rb +6 -0
- data/lib/simpex/catalog.rb +12 -0
- data/lib/simpex/factory.rb +37 -0
- data/lib/simpex/impex_result.rb +98 -0
- data/lib/simpex/type.rb +100 -0
- data/lib/simpex/type_entry.rb +94 -0
- data/lib/simpex/version.rb +4 -0
- data/readme.textile +82 -0
- data/simpex.gemspec +26 -0
- data/test/test_result.rb +36 -0
- data/test/test_rich_types.rb +29 -0
- data/test/test_type.rb +225 -0
- metadata +66 -0
data/.bundle/config
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.2@simpex --create
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/testtask'
|
3
|
+
require File.expand_path('simpex.rb', 'lib')
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
|
7
|
+
namespace :simpex do
|
8
|
+
desc "Generates ImpEx file"
|
9
|
+
task :generate do
|
10
|
+
output_directory = "tmp"
|
11
|
+
Factory.generate_base_catalog_setup_to(output_directory)
|
12
|
+
Factory.generate_base_catalog_setup_to_file(output_directory,"single_file_result.csv")
|
13
|
+
puts "Files generated inside #{output_directory}"
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Run all tests"
|
17
|
+
Rake::TestTask.new("test") do |t|
|
18
|
+
t.pattern = 'test/test_*.rb'
|
19
|
+
t.verbose = true
|
20
|
+
t.warning = true
|
21
|
+
end
|
22
|
+
end
|
data/lib/simpex.rb
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/simpex/version')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/simpex/type')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/simpex/type_entry')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/simpex/impex_result')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/simpex/factory')
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + '/simpex/catalog')
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Catalog < TypeEntry
|
2
|
+
|
3
|
+
def initialize(values)
|
4
|
+
super(@@type, values)
|
5
|
+
end
|
6
|
+
|
7
|
+
@@type = Type.new("Catalog", %w{activeCatalogVersion(catalog(id),version) backRefPK buyer(uid) creationtime[forceWrite=true,dateformat=dd.MM.yyyy hh:mm:ss] defaultCatalog[allownull=true] id[unique=true,allownull=true] name[lang=de] name[lang=en] name[lang=fr] name[lang=it] owner(Customer.uid) previewURLTemplate supplier(uid) urlPatterns})
|
8
|
+
|
9
|
+
def Catalog.type
|
10
|
+
@@type
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Factory
|
2
|
+
def Factory.generate_base_catalog_setup_to_file(impex_dest_dir, result_file_name)
|
3
|
+
language_type = Type.new("Language", %w{isocode[unique=true] active})
|
4
|
+
TypeEntry.new(language_type, %w{de true})
|
5
|
+
TypeEntry.new(language_type, %w{en true})
|
6
|
+
|
7
|
+
catalog_type = Type.new("Catalog", %w{id[unique=true] name[lang=de] name[lang=en] defaultCatalog})
|
8
|
+
catalog = TypeEntry.new(catalog_type, %w{simpex_catalog SimpexCatalog SimpexCatalog true})
|
9
|
+
|
10
|
+
catalog_version_type = Type.new("CatalogVersion", %w{catalog(id)[unique=true] version[unique=true] active defaultCurrency(isocode)})
|
11
|
+
TypeEntry.new(catalog_version_type, [catalog.id, "online", "true", "EUR", "de,en"])
|
12
|
+
|
13
|
+
result = ImpexResult.new(impex_dest_dir)
|
14
|
+
result << language_type
|
15
|
+
result << catalog_type
|
16
|
+
result << catalog_version_type
|
17
|
+
result.impexify(result_file_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def Factory.generate_base_catalog_setup_to(impex_dest_dir)
|
21
|
+
language_type = Type.new("Language", %w{isocode[unique=true] active})
|
22
|
+
TypeEntry.new(language_type, %w{de true})
|
23
|
+
TypeEntry.new(language_type, %w{en true})
|
24
|
+
|
25
|
+
catalog_type = Type.new("Catalog", %w{id[unique=true] name[lang=de] name[lang=en] defaultCatalog})
|
26
|
+
catalog = TypeEntry.new(catalog_type, %w{simpex_catalog SimpexCatalog SimpexCatalog true})
|
27
|
+
|
28
|
+
catalog_version_type = Type.new("CatalogVersion", %w{catalog(id)[unique=true] version[unique=true] active defaultCurrency(isocode)})
|
29
|
+
TypeEntry.new(catalog_version_type, [catalog.id, "online", "true", "EUR"])
|
30
|
+
|
31
|
+
result = ImpexResult.new(impex_dest_dir)
|
32
|
+
result << language_type
|
33
|
+
result << catalog_type
|
34
|
+
result << catalog_version_type
|
35
|
+
result.impexify
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
class ImpexResult
|
2
|
+
|
3
|
+
attr_writer :memory_safe, :max_type_entries_in_tree
|
4
|
+
|
5
|
+
def initialize(dest_folder)
|
6
|
+
raise "Given dest folder #{dest_folder} is either nil or does not exist!" if dest_folder.nil? || !Dir.exist?(dest_folder)
|
7
|
+
@dest_folder = dest_folder
|
8
|
+
@types = []
|
9
|
+
@max_type_entries_in_tree = 2000
|
10
|
+
@global_enties_number = 0
|
11
|
+
@impexify_occurences = 0
|
12
|
+
@memory_safe = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(type)
|
16
|
+
@types << type
|
17
|
+
if @memory_safe
|
18
|
+
type.memory_safe = true
|
19
|
+
end
|
20
|
+
type.impex_result = self
|
21
|
+
raise "no result set on type" unless type.impex_result
|
22
|
+
add_entries_number(type.entries.size)
|
23
|
+
check_for_impexify
|
24
|
+
end
|
25
|
+
|
26
|
+
def impexify(result_file_name="", time_stampify = true)
|
27
|
+
if result_file_name.empty?
|
28
|
+
stamp = Time.now.strftime("%S_%M_%H_%d_%m_%Y") if time_stampify
|
29
|
+
@types.each_with_index do |type, index|
|
30
|
+
if time_stampify
|
31
|
+
file_name = "#{@dest_folder}/#{format_number(@impexify_occurences)}_#{type.name.downcase}_#{stamp}.csv"
|
32
|
+
else
|
33
|
+
file_name = "#{@dest_folder}/#{format_number(@impexify_occurences)}_#{type.name.downcase}.csv"
|
34
|
+
end
|
35
|
+
unless type.empty?
|
36
|
+
puts "writing #{type.name} to #{file_name}"
|
37
|
+
File.open(file_name, 'w') do |f|
|
38
|
+
f.puts type.to_imp
|
39
|
+
end
|
40
|
+
@impexify_occurences += 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
else
|
44
|
+
result_file_name = File.basename(result_file_name)
|
45
|
+
file_name = "#{@dest_folder}/#{result_file_name}"
|
46
|
+
puts "writing complete result to the file #{file_name}"
|
47
|
+
result_file_name = File.basename(result_file_name)
|
48
|
+
raise "You gave the directory #{result_file_name} instead of a single file" if File.directory?(result_file_name)
|
49
|
+
File.open(file_name, "w") do |f|
|
50
|
+
all_macros = []
|
51
|
+
@types.each do |type|
|
52
|
+
type.macros.each do |macro|
|
53
|
+
all_macros << macro unless all_macros.include?(macro)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
all_macros.each do |m|
|
57
|
+
f.puts m
|
58
|
+
end
|
59
|
+
f.puts "\n"
|
60
|
+
@types.each do |type|
|
61
|
+
f.puts type.to_imp(false) unless type.empty?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@impexify_occurences += 1
|
65
|
+
end
|
66
|
+
clean_all_type_entries
|
67
|
+
end
|
68
|
+
|
69
|
+
def format_number(number_to_format, numeric_positions="4")
|
70
|
+
"%0#{numeric_positions}d" % number_to_format
|
71
|
+
end
|
72
|
+
|
73
|
+
def global_enties_number
|
74
|
+
@global_enties_number
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_entries_number(added_number)
|
78
|
+
@global_enties_number +=added_number
|
79
|
+
check_for_impexify
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def clean_all_type_entries
|
84
|
+
@types.each do |type|
|
85
|
+
type.entries.clear
|
86
|
+
end
|
87
|
+
@global_enties_number = 0
|
88
|
+
end
|
89
|
+
def check_for_impexify
|
90
|
+
if @memory_safe
|
91
|
+
if @global_enties_number > @max_type_entries_in_tree
|
92
|
+
puts "impexifying all entries since global entries #{@global_enties_number} is bigger then max #{@max_type_entries_in_tree}"
|
93
|
+
self.impexify
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
data/lib/simpex/type.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
class Type
|
5
|
+
attr_reader :attributes, :entries, :name, :macros, :impex_command, :impex_result, :after_each
|
6
|
+
attr_writer :impex_command, :impex_result, :memory_safe, :after_each
|
7
|
+
|
8
|
+
def initialize(name, type_attributes, macros=[])
|
9
|
+
raise "Type name was not given, use e.g. 'Product' or 'Category'" if name.empty?
|
10
|
+
raise ArgumentError.new("Attribute values must be given in an array, use '%w{code name description catalog}'") unless type_attributes.kind_of?(Array)
|
11
|
+
raise "Macros was given but is nil" if macros.nil?
|
12
|
+
|
13
|
+
if macros.kind_of? String
|
14
|
+
@macros = [macros]
|
15
|
+
else
|
16
|
+
@macros = macros
|
17
|
+
end
|
18
|
+
@attributes = []
|
19
|
+
type_attributes.each do |attribute|
|
20
|
+
next if attribute.nil? || attribute.empty?
|
21
|
+
if attribute.kind_of?(Hash)
|
22
|
+
@attributes += resolve_to_attributes(attribute)
|
23
|
+
else
|
24
|
+
@attributes << attribute
|
25
|
+
if attribute =~ /^\$/
|
26
|
+
if @macros.empty? || @macros.none?{|m| m.split("=").first == attribute}
|
27
|
+
raise ArgumentError.new "You are using a macro that is not defined: #{attribute}, declared macros are #{@macros}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@name = name
|
33
|
+
@entries = []
|
34
|
+
@impex_command = "INSERT_UPDATE"
|
35
|
+
@impex_result = nil
|
36
|
+
@memory_safe = false
|
37
|
+
@after_each = []
|
38
|
+
@before_each = []
|
39
|
+
end
|
40
|
+
|
41
|
+
def <<(entry)
|
42
|
+
@entries << entry
|
43
|
+
if @impex_result
|
44
|
+
@impex_result.add_entries_number(1)
|
45
|
+
elsif @memory_safe
|
46
|
+
raise "impex result object is not set, but we are running in a memory safe impex generation"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def empty?
|
51
|
+
self.entries.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_imp(macros=true)
|
55
|
+
result = ""
|
56
|
+
return result if @entries.empty?
|
57
|
+
if (!@macros.empty? && macros)
|
58
|
+
@macros.each do |macro|
|
59
|
+
result << macro
|
60
|
+
result << "\n"
|
61
|
+
end
|
62
|
+
result << "\n"
|
63
|
+
end
|
64
|
+
result << "#{@impex_command} #{@name}" + impexify(@attributes)
|
65
|
+
unless after_each.empty?
|
66
|
+
result << "\"#%afterEach:\n"
|
67
|
+
after_each.each do |bash_line|
|
68
|
+
result << bash_line << "\n"
|
69
|
+
end
|
70
|
+
result << "\"\n"
|
71
|
+
end
|
72
|
+
@entries.each do |entry|
|
73
|
+
result << entry.to_imp
|
74
|
+
end
|
75
|
+
result << "\n"
|
76
|
+
unless after_each.empty?
|
77
|
+
result << "\"#%afterEach:end\""
|
78
|
+
end
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def unregister_by(attribute, value)
|
83
|
+
self.entries.reject!{|entry| entry.send(attribute) == value}
|
84
|
+
end
|
85
|
+
|
86
|
+
def find_by(attribute, value)
|
87
|
+
self.entries.find_all{|entry| entry.send(attribute) == value}
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def resolve_to_attributes(attrib)
|
92
|
+
raise "The feature of reading hashes of attrbite names is planned but not implemented yet, implement it here"
|
93
|
+
end
|
94
|
+
|
95
|
+
def impexify(array)
|
96
|
+
CSV.generate_line([nil] + array + [nil], :col_sep => ";")
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
class TypeEntry
|
4
|
+
|
5
|
+
attr :type, :values
|
6
|
+
|
7
|
+
def initialize(type, values)
|
8
|
+
raise ArgumentError.new("Type must be a Type") unless type.kind_of? Type
|
9
|
+
raise ArgumentError.new("Values must be a hash or an array") if (!values.kind_of?(Hash) ) && !values.kind_of?(Array)
|
10
|
+
|
11
|
+
@type = type
|
12
|
+
|
13
|
+
@values = @type.attributes.inject({}) do |result, att|
|
14
|
+
result[att] = nil
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
if values.kind_of?(Hash)
|
19
|
+
values.each do |key, value|
|
20
|
+
real_att_name = guess_attribute(key)
|
21
|
+
if real_att_name
|
22
|
+
set(real_att_name, value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
else
|
26
|
+
if @type.attributes.size != values.size
|
27
|
+
raise ArgumentError.new "The number of given attributes is less then defined, expected are #{@type.attributes.inspect}"
|
28
|
+
end
|
29
|
+
@type.attributes.each_with_index do |att,index|
|
30
|
+
set(att, values[index])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
type << self
|
34
|
+
end
|
35
|
+
|
36
|
+
def get(att_name)
|
37
|
+
attr_names = @values.keys
|
38
|
+
if attr_names.include?(att_name)
|
39
|
+
@values[att_name]
|
40
|
+
else
|
41
|
+
@values[guess_attribute(att_name)]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(id, *args)
|
46
|
+
self.get("#{id}")
|
47
|
+
end
|
48
|
+
|
49
|
+
def set(attributes)
|
50
|
+
@values.merge!(attributes)
|
51
|
+
end
|
52
|
+
|
53
|
+
def set(key, value)
|
54
|
+
if value.kind_of?(Array)
|
55
|
+
@values[key] = value.reject{|v| v.nil? || v.empty? }.join(",")
|
56
|
+
else
|
57
|
+
@values[key] = value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_imp
|
62
|
+
impexify(@values.values)
|
63
|
+
end
|
64
|
+
|
65
|
+
def cat_ver_specific(attr_name)
|
66
|
+
self.get(attr_name) + ":" + self.get("catalogVersion")
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
def guess_attribute(att_name)
|
71
|
+
attr_names = @values.keys
|
72
|
+
guessed_attribute_matches = attr_names.select{|e| e.split("(").first == att_name ||
|
73
|
+
e.split("[").first == att_name ||
|
74
|
+
e.split("$").last == att_name }
|
75
|
+
|
76
|
+
if guessed_attribute_matches.size > 1
|
77
|
+
error_msg = "There is more than one matching attribute name for the given
|
78
|
+
name #{att_name}, matches are #{guessed_attribute_matches.inspect},
|
79
|
+
using of full attribute names is advised"
|
80
|
+
raise ArgumentError.new error_msg
|
81
|
+
else
|
82
|
+
guessed_attribute = guessed_attribute_matches.first
|
83
|
+
if guessed_attribute
|
84
|
+
guessed_attribute
|
85
|
+
else
|
86
|
+
raise ArgumentError.new "No attribte '#{att_name}' was found for the type '#{self.type.name}', declared attributes: #{attr_names.inspect}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def impexify(array)
|
92
|
+
CSV.generate_line([nil] + array + [nil], :col_sep => ";")
|
93
|
+
end
|
94
|
+
end
|
data/readme.textile
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
h1. Simpex – Ruby library for simple ImpEx generation
|
2
|
+
|
3
|
+
The impex torture is over guys! Enjoy your hybris projects with a nice ruby api for impex generation!
|
4
|
+
|
5
|
+
Simpex will make your life easier because:
|
6
|
+
|
7
|
+
* it will remove the "csv noise" from your eyes
|
8
|
+
* let you focus on the important stuff, building relationships between your impex tables
|
9
|
+
* process any incoming format like xml, excel, csv with the power of ruby
|
10
|
+
* do basic impex validations for you before hybris does it: asserting number of attributes and values, asserting the presense of macros
|
11
|
+
* handle huge file sets and write to a file after 20000 entries in the whole tree ( set @memory_safe = true and setup the max_type_entries_in_tree all in the impex_result.rb)
|
12
|
+
* generate the right files names with right index numbers so hyris can process them in the right order
|
13
|
+
* simpex is bullet proof and was used and developed for a huge ecommerce project in cooperation with namics.com
|
14
|
+
|
15
|
+
|
16
|
+
Ready? Here it comes:
|
17
|
+
|
18
|
+
product_type = Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de] unit(code) $catalogVersion supercategories(code)})
|
19
|
+
|
20
|
+
product = TypeEntry.new(product_type, %w{555 myproduct555 meinproduct555 pieces SimpexProducts:Online SampleCategory})
|
21
|
+
|
22
|
+
assert_equal "555", product.code
|
23
|
+
|
24
|
+
assert_equal "pieces", product.unit
|
25
|
+
|
26
|
+
assert_equal "SampleCategory", product.supercategories
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
Never worry about the order of rows any more just create a hash specifying the attributes:
|
31
|
+
|
32
|
+
product2 = TypeEntry.new(product_type, {"code" => "333", "name" => "MyName"})
|
33
|
+
|
34
|
+
|
35
|
+
Just use full string attribute names for ambigious attributes like
|
36
|
+
|
37
|
+
|
38
|
+
assert_equal "myproduct555", product.get("name[lang=en]")
|
39
|
+
|
40
|
+
assert_equal "meinproduct555", product.get("name[lang=de]")
|
41
|
+
|
42
|
+
|
43
|
+
Now lets build some real references:
|
44
|
+
|
45
|
+
catalog_type = Type.new("Catalog", %w{id[unique=true] name[lang=de] name[lang=en] defaultCatalog})
|
46
|
+
catalog = TypeEntry.new(catalog_type, %w{simpex_catalog SimpexCatalog SimpexCatalog true})
|
47
|
+
|
48
|
+
catalog_version_type = Type.new("CatalogVersion", %w{catalog(id)[unique=true] version[unique=true] active defaultCurrency(isocode)})
|
49
|
+
catalog_version = TypeEntry.new(catalog_version_type, [catalog.id, "online", "true", "EUR", "de,en"])
|
50
|
+
|
51
|
+
|
52
|
+
Now add averything to a main object managing the files creation:
|
53
|
+
|
54
|
+
result = ImpexResult.new("your/impex/folder")
|
55
|
+
|
56
|
+
catalog_type << catalog
|
57
|
+
product_type << product
|
58
|
+
|
59
|
+
result << catalog_type
|
60
|
+
result << product_type
|
61
|
+
|
62
|
+
result.impexify # => will write separate files for each type
|
63
|
+
result.impexify("basic_setup.csv") # => will write all tables to one file in the folder your/impex/folder
|
64
|
+
|
65
|
+
|
66
|
+
Thats it!
|
67
|
+
|
68
|
+
h2. Setup
|
69
|
+
|
70
|
+
rvm install 1.9.1
|
71
|
+
cd to directory and run _bundle install_
|
72
|
+
|
73
|
+
h2. ImpEx file generation
|
74
|
+
|
75
|
+
For now it only generates a dummy ImpEx file.
|
76
|
+
Run _rake simpex:generate_
|
77
|
+
You can find the generated file in 'tmp/'
|
78
|
+
|
79
|
+
Run _rake simpex:test_ to execute all tests
|
80
|
+
|
81
|
+
|
82
|
+
|
data/simpex.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "simpex/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "simpex"
|
7
|
+
s.version = Simpex::VERSION
|
8
|
+
s.authors = ["Denis Lutz"]
|
9
|
+
s.email = ["denis.lutz@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/denislutz/simpex"
|
11
|
+
s.summary = %q{Simpex is gem to confortably create hybris impex format files in an object oriented way.}
|
12
|
+
s.description = %q{Read more details at the homepage https://github.com/denislutz/simpex}
|
13
|
+
|
14
|
+
s.rubyforge_project = "simpex"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_development_dependency "rspec"
|
24
|
+
# s.add_runtime_dependency "rest-client"
|
25
|
+
end
|
26
|
+
|
data/test/test_result.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path('simpex.rb', 'lib')
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class TestResult < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
macros = []
|
8
|
+
macros << "$firstmacro"
|
9
|
+
macros << "$secondmacro"
|
10
|
+
|
11
|
+
@category_type = Type.new("Category", %w{code[unique=true] name[lang=de]}, macros)
|
12
|
+
@product_type = Type.new("Product", %w{code[unique=true] name[lang=en]}, macros)
|
13
|
+
|
14
|
+
@impex_dest_dir = "test/tmp"
|
15
|
+
FileUtils.mkdir(@impex_dest_dir) unless Dir.exist?(@impex_dest_dir)
|
16
|
+
@result_file_path = File.expand_path("result.csv", @impex_dest_dir)
|
17
|
+
|
18
|
+
#assert !File.exist?(@result_file_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_should_collect_all_marcros_in_a_given_file
|
22
|
+
entry = TypeEntry.new(@product_type, %w{555 myproduct555})
|
23
|
+
entry = TypeEntry.new(@category_type, %w{555 mycategory})
|
24
|
+
|
25
|
+
result = ImpexResult.new(@impex_dest_dir)
|
26
|
+
result << @category_type
|
27
|
+
result << @product_type
|
28
|
+
result.impexify("result.csv")
|
29
|
+
assert File.exist?(@result_file_path), "the file #{@result_file_path} should have been created"
|
30
|
+
end
|
31
|
+
|
32
|
+
def teardown
|
33
|
+
#File.delete(@result_file_path)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path('simpex.rb', 'lib')
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class TestRichTypes < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@impex_dest_dir = "test/tmp"
|
9
|
+
FileUtils.mkdir(@impex_dest_dir) unless Dir.exist?(@impex_dest_dir)
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
FileUtils.rm_rf(@impex_dest_dir)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_create_catalog_with_specific_type
|
17
|
+
file_name = "specific_type.csv"
|
18
|
+
assert_equal false, File.exist?(File.expand_path(file_name, "test/tmp"))
|
19
|
+
|
20
|
+
catalog = Catalog.new("id" => "mycatalog")
|
21
|
+
assert_not_nil catalog
|
22
|
+
assert_equal "mycatalog", catalog.id
|
23
|
+
|
24
|
+
result = ImpexResult.new(@impex_dest_dir)
|
25
|
+
result << Catalog.type
|
26
|
+
result.impexify(file_name)
|
27
|
+
assert_equal true, File.exist?(File.expand_path(file_name, "test/tmp"))
|
28
|
+
end
|
29
|
+
end
|
data/test/test_type.rb
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path('simpex.rb', 'lib')
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class TestType < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@macros = "$catalogVersion=catalogversion(catalog(id[default='simpexproducts']), version[default='staged'])[unique=true,default='simpexproducts:staged']"
|
8
|
+
|
9
|
+
@category_type = Type.new("Category", %w{code[unique=true] $catalogVersion name[lang=de] name[lang=en]}, @macros)
|
10
|
+
|
11
|
+
@product_type = Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de] unit(code) $catalogVersion supercategories(code)}, @macros)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_validate_type_input_on_creation
|
15
|
+
assert_raise ArgumentError do
|
16
|
+
@category_type = Type.new("MyType", "wrong;string")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_have_setter_getter_for_impex_command
|
21
|
+
assert_equal "INSERT_UPDATE", @product_type.impex_command
|
22
|
+
@product_type.impex_command = "update"
|
23
|
+
assert_equal "update", @product_type.impex_command
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_should_create_a_type
|
27
|
+
assert_not_nil @category_type.attributes
|
28
|
+
assert_not_nil @category_type.entries
|
29
|
+
puts @category_type.inspect
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_type_should_validate_the_presence_of_macros
|
33
|
+
assert_raises ArgumentError do
|
34
|
+
Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de] unit(code) $catalogVersion supercategories(code)})
|
35
|
+
end
|
36
|
+
|
37
|
+
macros = ["$catalogVersion=adsfasdfasdf"]
|
38
|
+
Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de] unit(code) $catalogVersion supercategories(code)}, macros)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_shoud_add_an_after_each_statement
|
42
|
+
bash_script = "#%afterEach: "
|
43
|
+
after_each = "impex.getLastImportedItem().setApprovalStatus(impex.getLastImportedItem().getBaseProduct().getApprovalStatus());"
|
44
|
+
product_type = Type.new("Product", %w{code[unique=true] name[lang=en]})
|
45
|
+
TypeEntry.new(product_type,%w{ 666 denis})
|
46
|
+
product_type.after_each << after_each
|
47
|
+
assert_match /impex/, product_type.after_each.first
|
48
|
+
assert_match /#%afterEach/, product_type.to_imp
|
49
|
+
puts product_type.to_imp
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_type_should_generate_nothing_if_no_entries
|
53
|
+
assert_equal "", @product_type.to_imp(false)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_create_a_type_entry
|
57
|
+
entry = TypeEntry.new(@product_type, {"code" => "333", "name[lang=de]" => "MyName"})
|
58
|
+
@product_type << entry
|
59
|
+
puts entry.inspect
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_entry_should_verity_the_number_of_given_attributes
|
63
|
+
assert_raises ArgumentError do
|
64
|
+
entry = TypeEntry.new(@product_type, %w{66 myname myname pieces})
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_entry_should_reference_other_entries
|
69
|
+
entry = TypeEntry.new(@product_type, {"code" => "333", "name[lang=en]" => "MyName"})
|
70
|
+
@product_type << entry
|
71
|
+
|
72
|
+
assert_equal "333", entry.get("code")
|
73
|
+
assert_equal "MyName", entry.get("name[lang=en]")
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_entry_should_validate_against_the_given_type_attributes
|
77
|
+
product_type = Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de]})
|
78
|
+
assert_raise ArgumentError do
|
79
|
+
entry = TypeEntry.new(product_type, {"co" => "555"})
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_should_fail_if_wrong_values_given
|
84
|
+
assert_raise ArgumentError do
|
85
|
+
entry = TypeEntry.new(@product_type, "somewrong string")
|
86
|
+
end
|
87
|
+
assert_raise ArgumentError do
|
88
|
+
entry = TypeEntry.new(nil, "somewrong string")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_entry_should_accept_array_of_values_and_assign_them_to_columns_according_to_the_order
|
93
|
+
entry = TypeEntry.new(@product_type, %w{555 myproduct555 meinproduct555 pieces SimpexProducts:Online SampleCategory})
|
94
|
+
assert_equal "myproduct555", entry.get("name[lang=en]")
|
95
|
+
assert_equal "meinproduct555", entry.get("name[lang=de]")
|
96
|
+
assert_equal "SampleCategory", entry.get("supercategories(code)")
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def test_entry_should_inforce_to_use_unique_attributes_if_needed_for_fuzzy_matching
|
101
|
+
product_type = Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de]})
|
102
|
+
entry = TypeEntry.new(product_type, %w{555 myproduct555 meinproduct555 })
|
103
|
+
assert_raise ArgumentError do
|
104
|
+
entry.get("name")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_should_create_impex_list_from_array
|
109
|
+
catalog_version_type = Type.new("CatalogVersion", %w{languages(isocode)})
|
110
|
+
|
111
|
+
entry = TypeEntry.new(catalog_version_type, [%w{en de fr it}])
|
112
|
+
assert_equal "en,de,fr,it", entry.languages
|
113
|
+
|
114
|
+
entry2 = TypeEntry.new(catalog_version_type, [["en", nil, "it"]])
|
115
|
+
assert_equal "en,it", entry2.languages
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_type_should_unregister_an_entry_by_attribute
|
119
|
+
product_type = Type.new("Product", %w{code})
|
120
|
+
entry = TypeEntry.new(product_type, %w{555 })
|
121
|
+
|
122
|
+
assert product_type.entries.one?{|e|e.code == "555"}
|
123
|
+
product_type.unregister_by("code", "555")
|
124
|
+
assert product_type.entries.none?{|e|e.code == "555"}
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_type_should_find_entry_by_attribute
|
128
|
+
product_type = Type.new("Product", %w{code})
|
129
|
+
assert product_type.find_by("code", "555").empty?
|
130
|
+
entry = TypeEntry.new(product_type, %w{555})
|
131
|
+
entry = TypeEntry.new(product_type, %w{555})
|
132
|
+
entry = TypeEntry.new(product_type, %w{556})
|
133
|
+
found = product_type.find_by("code", "555")
|
134
|
+
assert_equal 2, found.size
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_entry_should_match_fuzzy_attribute_names
|
138
|
+
product_type = Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de] unit(code) $catalogVersion supercategories(code)}, @macros)
|
139
|
+
entry = TypeEntry.new(product_type, %w{555 myproduct555 meinproduct555 pieces SimpexProducts:Online SampleCategory})
|
140
|
+
|
141
|
+
assert_equal "555", entry.get("code")
|
142
|
+
assert_equal "pieces", entry.get("unit")
|
143
|
+
assert_equal "SampleCategory", entry.get("supercategories")
|
144
|
+
|
145
|
+
assert_raise ArgumentError do
|
146
|
+
entry.get("supercat")
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_entry_should_match_nested_brakets_attributes
|
151
|
+
product_type = Type.new("Product", %w{code[unique=true] catalog(id)[unique=true]})
|
152
|
+
entry = TypeEntry.new(product_type, %w{555 myCatalogId})
|
153
|
+
assert_equal "myCatalogId", entry.catalog
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_entry_should_give_catalog_version_specific_attributes
|
157
|
+
product_type = Type.new("Product", %w{code[unique=true] $catalogVersion}, @macros)
|
158
|
+
entry = TypeEntry.new(product_type, %w{555 myCatalogId:staged })
|
159
|
+
assert_equal "555:myCatalogId:staged", entry.cat_ver_specific("code")
|
160
|
+
|
161
|
+
assert_raise ArgumentError do
|
162
|
+
product_type = Type.new("Product", %w{code[unique=true] someattr})
|
163
|
+
entry = TypeEntry.new(product_type, %w{555 myCatalogId:staged })
|
164
|
+
assert_equal "555:myCatalogId:staged", entry.cat_ver_specific("code")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_entry_should_match_macro_attributes
|
169
|
+
product_type = Type.new("Product", %w{code[unique=true] $catalogVersion},"$catalogVersion=asdfadsfasdfasdf")
|
170
|
+
entry = TypeEntry.new(product_type, %w{555 myCatalogId})
|
171
|
+
assert_equal "myCatalogId", entry.catalogVersion
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_entry_should_match_fuzzy_attribute_names_to_real_attributes
|
175
|
+
product_type = Type.new("Product", %w{code[unique=true] name[lang=en] name[lang=de] unit(code) $catalogVersion supercategories(code)}, @macros)
|
176
|
+
entry = TypeEntry.new(product_type, %w{555 myproduct555 meinproduct555 pieces SimpexProducts:Online SampleCategory})
|
177
|
+
|
178
|
+
assert_equal "555", entry.code
|
179
|
+
assert_equal "pieces", entry.unit
|
180
|
+
assert_equal "SampleCategory", entry.supercategories
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_should_write_the_impex_resupt_to_the_given_folder
|
184
|
+
impex_dest_dir = "test/tmp"
|
185
|
+
FileUtils.mkdir(impex_dest_dir) unless Dir.exist?(impex_dest_dir)
|
186
|
+
|
187
|
+
result = standard_result(impex_dest_dir)
|
188
|
+
result.impexify
|
189
|
+
|
190
|
+
FileUtils.rm_rf(impex_dest_dir)
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_should_write_the_result_in_one_file
|
194
|
+
impex_dest_dir = "test/tmp"
|
195
|
+
FileUtils.mkdir(impex_dest_dir) unless Dir.exist?(impex_dest_dir)
|
196
|
+
result_file_path = "#{impex_dest_dir}/result.csv"
|
197
|
+
|
198
|
+
assert !File.exist?(result_file_path)
|
199
|
+
result = standard_result(impex_dest_dir)
|
200
|
+
result.impexify("result.csv")
|
201
|
+
assert File.exist?(result_file_path), "the file #{result_file_path} should have been created"
|
202
|
+
|
203
|
+
File.delete(result_file_path)
|
204
|
+
end
|
205
|
+
|
206
|
+
private
|
207
|
+
def standard_result(impex_dest_dir)
|
208
|
+
|
209
|
+
language_type = Type.new("Language", %w{isocode[unique=true] active})
|
210
|
+
TypeEntry.new(language_type, %w{de true})
|
211
|
+
TypeEntry.new(language_type, %w{en true})
|
212
|
+
|
213
|
+
catalog_type = Type.new("Catalog", %w{id[unique=true] name[lang=de] name[lang=en] defaultCatalog})
|
214
|
+
catalog = TypeEntry.new(catalog_type, %w{simpex_catalog SimpexCatalog SimpexCatalog true})
|
215
|
+
|
216
|
+
catalog_version_type = Type.new("CatalogVersion", %w{catalog(id)[unique=true] version[unique=true] active defaultCurrency(isocode)})
|
217
|
+
TypeEntry.new(catalog_version_type, [catalog.id, "online", "true", "EUR"])
|
218
|
+
|
219
|
+
result = ImpexResult.new(impex_dest_dir)
|
220
|
+
result << language_type
|
221
|
+
result << catalog_type
|
222
|
+
result << catalog_version_type
|
223
|
+
result
|
224
|
+
end
|
225
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simpex
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Denis Lutz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-17 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Read more details at the homepage https://github.com/denislutz/simpex
|
15
|
+
email:
|
16
|
+
- denis.lutz@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .bundle/config
|
22
|
+
- .rvmrc
|
23
|
+
- Gemfile
|
24
|
+
- Gemfile.lock
|
25
|
+
- Rakefile
|
26
|
+
- lib/simpex.rb
|
27
|
+
- lib/simpex/catalog.rb
|
28
|
+
- lib/simpex/factory.rb
|
29
|
+
- lib/simpex/impex_result.rb
|
30
|
+
- lib/simpex/type.rb
|
31
|
+
- lib/simpex/type_entry.rb
|
32
|
+
- lib/simpex/version.rb
|
33
|
+
- readme.textile
|
34
|
+
- simpex.gemspec
|
35
|
+
- test/test_result.rb
|
36
|
+
- test/test_rich_types.rb
|
37
|
+
- test/test_type.rb
|
38
|
+
homepage: https://github.com/denislutz/simpex
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project: simpex
|
58
|
+
rubygems_version: 1.8.10
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Simpex is gem to confortably create hybris impex format files in an object
|
62
|
+
oriented way.
|
63
|
+
test_files:
|
64
|
+
- test/test_result.rb
|
65
|
+
- test/test_rich_types.rb
|
66
|
+
- test/test_type.rb
|