simpex 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|