veneer 0.2.0 → 0.4.0
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/.gitignore +1 -0
- data/Gemfile +12 -1
- data/README.md +55 -87
- data/Rakefile +1 -1
- data/lib/veneer.rb +6 -1
- data/lib/veneer/adapters/activerecord.rb +2 -0
- data/lib/veneer/adapters/activerecord/class_wrapper.rb +99 -5
- data/lib/veneer/adapters/activerecord/instance_wrapper.rb +4 -2
- data/lib/veneer/adapters/activerecord/pre_3.0_class_wrapper.rb +62 -1
- data/lib/veneer/adapters/activerecord/property.rb +22 -0
- data/lib/veneer/adapters/datamapper.rb +1 -0
- data/lib/veneer/adapters/datamapper/class_wrapper.rb +90 -6
- data/lib/veneer/adapters/datamapper/property.rb +25 -0
- data/lib/veneer/adapters/mongomapper.rb +1 -0
- data/lib/veneer/adapters/mongomapper/class_wrapper.rb +68 -0
- data/lib/veneer/adapters/mongomapper/property.rb +16 -0
- data/lib/veneer/base/class_wrapper.rb +110 -7
- data/lib/veneer/base/property.rb +27 -0
- data/lib/veneer/lint.rb +4 -180
- data/lib/veneer/lint/adapter.rb +282 -0
- data/lib/veneer/lint/base.rb +10 -0
- data/lib/veneer/lint/properties.rb +78 -0
- data/lib/veneer/version.rb +1 -1
- data/test/support/helpers.rb +10 -1
- data/test/test_helper.rb +3 -3
- data/test/veneer/activerecord/test_adapter.rb +80 -0
- data/test/veneer/activerecord/test_properties.rb +73 -0
- data/test/veneer/datamapper/test_adapter.rb +71 -0
- data/test/veneer/datamapper/test_properties.rb +59 -0
- data/test/veneer/{adapters/test_mongomapper.rb → mongomapper/test_adapter.rb} +35 -11
- data/test/veneer/mongomapper/test_properties.rb +56 -0
- data/test/veneer_test.rb +35 -0
- data/veneer.gemspec +2 -0
- metadata +57 -51
- data/test/veneer/adapters/test_active_record.rb +0 -56
- data/test/veneer/adapters/test_datamapper.rb +0 -56
@@ -0,0 +1,78 @@
|
|
1
|
+
module Veneer
|
2
|
+
module Lint
|
3
|
+
module Properties
|
4
|
+
include Veneer::Lint::Base
|
5
|
+
|
6
|
+
def test_should_setup_properties_mapping
|
7
|
+
assert_not_nil @properties_mapping
|
8
|
+
assert_kind_of Hash, @properties_mapping
|
9
|
+
@properties_mapping.each do |k, v|
|
10
|
+
assert_kind_of Symbol, k
|
11
|
+
assert_kind_of Class, v
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_setup_expected_primary_keys
|
16
|
+
assert_not_nil @primary_keys
|
17
|
+
assert_kind_of Array, @primary_keys
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_properties
|
21
|
+
result = Veneer(@klass).properties
|
22
|
+
assert result.kind_of?(Array)
|
23
|
+
assert result.size > 0
|
24
|
+
property = result.first
|
25
|
+
assert_kind_of Veneer::Base::Property, property
|
26
|
+
assert_kind_of Class, property.type
|
27
|
+
assert_kind_of Symbol, property.name
|
28
|
+
assert_not_nil property.primary?
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_primary_keys
|
32
|
+
wrapped = Veneer(@klass)
|
33
|
+
properties = wrapped.properties
|
34
|
+
primary_keys = wrapped.primary_keys
|
35
|
+
|
36
|
+
assert_equal @primary_keys, wrapped.primary_keys
|
37
|
+
|
38
|
+
|
39
|
+
desired_primary_keys = properties.select { |property| primary_keys.include? property.name }
|
40
|
+
assert_equal primary_keys.size, desired_primary_keys.size
|
41
|
+
|
42
|
+
desired_primary_keys.each { |key| assert key.primary? }
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_constraints
|
46
|
+
Veneer(@klass).properties.each do |property|
|
47
|
+
assert_not_nil property[:constraints]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_length
|
52
|
+
@properties_with_length.each do |name, length|
|
53
|
+
assert_equal length, property_by_name(name).constraints[:length], "Expected #{name}.length to be #{length}."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_types_conversion
|
58
|
+
@properties_mapping.each do |name, expected_normalized_type|
|
59
|
+
assert_equal expected_normalized_type, property_by_name(name).type, "Expected #{name} to be #{expected_normalized_type}."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_validations
|
64
|
+
@properties_with_validations.each do |name, validator_classes|
|
65
|
+
validators = Veneer(@klass).validators_on(name)
|
66
|
+
assert_equal validator_classes.size, validators.size
|
67
|
+
validators.zip(validator_classes).each do |validator, expected_class|
|
68
|
+
assert_kind_of expected_class, validator
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def property_by_name(name)
|
74
|
+
Veneer(@klass).properties.find { |prop| prop.name == name } or raise "Couldn't find property #{name}."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/veneer/version.rb
CHANGED
data/test/support/helpers.rb
CHANGED
@@ -12,7 +12,16 @@ module Veneer
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
16
15
|
end # Helpers
|
16
|
+
|
17
|
+
module ActiveRecordHelper
|
18
|
+
class << self
|
19
|
+
def establish_connection
|
20
|
+
unless ::ActiveRecord::Base.connected?
|
21
|
+
::ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end # Migrations
|
25
|
+
end # ActiveRecordHelper
|
17
26
|
end # Test
|
18
27
|
end # Veneer
|
data/test/test_helper.rb
CHANGED
@@ -3,12 +3,12 @@ require 'test/unit'
|
|
3
3
|
require 'shoulda'
|
4
4
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
5
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
$LOAD_PATH.unshift(Dir.pwd)
|
6
7
|
|
8
|
+
require 'veneer'
|
7
9
|
require 'veneer/lint'
|
8
10
|
|
9
|
-
Dir[File.join(File.dirname(__FILE__),
|
10
|
-
|
11
|
-
require 'veneer'
|
11
|
+
Dir[File.join(File.dirname(__FILE__),"support", "**/*.rb")].each{|f| require f}
|
12
12
|
|
13
13
|
$validations = []
|
14
14
|
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "..", "test_helper"))
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'active_record'
|
5
|
+
rescue LoadError
|
6
|
+
require 'activerecord'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'veneer/adapters/activerecord'
|
10
|
+
|
11
|
+
|
12
|
+
Veneer::Test::ActiveRecordHelper.establish_connection
|
13
|
+
|
14
|
+
class CreateActiveRecordFoo < ActiveRecord::Migration
|
15
|
+
|
16
|
+
def self.up
|
17
|
+
create_table :active_record_foos, :force => true do |t|
|
18
|
+
t.string :name
|
19
|
+
t.string :title
|
20
|
+
t.string :description
|
21
|
+
t.integer :integer_field
|
22
|
+
t.integer :order_field1
|
23
|
+
t.integer :belonger_id
|
24
|
+
t.text :text_field
|
25
|
+
t.float :float_field
|
26
|
+
t.decimal :decimal_field
|
27
|
+
t.datetime :datetime_field
|
28
|
+
t.timestamp :timestamp_field
|
29
|
+
t.time :time_field
|
30
|
+
t.datetime :datetime_field
|
31
|
+
t.date :date_field
|
32
|
+
t.binary :binary_field
|
33
|
+
t.boolean :boolean_field
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.down
|
38
|
+
drop_table :active_record_foos
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
CreateActiveRecordFoo.up
|
43
|
+
|
44
|
+
class ActiveRecordFoo < ActiveRecord::Base
|
45
|
+
has_many :items, :class_name => "ActiveRecordFoo", :foreign_key => 'belonger_id'
|
46
|
+
belongs_to :master, :class_name => "ActiveRecordFoo", :foreign_key => 'belonger_id'
|
47
|
+
|
48
|
+
validate :check_name
|
49
|
+
|
50
|
+
def self.veneer_spec_reset!
|
51
|
+
delete_all
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_name
|
55
|
+
errors.add(:name, "Name cannot be 'invalid'") if name == "invalid"
|
56
|
+
end
|
57
|
+
|
58
|
+
def v_with_m_test
|
59
|
+
errors.add(:name, "Name cannot be v_with_m_test") if name == "v_with_m_test"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class ActiveRecordAdapterTest < ::Test::Unit::TestCase
|
64
|
+
include Veneer::Lint::Adapter
|
65
|
+
|
66
|
+
def setup
|
67
|
+
@klass = ::ActiveRecordFoo
|
68
|
+
@valid_attributes = {:name => "foo", :title => "title", :description => "description", :integer_field => 1}
|
69
|
+
@invalid_attributes = @valid_attributes.dup.merge(:name => "invalid")
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_valid_items(num)
|
73
|
+
attr = @valid_attributes
|
74
|
+
|
75
|
+
(1..num).each do |i|
|
76
|
+
ActiveRecordFoo.create(:name => "#{attr[:name]}#{i}", :title => "#{attr[:title]}#{i}", :description => "#{attr[:description]}#{i}", :integer_field => 1)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "..", "test_helper"))
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'active_record'
|
5
|
+
rescue LoadError
|
6
|
+
require 'activerecord'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'veneer/adapters/activerecord'
|
10
|
+
|
11
|
+
|
12
|
+
Veneer::Test::ActiveRecordHelper.establish_connection
|
13
|
+
|
14
|
+
class CreateActiveRecordBar < ActiveRecord::Migration
|
15
|
+
def self.up
|
16
|
+
create_table :active_record_bars, :force => true do |t|
|
17
|
+
t.string :name
|
18
|
+
t.string :string_field
|
19
|
+
t.integer :integer_field
|
20
|
+
t.text :text_field
|
21
|
+
t.float :float_field
|
22
|
+
t.decimal :decimal_field, :precision => 5, :scale => 2
|
23
|
+
t.datetime :datetime_field
|
24
|
+
t.timestamp :timestamp_field
|
25
|
+
t.time :time_field
|
26
|
+
t.datetime :datetime_field
|
27
|
+
t.date :date_field
|
28
|
+
t.binary :binary_field
|
29
|
+
t.boolean :boolean_field
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.down
|
34
|
+
drop_table :active_record_bars
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
CreateActiveRecordBar.up
|
39
|
+
|
40
|
+
class ActiveRecordBar < ActiveRecord::Base
|
41
|
+
validates_presence_of :integer_field
|
42
|
+
end
|
43
|
+
|
44
|
+
class ActiveRecordPropertiesTest < ::Test::Unit::TestCase
|
45
|
+
include Veneer::Lint::Properties
|
46
|
+
|
47
|
+
def setup
|
48
|
+
@klass = ::ActiveRecordBar
|
49
|
+
@properties_mapping = {
|
50
|
+
:id => Integer,
|
51
|
+
:string_field => String,
|
52
|
+
:text_field => String,
|
53
|
+
:integer_field => Integer,
|
54
|
+
:float_field => Float,
|
55
|
+
:decimal_field => BigDecimal,
|
56
|
+
:datetime_field => DateTime,
|
57
|
+
:timestamp_field => DateTime,
|
58
|
+
:time_field => Time,
|
59
|
+
:date_field => Date,
|
60
|
+
:binary_field => StringIO,
|
61
|
+
:boolean_field => TrueClass
|
62
|
+
}
|
63
|
+
@primary_keys = [:id]
|
64
|
+
@properties_with_length = {
|
65
|
+
:string_field => 255,
|
66
|
+
:text_field => nil
|
67
|
+
|
68
|
+
}
|
69
|
+
@properties_with_validations = {
|
70
|
+
:integer_field => [ActiveModel::Validations::PresenceValidator]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "..", "test_helper"))
|
2
|
+
require 'dm-core'
|
3
|
+
require 'dm-migrations'
|
4
|
+
require 'dm-aggregates'
|
5
|
+
require 'veneer/adapters/datamapper'
|
6
|
+
|
7
|
+
DataMapper.setup(:default, 'sqlite3::memory:')
|
8
|
+
|
9
|
+
class DMFoo
|
10
|
+
include DataMapper::Resource
|
11
|
+
include ActiveModel::Validations
|
12
|
+
|
13
|
+
property :id, Serial
|
14
|
+
property :name, String
|
15
|
+
property :title, String
|
16
|
+
property :description, String
|
17
|
+
property :integer_field, Integer, :required => false
|
18
|
+
property :order_field1, Integer
|
19
|
+
property :item_id, Integer, :required => false
|
20
|
+
property :text_field, Text
|
21
|
+
property :float_field, Float
|
22
|
+
property :decimal_field, Decimal, :scale => 0, :precision => 10
|
23
|
+
property :datetime_field, DateTime
|
24
|
+
property :time_field, Time
|
25
|
+
property :date_field, Date
|
26
|
+
property :boolean_field, Boolean
|
27
|
+
property :object_field, Object
|
28
|
+
property :discriminator_field, Discriminator
|
29
|
+
|
30
|
+
validate :check_name
|
31
|
+
|
32
|
+
has n, :items, self, :child_key => [:item_id]
|
33
|
+
belongs_to :master, self, :child_key => [:item_id]
|
34
|
+
|
35
|
+
before :save do
|
36
|
+
throw :halt unless valid?
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_name
|
40
|
+
errors.add(:base, "Invalid name") if name == "invalid"
|
41
|
+
end
|
42
|
+
|
43
|
+
def v_with_m_test
|
44
|
+
if name == "v_with_m_test"
|
45
|
+
[false, "name cannot be v_with_m_test"]
|
46
|
+
else
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
DataMapper.auto_migrate!
|
53
|
+
|
54
|
+
class DataMapperAdapterTest < ::Test::Unit::TestCase
|
55
|
+
include Veneer::Lint::Adapter
|
56
|
+
|
57
|
+
def setup
|
58
|
+
@klass = ::DMFoo
|
59
|
+
@valid_attributes = {:name => "foo", :title => "title", :description => "description", :integer_field => 1}
|
60
|
+
@invalid_attributes = @valid_attributes.dup.merge(:name => "invalid")
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_valid_items(num)
|
64
|
+
attr = @valid_attributes
|
65
|
+
|
66
|
+
(1..num).each do |i|
|
67
|
+
DMFoo.create(:name => "#{attr[:name]}#{i}", :title => "#{attr[:title]}#{i}", :description => "#{attr[:description]}#{i}", :integer_field => 1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "..", "test_helper"))
|
2
|
+
require 'dm-core'
|
3
|
+
require 'dm-migrations'
|
4
|
+
require 'veneer/adapters/datamapper'
|
5
|
+
|
6
|
+
DataMapper.setup(:default, 'sqlite3::memory:')
|
7
|
+
|
8
|
+
class DMBar
|
9
|
+
include DataMapper::Resource
|
10
|
+
include ActiveModel::Validations
|
11
|
+
|
12
|
+
validates_presence_of :integer_field
|
13
|
+
|
14
|
+
property :id, Serial, :key => true
|
15
|
+
property :another_id, Integer, :key => true
|
16
|
+
property :string_field, String, :length => 255
|
17
|
+
property :integer_field, Integer
|
18
|
+
property :text_field, Text
|
19
|
+
property :float_field, Float
|
20
|
+
property :decimal_field, Decimal, :scale => 0, :precision => 10
|
21
|
+
property :datetime_field, DateTime
|
22
|
+
property :time_field, Time
|
23
|
+
property :date_field, Date
|
24
|
+
property :boolean_field, Boolean
|
25
|
+
property :object_field, Object
|
26
|
+
property :discriminator_field, Discriminator
|
27
|
+
end
|
28
|
+
|
29
|
+
DataMapper.auto_migrate!
|
30
|
+
|
31
|
+
class DataMapperPropertiesTest < ::Test::Unit::TestCase
|
32
|
+
include Veneer::Lint::Properties
|
33
|
+
|
34
|
+
def setup
|
35
|
+
@klass = ::DMBar
|
36
|
+
@properties_mapping = {
|
37
|
+
:id => Integer, #Serial,
|
38
|
+
:string_field => String,
|
39
|
+
:text_field => String,
|
40
|
+
:integer_field => Integer,
|
41
|
+
:float_field => Float,
|
42
|
+
:decimal_field => BigDecimal,
|
43
|
+
:datetime_field => DateTime,
|
44
|
+
:time_field => Time,
|
45
|
+
:date_field => Date,
|
46
|
+
:boolean_field => TrueClass,
|
47
|
+
:object_field => Object,
|
48
|
+
:discriminator_field => Class
|
49
|
+
}
|
50
|
+
@primary_keys = [:id, :another_id]
|
51
|
+
@properties_with_length = {
|
52
|
+
:string_field => 255,
|
53
|
+
:integer_field => nil
|
54
|
+
}
|
55
|
+
@properties_with_validations = {
|
56
|
+
:integer_field => [ActiveModel::Validations::PresenceValidator]
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "..", "test_helper"))
|
2
2
|
require 'mongo_mapper'
|
3
3
|
|
4
4
|
require 'veneer/adapters/mongomapper'
|
@@ -13,9 +13,21 @@ class MongoFoo
|
|
13
13
|
key :name, String
|
14
14
|
key :title, String
|
15
15
|
key :description, String
|
16
|
+
key :integer_field, Integer
|
16
17
|
key :order_field1, Integer
|
18
|
+
key :float_field, Float
|
19
|
+
key :date_field, Date
|
20
|
+
key :boolean_field, Boolean
|
21
|
+
key :hash_field, Hash
|
22
|
+
key :set_field, Set
|
23
|
+
key :time_field, Time
|
24
|
+
key :object_field, Object
|
25
|
+
key :binary_field, Binary
|
17
26
|
|
18
|
-
|
27
|
+
validate :check_name, :on => :create
|
28
|
+
|
29
|
+
belongs_to :foo, :class_name => "MongoFoo"
|
30
|
+
many :foos, :class_name => "MongoFoo"
|
19
31
|
|
20
32
|
def check_name
|
21
33
|
errors.add(:name, "may not be invalid") if name == "invalid"
|
@@ -26,12 +38,12 @@ class MongoFoo
|
|
26
38
|
end
|
27
39
|
end
|
28
40
|
|
29
|
-
class
|
30
|
-
include Veneer::Lint
|
41
|
+
class MongoMapperAdapterTest < ::Test::Unit::TestCase
|
42
|
+
include Veneer::Lint::Adapter
|
31
43
|
|
32
44
|
def setup
|
33
45
|
@klass = ::MongoFoo
|
34
|
-
@valid_attributes = {:name => "foo", :title => "title", :description => "description"}
|
46
|
+
@valid_attributes = {:name => "foo", :title => "title", :description => "description", :integer_field => 1}
|
35
47
|
@invalid_attributes = @valid_attributes.dup.merge(:name => "invalid")
|
36
48
|
end
|
37
49
|
|
@@ -39,11 +51,23 @@ class MongoMapperVeneerTest < ::Test::Unit::TestCase
|
|
39
51
|
attr = @valid_attributes
|
40
52
|
|
41
53
|
(1..num).each do |i|
|
42
|
-
MongoFoo.create(:name => "#{attr[:name]}#{i}", :title => "#{attr[:title]}#{i}", :description => "#{attr[:description]}#{i}")
|
54
|
+
MongoFoo.create(:name => "#{attr[:name]}#{i}", :title => "#{attr[:title]}#{i}", :description => "#{attr[:description]}#{i}", :integer_field => 1)
|
43
55
|
end
|
44
56
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
57
|
+
|
58
|
+
def properties_mappings
|
59
|
+
{
|
60
|
+
:_id => String, #ObjectID
|
61
|
+
:name => String,
|
62
|
+
:integer_field => Integer,
|
63
|
+
:float_field => Float,
|
64
|
+
:date_field => Date,
|
65
|
+
:boolean_field => TrueClass,
|
66
|
+
:hash_field => Hash,
|
67
|
+
:set_field => Set,
|
68
|
+
:time_field => Time,
|
69
|
+
:object_field => Object,
|
70
|
+
:binary_field => StringIO
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|