kangaroo 0.0.3 → 0.1.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/.gitignore +6 -1
  2. data/Gemfile +11 -0
  3. data/README.md +23 -132
  4. data/Rakefile +0 -8
  5. data/bin/kang +5 -64
  6. data/bin/kangdoc +21 -0
  7. data/bin/kangviz +21 -0
  8. data/config/kangaroo.yml.sample +12 -2
  9. data/docs/Architecture.md +1 -0
  10. data/docs/Classes.md +67 -0
  11. data/docs/Installation.md +2 -1
  12. data/docs/Usage.md +1 -0
  13. data/kangaroo.gemspec +8 -8
  14. data/lib/kangaroo.rb +3 -2
  15. data/lib/kangaroo/commands/base.rb +123 -0
  16. data/lib/kangaroo/commands/cli.rb +65 -0
  17. data/lib/kangaroo/commands/doc.rb +44 -0
  18. data/lib/kangaroo/commands/endpoint.rb +33 -0
  19. data/lib/kangaroo/commands/viz.rb +58 -0
  20. data/lib/kangaroo/doc.rb +2 -0
  21. data/lib/kangaroo/exception.rb +3 -0
  22. data/lib/kangaroo/hirb.rb +2 -1
  23. data/lib/kangaroo/model/associations.rb +33 -0
  24. data/lib/kangaroo/model/associations/many2one.rb +43 -0
  25. data/lib/kangaroo/model/associations/one2many.rb +41 -0
  26. data/lib/kangaroo/model/attributes.rb +88 -93
  27. data/lib/kangaroo/model/base.rb +44 -15
  28. data/lib/kangaroo/model/condition_normalizer.rb +7 -7
  29. data/lib/kangaroo/model/data_import.rb +28 -0
  30. data/lib/kangaroo/model/default_attributes.rb +20 -14
  31. data/lib/kangaroo/model/dynamic_finder.rb +42 -0
  32. data/lib/kangaroo/model/field.rb +52 -1
  33. data/lib/kangaroo/model/field/readonly.rb +39 -0
  34. data/lib/kangaroo/model/finder.rb +6 -2
  35. data/lib/kangaroo/model/inspector.rb +1 -4
  36. data/lib/kangaroo/model/mass_import.rb +42 -0
  37. data/lib/kangaroo/model/open_object_orm.rb +51 -5
  38. data/lib/kangaroo/model/persistence.rb +43 -19
  39. data/lib/kangaroo/model/readonly_attributes.rb +43 -0
  40. data/lib/kangaroo/model/relation.rb +40 -9
  41. data/lib/kangaroo/model/remote_execute.rb +1 -1
  42. data/lib/kangaroo/model/required_attributes.rb +26 -0
  43. data/lib/kangaroo/railtie.rb +13 -3
  44. data/lib/kangaroo/ruby_adapter/base.rb +2 -1
  45. data/lib/kangaroo/ruby_adapter/class_definition.rb +18 -3
  46. data/lib/kangaroo/ruby_adapter/fields.rb +27 -2
  47. data/lib/kangaroo/ruby_adapter/many2one.rb +38 -0
  48. data/lib/kangaroo/ruby_adapter/one2many.rb +31 -0
  49. data/lib/kangaroo/util/client.rb +29 -4
  50. data/lib/kangaroo/util/configuration.rb +15 -10
  51. data/lib/kangaroo/util/database.rb +8 -8
  52. data/lib/kangaroo/util/loader.rb +18 -22
  53. data/lib/kangaroo/util/loader/information_repository.rb +56 -0
  54. data/lib/kangaroo/util/loader/namespace.rb +1 -1
  55. data/lib/kangaroo/util/loader/reflection.rb +61 -0
  56. data/lib/kangaroo/util/loader/root_namespace.rb +12 -21
  57. data/lib/kangaroo/util/proxy.rb +9 -0
  58. data/lib/kangaroo/util/proxy/common.rb +28 -4
  59. data/lib/kangaroo/util/proxy/db.rb +14 -0
  60. data/lib/kangaroo/util/proxy/object.rb +40 -1
  61. data/lib/kangaroo/util/proxy/superadmin.rb +13 -0
  62. data/lib/kangaroo/version.rb +1 -1
  63. data/lib/kangaroo/viz.rb +1 -0
  64. data/lib/kangaroo/viz/base.rb +92 -0
  65. data/spec/commands/base_spec.rb +42 -0
  66. data/spec/functional/associations/many2one_spec.rb +72 -0
  67. data/spec/functional/associations/one2many_spec.rb +65 -0
  68. data/spec/functional/common_service_spec.rb +25 -0
  69. data/spec/functional/data_import_spec.rb +48 -0
  70. data/spec/functional/dynamic_finder_spec.rb +35 -0
  71. data/spec/functional/exception_handling_spec.rb +18 -0
  72. data/spec/functional/identity_spec.rb +48 -0
  73. data/spec/functional/import_export_spec.rb +39 -0
  74. data/spec/functional/lazy_loading_spec.rb +18 -11
  75. data/spec/functional/ordering_spec.rb +33 -0
  76. data/spec/functional/readonly_attributes_spec.rb +37 -0
  77. data/spec/functional/required_attributes_spec.rb +37 -0
  78. data/spec/functional/root_namespace_spec.rb +19 -0
  79. data/spec/functional/select_relation_spec.rb +26 -0
  80. data/spec/model/attributes_spec.rb +1 -0
  81. data/spec/model/base_spec.rb +1 -0
  82. data/spec/model/default_attributes_spec.rb +3 -1
  83. data/spec/model/finder_spec.rb +2 -1
  84. data/spec/model/inspector_spec.rb +1 -0
  85. data/spec/model/open_object_orm_spec.rb +5 -2
  86. data/spec/model/persistence_spec.rb +1 -0
  87. data/spec/model/relation_spec.rb +2 -2
  88. data/spec/ruby_adapter/class_definition_spec.rb +1 -0
  89. data/spec/server_helper.rb +0 -1
  90. data/spec/spec_helper.rb +4 -1
  91. data/spec/util/loader_spec.rb +6 -6
  92. metadata +152 -159
  93. data/Gemfile.lock +0 -69
  94. data/features/configuration.feature +0 -10
  95. data/features/env.rb +0 -8
  96. data/features/step_definitions/basic_steps.rb +0 -18
  97. data/features/step_definitions/configuration_steps.rb +0 -21
  98. data/features/support/test.yml +0 -11
  99. data/features/utility_services.feature +0 -33
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ module Kangaroo
4
+ describe 'Exception handling' do
5
+ before :all do
6
+ @config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
7
+ @config.login
8
+
9
+ Kangaroo::Util::Loader.new('res.partner', @config.database, 'ExceptionHandlingSpec').load!
10
+ end
11
+
12
+ it "catches missing methods" do
13
+ lambda {
14
+ @config.client.common.abcdef
15
+ }.should raise_error(NoMethodError)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ module Kangaroo
4
+ describe 'Identity' do
5
+ before :all do
6
+ @config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
7
+ @config.login
8
+
9
+ Kangaroo::Util::Loader.new('res.partner', @config.database, 'IdentitySpec').load!
10
+ end
11
+
12
+ it ': Instances of same OpenERP object are considered equal' do
13
+ a = IdentitySpec::Res::Partner.first
14
+ b = IdentitySpec::Res::Partner.first
15
+
16
+ a.should == b
17
+ end
18
+
19
+ it ': Instances of different OpenERP objects are not equal' do
20
+ a, b = IdentitySpec::Res::Partner.all[0, 2]
21
+
22
+ a.should_not == b
23
+ end
24
+
25
+ it ': New records are not equal to anything' do
26
+ a = IdentitySpec::Res::Partner.first
27
+ b = IdentitySpec::Res::Partner.new
28
+ c = IdentitySpec::Res::Partner.new
29
+
30
+ a.should_not == b
31
+ b.should_not == c
32
+ end
33
+
34
+ it ': Instances of different models are always not equal' do
35
+ a = IdentitySpec::Res::Partner.find 1
36
+ b = IdentitySpec::Res::Country.find 1
37
+
38
+ a.should_not == b
39
+ end
40
+
41
+ it ': Arrays of same instances should be equal' do
42
+ a = IdentitySpec::Res::Partner.first
43
+ b = IdentitySpec::Res::Partner.first
44
+
45
+ [a].should == [b]
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ module Kangaroo
4
+ describe 'Import / Export' do
5
+ before :all do
6
+ @config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
7
+ @config.login
8
+
9
+ Kangaroo::Util::Loader.new('res.partner', @config.database, 'ImportExportSpec').load!
10
+ end
11
+
12
+ after :each do
13
+ @cleanup && @cleanup.call
14
+ end
15
+
16
+ it 'exports records' do
17
+ ids = ImportExportSpec::Res::Partner.select(:id).limit(3).all.map &:id
18
+
19
+ exported = ImportExportSpec::Res::Partner.export_data ids, [:name, :id]
20
+
21
+ exported.should be_a(Array)
22
+ exported.first.should be_a(Array)
23
+ exported.first.length.should == 2
24
+ end
25
+
26
+ it 'imports records' do
27
+ name = ImportExportSpec::Res::Partner.find(1).name
28
+
29
+ @cleanup = lambda do
30
+ partner = ImportExportSpec::Res::Partner.find(1)
31
+ partner.name = name
32
+ partner.save!
33
+ end
34
+
35
+ ImportExportSpec::Res::Partner.import_data [".id", "name"], [[1, "XYZ"]]
36
+ ImportExportSpec::Res::Partner.find(1).name.should == "XYZ"
37
+ end
38
+ end
39
+ end
@@ -1,41 +1,48 @@
1
1
  require 'spec_helper'
2
2
 
3
-
4
3
  module Kangaroo
5
4
  describe 'Lazy Loading' do
6
5
  before :all do
7
6
  config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
8
7
  config.login
9
8
 
10
- Kangaroo::Util::Loader.new('res.partner', config.database).load!
9
+ Kangaroo::Util::Loader.new('res.partner', config.database, 'LazyLoadSpec').load!
11
10
  end
12
11
 
13
- it 'should raise error if trying to access constant without corresponding OpenERP Model' do
12
+ it 'raises an error if trying to access constant without corresponding OpenERP Model' do
14
13
  lambda {
15
- Oo::Abcd
14
+ LazyLoadSpec::Abcd
16
15
  }.should raise_error
17
16
 
18
17
  lambda {
19
- Oo::Res::Bcde
18
+ LazyLoadSpec::Res::Bcde
20
19
  }.should raise_error
21
20
  end
22
21
 
23
- it 'should lazy load additional models in an OpenERP namespace' do
22
+ it 'lazy loads additional models in an OpenERP namespace' do
23
+ lambda {
24
+ LazyLoadSpec::Res::Country
25
+ }.should_not raise_error
26
+ end
27
+
28
+ it 'creates namespace modules on demand' do
24
29
  lambda {
25
- Oo::Res::Country
30
+ LazyLoadSpec::Product
26
31
  }.should_not raise_error
27
32
  end
28
33
 
29
- it 'should create namespace modules on demand' do
34
+ it 'lazy loads missing models in other namespaces' do
30
35
  lambda {
31
- Oo::Product
36
+ LazyLoadSpec::Product::Product
32
37
  }.should_not raise_error
33
38
  end
34
39
 
35
- it 'should lazy load missing models in other namespaces' do
40
+ it 'lazy loads nested models' do
36
41
  lambda {
37
- Oo::Product::Product
42
+ LazyLoadSpec::Sale::Order::Line
38
43
  }.should_not raise_error
44
+
45
+ LazyLoadSpec::Sale::Order.should be_a(Class)
39
46
  end
40
47
  end
41
48
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Kangaroo
4
+ describe 'Ordering' do
5
+ before :all do
6
+ @config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
7
+ @config.login
8
+
9
+ Kangaroo::Util::Loader.new('res.partner', @config.database, 'OrderingSpec').load!
10
+ end
11
+
12
+ it 'can order by id descending' do
13
+ partners = OrderingSpec::Res::Partner.order('id desc').select(:id).all
14
+
15
+ partners[1..-1].each_with_index do |p, i|
16
+ partners[i].id.should > p.id
17
+ end
18
+ end
19
+
20
+ it 'can reverse queries with default ordering' do
21
+ partners = OrderingSpec::Res::Partner.select(:id).all
22
+ reversed_partners = OrderingSpec::Res::Partner.reverse.select(:id).all
23
+
24
+ partners.should == reversed_partners.reverse
25
+ end
26
+
27
+ it 'can return last element' do
28
+ last = OrderingSpec::Res::Partner.last
29
+
30
+ last.should == OrderingSpec::Res::Partner.all.last
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module Kangaroo
4
+ module Model
5
+ describe ReadonlyAttributes do
6
+ before :all do
7
+ config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
8
+ config.login
9
+
10
+ Kangaroo::Util::Loader.new('res.partner', config.database, 'ReadonlyAttributesSpec').load!
11
+ end
12
+
13
+ it 'raises error if trying to write readonly attributes' do
14
+ sale_order = ReadonlyAttributesSpec.by_xml_id :sale, :order
15
+
16
+ ReadonlyAttributesSpec::Sale::Order.fields_hash[:amount_untaxed].readonly?.should == true
17
+
18
+ lambda {
19
+ sale_order.amount_untaxed = 200
20
+ }.should raise_error
21
+ end
22
+
23
+ it 'does not raise error if in state where writing is allowed' do
24
+ sale_order = ReadonlyAttributesSpec.by_xml_id :sale, :order
25
+
26
+ # Asserting the assumptions, in case OpenERPs demo data changes
27
+ ReadonlyAttributesSpec::Sale::Order.fields_hash[:name].readonly?.should == true
28
+ ReadonlyAttributesSpec::Sale::Order.fields_hash[:name].readonly_in?('draft').should == false
29
+ sale_order.state.should == 'draft'
30
+
31
+ lambda {
32
+ sale_order.name = "abcd"
33
+ }.should_not raise_error
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module Kangaroo
4
+ describe Model::RequiredAttributes do
5
+ before :all do
6
+ config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
7
+ config.login
8
+
9
+ Kangaroo::Util::Loader.new('res.country', config.database, 'RequiredAttributesSpec').load!
10
+ end
11
+
12
+ after :each do
13
+ @cleanup && @cleanup.call
14
+ end
15
+
16
+ it 'validates required fields' do
17
+ c = RequiredAttributesSpec::Res::Country.new :name => 'ABCXYZ'
18
+
19
+ c.valid?.should_not == true
20
+ c.errors.keys.should include :code
21
+ end
22
+
23
+ it 'refuses to save invalid records' do
24
+ a = RequiredAttributesSpec::Res::Country.where(:name => 'ABCXYZ').first
25
+ a && a.destroy
26
+
27
+ c = RequiredAttributesSpec::Res::Country.new :name => 'ABCXYZ'
28
+
29
+ c.save.should_not == true
30
+ c.errors.keys.should include :code
31
+
32
+ lambda {
33
+ c.save!
34
+ }.should raise_error
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ module Kangaroo
4
+ describe 'Root namespace' do
5
+ before :all do
6
+ config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
7
+ config.login
8
+
9
+ Kangaroo::Util::Loader.new('res.partner', config.database, 'RootNamespaceSpec').load!
10
+ end
11
+
12
+ it "gets objects by xml id" do
13
+ country = RootNamespaceSpec.by_xml_id :base, :de
14
+
15
+ country.should be_a(RootNamespaceSpec::Res::Country)
16
+ country.code.should == 'DE'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ module Kangaroo
5
+ describe 'Select Relation' do
6
+ before :all do
7
+ config = Kangaroo::Util::Configuration.new 'spec/test_env/test.yml'
8
+ config.login
9
+
10
+ Kangaroo::Util::Loader.new('res.partner', config.database, 'SelectRelationSpec').load!
11
+ end
12
+
13
+ it 'adjusts "attribute_names" when record is fetched with select clause' do
14
+ partner = SelectRelationSpec::Res::Partner.select(:lang, :email).first
15
+
16
+ partner.attribute_names.should =~ %w(lang email)
17
+ SelectRelationSpec::Res::Partner.attribute_names.count.should > 2
18
+ end
19
+
20
+ it 'returns only selected attributes' do
21
+ partner = SelectRelationSpec::Res::Partner.select(:lang, :email).first
22
+
23
+ partner.attributes.keys.should =~ %w(lang email)
24
+ end
25
+ end
26
+ end
@@ -6,6 +6,7 @@ module Kangaroo
6
6
  describe Attributes do
7
7
  before :all do
8
8
  @klass = Class.new(Kangaroo::Model::Base)
9
+ @klass.stub!(:fields_hash).and_return({})
9
10
  @klass.define_multiple_accessors :a, :b
10
11
  end
11
12
 
@@ -6,6 +6,7 @@ module Kangaroo
6
6
  describe Base do
7
7
  before :all do
8
8
  @klass = Class.new(Kangaroo::Model::Base)
9
+ @klass.stub!(:fields_hash).and_return({})
9
10
  @klass.define_multiple_accessors :a, :b
10
11
  end
11
12
 
@@ -4,8 +4,9 @@ require 'kangaroo/model/base'
4
4
  module Kangaroo
5
5
  module Model
6
6
  describe DefaultAttributes do
7
- before :all do
7
+ before :each do
8
8
  @klass = Class.new(Kangaroo::Model::Base)
9
+ @klass.stub!(:fields_hash).and_return({})
9
10
  @klass.define_multiple_accessors :a, :b
10
11
  end
11
12
 
@@ -24,6 +25,7 @@ module Kangaroo
24
25
 
25
26
  it 'fetches default values via default_get on the object service' do
26
27
  @klass = Class.new(Kangaroo::Model::Base)
28
+ @klass.stub!(:fields_hash).and_return({})
27
29
  @klass.define_multiple_accessors :a, :b
28
30
  @klass.field_names = %w(a b)
29
31
  @klass.stub!(:remote).and_return mock('object_service')
@@ -8,6 +8,7 @@ module Kangaroo
8
8
 
9
9
  before :each do
10
10
  @klass = Class.new(Kangaroo::Model::Base)
11
+ @klass.stub!(:fields_hash).and_return({})
11
12
  @klass.define_multiple_accessors :a, :b
12
13
  @klass.stub!(:default_attributes).and_return({})
13
14
  @remote_stub = mock 'remote'
@@ -91,7 +92,7 @@ module Kangaroo
91
92
  @klass.first
92
93
  end
93
94
  end
94
-
95
+
95
96
  describe '#count' do
96
97
  it 'only counts how many records are present' do
97
98
  @remote_stub.should_receive(:search).with([], 0, anything, anything, anything, true).
@@ -6,6 +6,7 @@ module Kangaroo
6
6
  describe Inspector do
7
7
  before :all do
8
8
  SomeClass = Class.new(Kangaroo::Model::Base)
9
+ SomeClass.stub!(:fields_hash).and_return({})
9
10
  SomeClass.define_multiple_accessors :first_attribute, :second_attribute
10
11
  end
11
12
 
@@ -9,6 +9,7 @@ module Kangaroo
9
9
 
10
10
  before :each do
11
11
  @klass = Class.new(Kangaroo::Model::Base)
12
+ @klass.stub!(:fields_hash).and_return({})
12
13
  @klass.define_multiple_accessors :a, :b
13
14
  @klass.stub!(:default_attributes).and_return({})
14
15
  @klass.stub!(:remote).and_return proxy('object', 'some_class')
@@ -17,7 +18,7 @@ module Kangaroo
17
18
  describe '#read' do
18
19
  it 'reads and instantiates records' do
19
20
  object_service.stub!(:xmlrpc_call).
20
- with('execute', 'some_class', 'read', [1], ['a', 'b']).
21
+ with('execute', 'some_class', 'read', [1], ['a', 'b'], false).
21
22
  and_return([{:a => 'one', :id => 1}])
22
23
  @klass.read([1], :fields => ['a', 'b']).first.a.should == 'one'
23
24
  end
@@ -29,7 +30,9 @@ module Kangaroo
29
30
  end
30
31
 
31
32
  it 'uses attribute_names as default value for field list' do
32
- object_service.should_receive(:xmlrpc_call).with('execute', 'some_class', 'read', [1], ['a', 'b']).
33
+ object_service.
34
+ should_receive(:xmlrpc_call).
35
+ with('execute', 'some_class', 'read', [1], ['a', 'b'], false).
33
36
  and_return([{:a => 'one', :id => 1}])
34
37
  @klass.read([1])
35
38
  end
@@ -7,6 +7,7 @@ module Kangaroo
7
7
 
8
8
  before :each do
9
9
  @klass = Class.new(Kangaroo::Model::Base)
10
+ @klass.stub!(:fields_hash).and_return({})
10
11
  @klass.define_multiple_accessors :a, :b
11
12
  @klass.stub!(:default_attributes).and_return({})
12
13
  end
@@ -72,8 +72,8 @@ module Kangaroo
72
72
  end
73
73
 
74
74
  describe '#reverse' do
75
- it 'adds descending id order if no order was specified' do
76
- @relation.reverse.order_clause.should == ['id desc']
75
+ it 'sets the reverse flag if no order was specified' do
76
+ @relation.reverse.reverse_flag.should == true
77
77
  end
78
78
 
79
79
  it 'reverses previously specified orders' do