MikeSofaer-saxual-replication 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/README +0 -0
- data/Rakefile +14 -0
- data/lib/saxual-replication.rb +92 -0
- data/spec/saxual-replication/saxual_replication_spec.rb +76 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +13 -0
- metadata +77 -0
data/README
ADDED
|
File without changes
|
data/Rakefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require "spec"
|
|
2
|
+
require "spec/rake/spectask"
|
|
3
|
+
require 'lib/saxual-replication.rb'
|
|
4
|
+
|
|
5
|
+
Spec::Rake::SpecTask.new do |t|
|
|
6
|
+
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
|
7
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
task :install do
|
|
11
|
+
rm_rf "*.gem"
|
|
12
|
+
puts `gem build saxual-replication.gemspec`
|
|
13
|
+
puts `sudo gem install saxual-replication-#{SAXualReplication::VERSION}.gem`
|
|
14
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'sax-machine'
|
|
2
|
+
require 'dm-core'
|
|
3
|
+
|
|
4
|
+
module SAXualReplication
|
|
5
|
+
class MissingElementError < Exception; end
|
|
6
|
+
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.send(:include, SAXMachine)
|
|
9
|
+
base.extend SaverMethods
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module SaverMethods
|
|
13
|
+
def parse(xml)
|
|
14
|
+
ret = super(xml)
|
|
15
|
+
ret.validate
|
|
16
|
+
return ret
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def parse_multiple(xml)
|
|
20
|
+
klass = collection_class
|
|
21
|
+
ret = klass.parse(xml)
|
|
22
|
+
ret.rows.each{|o| o.validate}
|
|
23
|
+
ret.rows
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def columns_with_types
|
|
27
|
+
column_names.each{|c| yield c, data_class(c) || String}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def connection
|
|
31
|
+
DataMapper.repository(:default).adapter
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def table(value)
|
|
35
|
+
@table_name = value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def tag(value)
|
|
39
|
+
@tag = value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def datamapper_class
|
|
43
|
+
klass = self.dup
|
|
44
|
+
klass.send(:include, DataMapper::Resource)
|
|
45
|
+
klass.storage_names[:default] = @table_name
|
|
46
|
+
klass.property(:id, DataMapper::Types::Serial)
|
|
47
|
+
klass.property(:created_at, DateTime, :nullable => false)
|
|
48
|
+
klass.property(:updated_at, DateTime, :nullable => false)
|
|
49
|
+
columns_with_types { |n, t| klass.property(n, t) }
|
|
50
|
+
klass
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def collection_class
|
|
54
|
+
klass = self
|
|
55
|
+
tag = @tag
|
|
56
|
+
Class.new do
|
|
57
|
+
include SAXualReplication
|
|
58
|
+
elements tag, :as => :rows, :class => klass
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def sql(rows)
|
|
63
|
+
"INSERT INTO "+ @table_name + "(" + column_names.join(', ') + ", created_at, updated_at) VALUES " +
|
|
64
|
+
([("(" + (["?"] * (column_names.size + 2)).join(',') + ")")] * rows.size).join(',')
|
|
65
|
+
end
|
|
66
|
+
def bind_values(rows)
|
|
67
|
+
names = column_names
|
|
68
|
+
datetime = DateTime.now
|
|
69
|
+
array = []
|
|
70
|
+
rows.each{|row| row.add_bind_values!(names, array, datetime)}
|
|
71
|
+
array
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def save(rows)
|
|
75
|
+
connection.execute sql(rows), *bind_values(rows)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
#+ " ON DUPLICATE KEY UPDATE " + update_keys.join(', ')
|
|
81
|
+
|
|
82
|
+
def add_bind_values!(column_names, bind_array, datetime)
|
|
83
|
+
column_names.each{|c| bind_array << self.send(c)}
|
|
84
|
+
bind_array << datetime << datetime
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def validate
|
|
88
|
+
self.class.instance_variable_get('@sax_config').instance_variable_get('@top_level_elements').select{ |e| e.required? }.each do |element|
|
|
89
|
+
raise MissingElementError.new("Missing the required attribute " + element.name) unless send(element.instance_variable_get('@as'))
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "SAXualReplication" do
|
|
4
|
+
before :each do
|
|
5
|
+
@klass = Class.new do
|
|
6
|
+
include SAXualReplication
|
|
7
|
+
element :title
|
|
8
|
+
element :written_on, :class => DateTime
|
|
9
|
+
table "documents"
|
|
10
|
+
tag :document
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
it "should function as a SAXMachine class" do
|
|
14
|
+
document = @klass.parse("<title>Hello, Everyone!</title>")
|
|
15
|
+
document.title.should == "Hello, Everyone!"
|
|
16
|
+
end
|
|
17
|
+
describe "DataMapper" do
|
|
18
|
+
before(:each) do
|
|
19
|
+
DataMapper.setup(:default, 'mysql://localhost/saxual_replication_test')
|
|
20
|
+
@adapter = DataMapper.repository.adapter
|
|
21
|
+
end
|
|
22
|
+
it "should have the database connection" do
|
|
23
|
+
@adapter.query "show tables"
|
|
24
|
+
end
|
|
25
|
+
it "should have a DataMapper class" do
|
|
26
|
+
@klass.datamapper_class.all.should be_a(Array)
|
|
27
|
+
end
|
|
28
|
+
it "should be able to auto-migrate the document table" do
|
|
29
|
+
DataMapper.auto_migrate!
|
|
30
|
+
end
|
|
31
|
+
describe "with multiple columns" do
|
|
32
|
+
before(:each) do
|
|
33
|
+
@document = @klass.parse("<xml><title>Someone's Cat</title><written_on>March 5 2007</written_on></xml>")
|
|
34
|
+
end
|
|
35
|
+
after(:each) do
|
|
36
|
+
@adapter.execute "delete from documents"
|
|
37
|
+
end
|
|
38
|
+
it "should generate the correct bind values for the specified columns" do
|
|
39
|
+
@klass.column_names.should =~ [:title, :written_on]
|
|
40
|
+
array = []
|
|
41
|
+
@document.add_bind_values!(@klass.column_names, array, DateTime.now)
|
|
42
|
+
array[0].should == "Someone's Cat"
|
|
43
|
+
array[1].should be_a(DateTime)
|
|
44
|
+
array[2].should be_a(DateTime)
|
|
45
|
+
array[3].should be_a(DateTime)
|
|
46
|
+
end
|
|
47
|
+
it "should generate the correct bind values from a class call" do
|
|
48
|
+
array = @klass.bind_values([@document,@document])
|
|
49
|
+
array[0].should == "Someone's Cat"
|
|
50
|
+
array[4].should == "Someone's Cat"
|
|
51
|
+
array[1].should be_a(DateTime)
|
|
52
|
+
array[5].should be_a(DateTime)
|
|
53
|
+
end
|
|
54
|
+
it "should generate the correct SQL from a class call" do
|
|
55
|
+
@klass.sql([@document,@document]).should == "INSERT INTO documents(title, written_on, created_at, updated_at) VALUES (?,?,?,?),(?,?,?,?)"
|
|
56
|
+
end
|
|
57
|
+
describe "multiple records" do
|
|
58
|
+
before(:each) do
|
|
59
|
+
@xml = "<xml><document><title>Hello, Everyone!</title></document><document><title>Someone's Cat</title></document></xml>"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should be possible to parse two records" do
|
|
63
|
+
rows = @klass.parse_multiple(@xml)
|
|
64
|
+
rows.size.should == 2
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should be able to save two records" do
|
|
68
|
+
documents = @klass.parse_multiple(@xml)
|
|
69
|
+
@klass.save documents
|
|
70
|
+
@klass.datamapper_class.all[0].title.should == "Hello, Everyone!"
|
|
71
|
+
@klass.datamapper_class.all[1].title.should == "Someone's Cat"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "rubygems"
|
|
2
|
+
require "spec"
|
|
3
|
+
|
|
4
|
+
# gem install redgreen for colored test output
|
|
5
|
+
begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end
|
|
6
|
+
|
|
7
|
+
path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
|
8
|
+
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
|
9
|
+
|
|
10
|
+
require "lib/saxual-replication"
|
|
11
|
+
|
|
12
|
+
# Spec::Runner.configure do |config|
|
|
13
|
+
# end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: MikeSofaer-saxual-replication
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Michael Sofaer
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-07-21 00:00:00 -07:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: sax-machine
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">"
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: 0.0.15
|
|
24
|
+
version:
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: dm-core
|
|
27
|
+
type: :runtime
|
|
28
|
+
version_requirement:
|
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 0.0.0
|
|
34
|
+
version:
|
|
35
|
+
description:
|
|
36
|
+
email: mike@sofaer.net
|
|
37
|
+
executables: []
|
|
38
|
+
|
|
39
|
+
extensions: []
|
|
40
|
+
|
|
41
|
+
extra_rdoc_files: []
|
|
42
|
+
|
|
43
|
+
files:
|
|
44
|
+
- lib/saxual-replication.rb
|
|
45
|
+
- README
|
|
46
|
+
- Rakefile
|
|
47
|
+
- spec/spec.opts
|
|
48
|
+
- spec/spec_helper.rb
|
|
49
|
+
- spec/saxual-replication/saxual_replication_spec.rb
|
|
50
|
+
has_rdoc: false
|
|
51
|
+
homepage: http://github.com/MikeSofaer/saxual-replication
|
|
52
|
+
post_install_message:
|
|
53
|
+
rdoc_options: []
|
|
54
|
+
|
|
55
|
+
require_paths:
|
|
56
|
+
- lib
|
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: "0"
|
|
62
|
+
version:
|
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: "0"
|
|
68
|
+
version:
|
|
69
|
+
requirements: []
|
|
70
|
+
|
|
71
|
+
rubyforge_project:
|
|
72
|
+
rubygems_version: 1.2.0
|
|
73
|
+
signing_key:
|
|
74
|
+
specification_version: 2
|
|
75
|
+
summary: Database replication from XML with SAXMachine
|
|
76
|
+
test_files: []
|
|
77
|
+
|