mochigome 0.0.2
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/.autotest +14 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +71 -0
- data/LICENSE +674 -0
- data/README.rdoc +11 -0
- data/Rakefile +74 -0
- data/TODO +6 -0
- data/lib/data_node.rb +106 -0
- data/lib/exceptions.rb +6 -0
- data/lib/mochigome.rb +7 -0
- data/lib/mochigome_ver.rb +3 -0
- data/lib/model_extensions.rb +211 -0
- data/lib/query.rb +199 -0
- data/test/app_root/app/controllers/application_controller.rb +2 -0
- data/test/app_root/app/controllers/owners_controller.rb +2 -0
- data/test/app_root/app/models/boring_datum.rb +3 -0
- data/test/app_root/app/models/category.rb +7 -0
- data/test/app_root/app/models/owner.rb +17 -0
- data/test/app_root/app/models/product.rb +21 -0
- data/test/app_root/app/models/sale.rb +9 -0
- data/test/app_root/app/models/store.rb +13 -0
- data/test/app_root/app/models/store_product.rb +11 -0
- data/test/app_root/config/boot.rb +130 -0
- data/test/app_root/config/database-pg.yml +8 -0
- data/test/app_root/config/database.yml +6 -0
- data/test/app_root/config/environment.rb +14 -0
- data/test/app_root/config/environments/test.rb +20 -0
- data/test/app_root/config/offroad.yml +6 -0
- data/test/app_root/config/preinitializer.rb +20 -0
- data/test/app_root/config/routes.rb +4 -0
- data/test/app_root/db/migrate/20110817163830_create_tables.rb +66 -0
- data/test/app_root/vendor/plugins/mochigome/init.rb +2 -0
- data/test/factories.rb +39 -0
- data/test/test.watchr +6 -0
- data/test/test_helper.rb +66 -0
- data/test/unit/data_node_test.rb +144 -0
- data/test/unit/model_extensions_test.rb +367 -0
- data/test/unit/query_test.rb +202 -0
- metadata +143 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
class Store < ActiveRecord::Base
|
2
|
+
acts_as_mochigome_focus do |f|
|
3
|
+
f.type_name "Storefront"
|
4
|
+
end
|
5
|
+
|
6
|
+
belongs_to :owner
|
7
|
+
has_many :store_products
|
8
|
+
has_many :products, :through => :store_products
|
9
|
+
has_many :sales, :through => :store_products
|
10
|
+
|
11
|
+
validates_presence_of :name
|
12
|
+
validates_presence_of :owner
|
13
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# Don't change this file!
|
2
|
+
# Configure your app in config/environment.rb and config/environments/*.rb
|
3
|
+
|
4
|
+
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
5
|
+
|
6
|
+
module Rails
|
7
|
+
class << self
|
8
|
+
def boot!
|
9
|
+
require 'rubygems'
|
10
|
+
Deprecate::skip = true
|
11
|
+
unless booted?
|
12
|
+
preinitialize
|
13
|
+
pick_boot.run
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def booted?
|
18
|
+
defined? Rails::Initializer
|
19
|
+
end
|
20
|
+
|
21
|
+
def pick_boot
|
22
|
+
(vendor_rails? ? VendorBoot : GemBoot).new
|
23
|
+
end
|
24
|
+
|
25
|
+
def vendor_rails?
|
26
|
+
File.exist?("#{RAILS_ROOT}/vendor/rails")
|
27
|
+
end
|
28
|
+
|
29
|
+
def preinitialize
|
30
|
+
load(preinitializer_path) if File.exist?(preinitializer_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
def preinitializer_path
|
34
|
+
"#{RAILS_ROOT}/config/preinitializer.rb"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Boot
|
39
|
+
def run
|
40
|
+
load_initializer
|
41
|
+
Rails::Initializer.run(:set_load_path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class VendorBoot < Boot
|
46
|
+
def load_initializer
|
47
|
+
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
48
|
+
Rails::Initializer.run(:install_gem_spec_stubs)
|
49
|
+
Rails::GemDependency.add_frozen_gem_path
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class GemBoot < Boot
|
54
|
+
def load_initializer
|
55
|
+
self.class.load_rubygems
|
56
|
+
load_rails_gem
|
57
|
+
require 'initializer'
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_rails_gem
|
61
|
+
if version = self.class.gem_version
|
62
|
+
gem 'rails', version
|
63
|
+
else
|
64
|
+
gem 'rails'
|
65
|
+
end
|
66
|
+
rescue Gem::LoadError => load_error
|
67
|
+
if load_error.message =~ /Could not find RubyGem rails/
|
68
|
+
STDERR.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
|
69
|
+
exit 1
|
70
|
+
else
|
71
|
+
raise
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class << self
|
76
|
+
def rubygems_version
|
77
|
+
Gem::RubyGemsVersion rescue nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def gem_version
|
81
|
+
if defined? RAILS_GEM_VERSION
|
82
|
+
RAILS_GEM_VERSION
|
83
|
+
elsif ENV.include?('RAILS_GEM_VERSION')
|
84
|
+
ENV['RAILS_GEM_VERSION']
|
85
|
+
else
|
86
|
+
parse_gem_version(read_environment_rb)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def load_rubygems
|
91
|
+
min_version = '1.3.2'
|
92
|
+
require 'rubygems'
|
93
|
+
unless rubygems_version >= min_version
|
94
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
95
|
+
exit 1
|
96
|
+
end
|
97
|
+
|
98
|
+
rescue LoadError
|
99
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
100
|
+
exit 1
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_gem_version(text)
|
104
|
+
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def read_environment_rb
|
109
|
+
File.read("#{RAILS_ROOT}/config/environment.rb")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class Rails::Boot
|
116
|
+
def run
|
117
|
+
load_initializer
|
118
|
+
|
119
|
+
Rails::Initializer.class_eval do
|
120
|
+
def load_gems
|
121
|
+
@bundler_loaded ||= Bundler.require :default, Rails.env
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
Rails::Initializer.run(:set_load_path)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# All that for this:
|
130
|
+
Rails.boot!
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
2
|
+
|
3
|
+
Rails::Initializer.run do |config|
|
4
|
+
config.cache_classes = false
|
5
|
+
config.whiny_nils = true
|
6
|
+
config.action_controller.session = {:key => 'rails_session', :secret => 'd229e4d22437432705ab3985d4d246'}
|
7
|
+
|
8
|
+
if ENV['PSQL_TEST_MODE']
|
9
|
+
puts "Using postgresql for a test database"
|
10
|
+
config.database_configuration_file = "#{RAILS_ROOT}/config/database-pg.yml"
|
11
|
+
else
|
12
|
+
puts "Using sqlite for a test database"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
config.cache_classes = true
|
2
|
+
|
3
|
+
# Log error messages when you accidentally call methods on nil.
|
4
|
+
config.whiny_nils = true
|
5
|
+
|
6
|
+
# Show full error reports and disable caching
|
7
|
+
config.action_controller.consider_all_requests_local = true
|
8
|
+
config.action_controller.perform_caching = false
|
9
|
+
config.action_view.cache_template_loading = true
|
10
|
+
|
11
|
+
# Disable request forgery protection in test environment
|
12
|
+
config.action_controller.allow_forgery_protection = false
|
13
|
+
|
14
|
+
# Tell Action Mailer not to deliver emails to the real world.
|
15
|
+
# The :test delivery method accumulates sent emails in the
|
16
|
+
# ActionMailer::Base.deliveries array.
|
17
|
+
config.action_mailer.delivery_method = :test
|
18
|
+
|
19
|
+
# Avoid excessively large log files
|
20
|
+
config.log_level = :error
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Configuration for Offroad
|
2
|
+
# :online_url: The URL for the regular online version of the app
|
3
|
+
# :app_name: The name of the application, to be used in helpful messages in the generated mirror data files.
|
4
|
+
|
5
|
+
:online_url: "http://example.com"
|
6
|
+
:app_name: Example Application
|
@@ -0,0 +1,20 @@
|
|
1
|
+
begin
|
2
|
+
require "rubygems"
|
3
|
+
require "bundler"
|
4
|
+
rescue LoadError
|
5
|
+
raise "Could not load the bundler gem. Install it with `gem install bundler`."
|
6
|
+
end
|
7
|
+
|
8
|
+
if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.24")
|
9
|
+
raise RuntimeError, "Your bundler version is too old for Rails 2.3." +
|
10
|
+
"Run `gem install bundler` to upgrade."
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
# Set up load paths for all bundled gems
|
15
|
+
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../../../Gemfile", __FILE__)
|
16
|
+
Bundler.setup
|
17
|
+
rescue Bundler::GemNotFound
|
18
|
+
raise RuntimeError, "Bundler couldn't find some gems." +
|
19
|
+
"Did you run `bundle install`?"
|
20
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class CreateTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :products do |t|
|
4
|
+
t.string :name
|
5
|
+
t.decimal :price
|
6
|
+
t.integer :category_id
|
7
|
+
t.boolean :categorized
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table :categories do |t|
|
12
|
+
t.string :name
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :stores do |t|
|
17
|
+
t.string :name
|
18
|
+
t.integer :owner_id
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table :owners do |t|
|
23
|
+
t.string :first_name
|
24
|
+
t.string :last_name
|
25
|
+
t.date :birth_date
|
26
|
+
t.string :phone_number
|
27
|
+
t.string :email_address
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :store_products do |t|
|
32
|
+
t.integer :store_id
|
33
|
+
t.integer :product_id
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :sales do |t|
|
37
|
+
t.integer :store_product_id
|
38
|
+
t.timestamps
|
39
|
+
end
|
40
|
+
|
41
|
+
# Used by ModelExtensionTest to create temporary models
|
42
|
+
create_table :fake do |t|
|
43
|
+
t.timestamps
|
44
|
+
t.string :a
|
45
|
+
t.string :b
|
46
|
+
t.integer :product_id
|
47
|
+
t.integer :x
|
48
|
+
end
|
49
|
+
|
50
|
+
# A model that has nothing to do with reports
|
51
|
+
create_table :boring_data do |t|
|
52
|
+
t.string :foo
|
53
|
+
t.string :bar
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.down
|
58
|
+
drop_table :products
|
59
|
+
drop_table :categories
|
60
|
+
drop_table :stores
|
61
|
+
drop_table :owners
|
62
|
+
drop_table :store_products
|
63
|
+
drop_table :sales
|
64
|
+
drop_table :fake
|
65
|
+
end
|
66
|
+
end
|
data/test/factories.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
FactoryGirl.define do
|
4
|
+
factory :product do
|
5
|
+
name 'LG Optimus V'
|
6
|
+
price 19.95
|
7
|
+
categorized true
|
8
|
+
end
|
9
|
+
|
10
|
+
factory :category do
|
11
|
+
name 'Gadgets'
|
12
|
+
end
|
13
|
+
|
14
|
+
factory :store do
|
15
|
+
name 'Best Buy'
|
16
|
+
owner
|
17
|
+
end
|
18
|
+
|
19
|
+
factory :owner do
|
20
|
+
first_name 'Thomas'
|
21
|
+
last_name 'Edison'
|
22
|
+
birth_date { 30.years.ago }
|
23
|
+
phone_number "800-555-1212"
|
24
|
+
email_address { "#{first_name}.#{last_name}@example.com".downcase }
|
25
|
+
end
|
26
|
+
|
27
|
+
factory :store_product do
|
28
|
+
store
|
29
|
+
product
|
30
|
+
end
|
31
|
+
|
32
|
+
factory :sale do
|
33
|
+
store_product
|
34
|
+
end
|
35
|
+
|
36
|
+
factory :boring_datum do
|
37
|
+
foo 'Bar'
|
38
|
+
end
|
39
|
+
end
|
data/test/test.watchr
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
2
|
+
|
3
|
+
prev_dir = Dir.getwd
|
4
|
+
begin
|
5
|
+
Dir.chdir("#{File.dirname(__FILE__)}/..")
|
6
|
+
|
7
|
+
begin
|
8
|
+
# Used when running test files directly
|
9
|
+
$LOAD_PATH << "#{File.dirname(__FILE__)}/../lib"
|
10
|
+
require "#{File.dirname(__FILE__)}/app_root/config/environment"
|
11
|
+
rescue LoadError
|
12
|
+
# This is needed for root-level rake task 'test'
|
13
|
+
require "app_root/config/environment"
|
14
|
+
end
|
15
|
+
ensure
|
16
|
+
Dir.chdir(prev_dir)
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'redgreen'
|
22
|
+
|
23
|
+
module MiniTest
|
24
|
+
def self.filter_backtrace(backtrace)
|
25
|
+
backtrace = backtrace.select do |e|
|
26
|
+
if ENV['FULL_BACKTRACE']
|
27
|
+
true
|
28
|
+
else
|
29
|
+
!(e.include?("/ruby/") || e.include?("/gems/"))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
common_prefix = nil
|
34
|
+
backtrace.each do |elem|
|
35
|
+
next if elem.start_with? "./"
|
36
|
+
if common_prefix
|
37
|
+
until elem.start_with? common_prefix
|
38
|
+
common_prefix.chop!
|
39
|
+
end
|
40
|
+
else
|
41
|
+
common_prefix = String.new(elem)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
return backtrace.map do |element|
|
46
|
+
if element.start_with? common_prefix && common_prefix.size < element.size
|
47
|
+
element[common_prefix.size, element.size]
|
48
|
+
elsif element.start_with? "./"
|
49
|
+
element[2, element.size]
|
50
|
+
elsif element.start_with?(Dir.getwd)
|
51
|
+
element[Dir.getwd.size+1, element.size]
|
52
|
+
else
|
53
|
+
element
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
require 'factories'
|
61
|
+
MiniTest::Unit::TestCase.send(:include, Factory::Syntax::Methods)
|
62
|
+
|
63
|
+
MiniTest::Unit::TestCase.add_setup_hook do
|
64
|
+
ActiveRecord::Migration.verbose = false
|
65
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate") # Migrations in the test app
|
66
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
describe Mochigome::DataNode do
|
4
|
+
it "is a Hash" do
|
5
|
+
assert Mochigome::DataNode.new(:foo, :bar).is_a?(Hash)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "converts keys to symbols on creation" do
|
9
|
+
datanode = Mochigome::DataNode.new(:foo, :bar, [{"a" => 1}, {"b" => 2}, {:c => 3}])
|
10
|
+
assert_equal({:a => 1, :b => 2, :c => 3}, datanode)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "converts its type name and name to strings on creation" do
|
14
|
+
datanode = Mochigome::DataNode.new(:foo, :bar)
|
15
|
+
assert_equal "foo", datanode.type_name
|
16
|
+
assert_equal "bar", datanode.name
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "when created empty" do
|
20
|
+
before do
|
21
|
+
@datanode = Mochigome::DataNode.new(:data, :john_doe)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "has no comment" do
|
25
|
+
assert_equal nil, @datanode.comment
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can get a comment" do
|
29
|
+
@datanode.comment = "We are the Knights of Ni!"
|
30
|
+
assert_equal "We are the Knights of Ni!", @datanode.comment
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can merge content from an array of single-item hashes" do
|
34
|
+
@datanode.merge! [{:foo => 42}, {"bar" => 84}]
|
35
|
+
assert_equal 42, @datanode[:foo]
|
36
|
+
assert_equal 84, @datanode[:bar]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "can have child nodes added to the top layer" do
|
40
|
+
@datanode << Mochigome::DataNode.new(:subdata, :alice, {:a => 1, :b => 2})
|
41
|
+
@datanode << Mochigome::DataNode.new(:subdata, :bob, {:a => 3, :b => 4})
|
42
|
+
assert_equal 2, @datanode.children.size
|
43
|
+
assert_equal({:a => 1, :b => 2}, @datanode.children.first)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can accept an array of children" do
|
47
|
+
@datanode << [
|
48
|
+
Mochigome::DataNode.new(:subdata, :alice, {:a => 1, :b => 2}),
|
49
|
+
Mochigome::DataNode.new(:subdata, :bob, {:a => 3, :b => 4})
|
50
|
+
]
|
51
|
+
assert_equal 2, @datanode.children.size
|
52
|
+
assert_equal({:a => 1, :b => 2}, @datanode.children.first)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "can have items added at multiple layers" do
|
56
|
+
@datanode << Mochigome::DataNode.new(:subdata, :alice, {:a => 1, :b => 2})
|
57
|
+
@datanode.children.first << Mochigome::DataNode.new(:subsubdata, :spot, {:x => 10, :y => 20})
|
58
|
+
@datanode.children.first << Mochigome::DataNode.new(:subsubdata, :fluffy, {:x => 100, :y => 200})
|
59
|
+
assert_equal 1, @datanode.children.size
|
60
|
+
assert_equal 2, @datanode.children.first.size
|
61
|
+
assert_equal({:x => 10, :y => 20}, @datanode.children.first.children.first)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "cannot accept children that are not DataNodes" do
|
65
|
+
assert_raises Mochigome::DataNodeError do
|
66
|
+
@datanode << {:x => 1, :y => 2}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns the new child DataNode(s) from a concatenation" do
|
71
|
+
new_child = @datanode << Mochigome::DataNode.new(:subdata, :alce, {:a => 1})
|
72
|
+
assert_equal @datanode.children.first, new_child
|
73
|
+
|
74
|
+
new_children = @datanode << [
|
75
|
+
Mochigome::DataNode.new(:subdata, :bob, {:a => 1}),
|
76
|
+
Mochigome::DataNode.new(:subdata, :charlie, {:a => 2})
|
77
|
+
]
|
78
|
+
assert_equal @datanode.children.drop(1), new_children
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "when populated" do
|
83
|
+
before do
|
84
|
+
@datanode = Mochigome::DataNode.new(:corporation, :acme)
|
85
|
+
@datanode.comment = "Foo"
|
86
|
+
@datanode.merge! [{:id => 400}, {:apples => 1}, {:box_cutters => 2}, {:can_openers => 3}]
|
87
|
+
emp1 = @datanode << Mochigome::DataNode.new(:employee, :alice)
|
88
|
+
emp1.merge! [{:id => 500}, {:x => 9}, {:y => 8}, {:z => 7}, {:internal_type => "Cyborg"}]
|
89
|
+
emp2 = @datanode << Mochigome::DataNode.new(:employee, :bob)
|
90
|
+
emp2.merge! [{:id => 600}, {:x => 5}, {:y => 4}, {:z => 8734}, {:internal_type => "Human"}]
|
91
|
+
emp2 << Mochigome::DataNode.new(:pet, :lassie)
|
92
|
+
|
93
|
+
@titles = [
|
94
|
+
"corporation::name",
|
95
|
+
"corporation::id",
|
96
|
+
"corporation::apples",
|
97
|
+
"corporation::box_cutters",
|
98
|
+
"corporation::can_openers",
|
99
|
+
"employee::name",
|
100
|
+
"employee::id",
|
101
|
+
"employee::x",
|
102
|
+
"employee::y",
|
103
|
+
"employee::z",
|
104
|
+
"employee::internal_type",
|
105
|
+
"pet::name"
|
106
|
+
]
|
107
|
+
end
|
108
|
+
|
109
|
+
it "can convert to an XML document with ids, names, types, and internal_types as attributes" do
|
110
|
+
# Why stringify and reparse it? So that we could switch to another XML generator.
|
111
|
+
doc = Nokogiri::XML(@datanode.to_xml.to_s)
|
112
|
+
|
113
|
+
comment = doc.xpath('/node[@type="Corporation"]/comment()').first
|
114
|
+
assert comment
|
115
|
+
assert comment.comment?
|
116
|
+
assert_equal "Foo", comment.content
|
117
|
+
|
118
|
+
assert_equal "400", doc.xpath('/node[@type="Corporation"]').first['id']
|
119
|
+
assert_equal "2", doc.xpath('/node/datum[@name="Box Cutters"]').first.content
|
120
|
+
|
121
|
+
emp_nodes = doc.xpath('/node/node[@type="Employee"]')
|
122
|
+
assert_equal "500", emp_nodes.first['id']
|
123
|
+
assert_equal "alice", emp_nodes.first['name']
|
124
|
+
assert_equal "bob", emp_nodes.last['name']
|
125
|
+
assert_equal "Cyborg", emp_nodes.first['internal_type']
|
126
|
+
assert_equal "4", emp_nodes.last.xpath('./datum[@name="Y"]').first.content
|
127
|
+
assert_equal "lassie", emp_nodes.last.xpath('node').first['name']
|
128
|
+
end
|
129
|
+
|
130
|
+
it "can convert to a flattened Ruport table" do
|
131
|
+
table = @datanode.to_flat_ruport_table
|
132
|
+
assert_equal @titles, table.column_names
|
133
|
+
assert_equal ['acme', 400, 1, 2, 3, 'alice', 500, 9, 8, 7, "Cyborg", nil], table.data[0].to_a
|
134
|
+
assert_equal ['acme', 400, 1, 2, 3, 'bob', 600, 5, 4, 8734, "Human", "lassie"], table.data[1].to_a
|
135
|
+
end
|
136
|
+
|
137
|
+
it "can convert to a flat array of arrays" do
|
138
|
+
a = @datanode.to_flat_arrays
|
139
|
+
assert_equal @titles, a[0]
|
140
|
+
assert_equal ['acme', 400, 1, 2, 3, 'alice', 500, 9, 8, 7, "Cyborg", nil], a[1]
|
141
|
+
assert_equal ['acme', 400, 1, 2, 3, 'bob', 600, 5, 4, 8734, "Human", "lassie"], a[2]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|