hickey 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.
@@ -0,0 +1,38 @@
1
+ module Hickey
2
+ module DomainDetector
3
+ module Configurable
4
+ def self.included(base)
5
+ base.class_eval do
6
+ @@configurations = {}
7
+ cattr_accessor :configurations, :instance_writer => false
8
+ alias_method_chain :new_instance, :configuration
9
+ end
10
+ end
11
+
12
+ private
13
+ def new_instance_with_configuration(class_or_instance, record)
14
+ instance = new_instance_without_configuration(class_or_instance, record)
15
+ instance.instance_eval do
16
+ def valid_without_callbacks?
17
+ true
18
+ end
19
+ end
20
+ unless configuration_of(instance)[:callbacks] == :all
21
+ callbacks = configuration_of(instance)[:callbacks] || []
22
+ instance.instance_eval <<-"end_eval"
23
+ alias :original_callback :callback
24
+ def callback(method)
25
+ [#{callbacks.collect(&:inspect).join(',')}].include?(method) ? original_callback(method) : true
26
+ end
27
+ end_eval
28
+ end
29
+ instance
30
+ end
31
+
32
+ def configuration_of(instance)
33
+ klass = instance.class
34
+ @@configurations[klass.name.underscore.to_sym] || @@configurations[klass.base_class.name.underscore.to_sym] || {}
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ module Hickey
2
+ module DomainDetector
3
+ module Scopes
4
+ def self.included(base)
5
+ base.send(:alias_method_chain, :visit_hash, :scopes)
6
+ base.send(:alias_method_chain, :new_instance, :scopes)
7
+ end
8
+
9
+ def visit_hash_with_scopes(attribute, record)
10
+ scopes.each do |foreign_key, owner|
11
+ record[foreign_key] = owner.id unless record[foreign_key]
12
+ end
13
+ returning visit_hash_without_scopes(attribute, record) do |instance|
14
+ scopes.delete instance.class.name.foreign_key
15
+ end
16
+ end
17
+
18
+ def new_instance_with_scopes(class_or_instance, record)
19
+ returning new_instance_without_scopes(class_or_instance, record) do |instance|
20
+ scopes[instance.class.name.foreign_key] = instance
21
+ end
22
+ end
23
+
24
+ private
25
+ def scopes
26
+ @scopes ||= {}
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ class BelongsToAssociationTest < Test::Unit::TestCase
4
+ def test_create_associated_belongs_to_model
5
+ Hickey.dump :projects_member => {:user => {:login => 'xli'}}
6
+ assert_not_nil projects_member.user
7
+ assert_equal 'xli', projects_member.user.login
8
+ end
9
+
10
+ def test_create_associated_belongs_to_model_with_class_name
11
+ Hickey.dump :topic => {:title => 'Bla bla...', :owner => {:login => 'xli'}}
12
+
13
+ topic = Topic.find(:first)
14
+ assert_not_nil topic.owner
15
+ assert_equal 'xli', topic.owner.login
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'logger'
2
+
3
+ RAILS_DEFAULT_LOGGER = Logger.new(File.expand_path(File.dirname(__FILE__)) + '/debug.log')
4
+ RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
5
+ ActiveRecord::Base.logger = RAILS_DEFAULT_LOGGER
6
+
7
+ ActiveRecord::Base.configurations = {
8
+ 'test' => {
9
+ :database => ":memory:",
10
+ :adapter => 'sqlite3',
11
+ :timeout => 500
12
+ }
13
+ }
14
+
15
+ ActiveRecord::Base.establish_connection 'test'
16
+
17
+ ActiveRecord::Base.silence do
18
+ ActiveRecord::Migration.verbose = false
19
+ load File.join(File.dirname(__FILE__), 'schema.rb')
20
+ end
@@ -0,0 +1,144 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ class EnableCallbacksTest < Test::Unit::TestCase
4
+
5
+ def teardown
6
+ Hickey.setup.clear
7
+ Simple.public_instance_methods(false).each do |method|
8
+ next if method == 'id'
9
+ Simple.class_eval "def #{method};end"
10
+ end
11
+ end
12
+
13
+ def test_configuration_setup_should_not_effect_other_instances
14
+ Hickey.setup(:simple => {:callbacks => [:after_save]})
15
+ simple = Hickey.dump(:simple => {})
16
+ assert simple.respond_to?(:original_callback, true)
17
+
18
+ simple = Simple.find(:all).first
19
+ assert !simple.respond_to?(:original_callback, true)
20
+ end
21
+
22
+ def test_invoke_before_save_and_after_save_after_configured_all_callbacks
23
+ Hickey.setup(:simple => {:callbacks => :all})
24
+ Simple.class_eval do
25
+ before_save :create_user_before_save
26
+ after_save :create_user_after_save
27
+ def create_user_after_save
28
+ Hickey.dump(:user => {:login => 'create_user_after_save'})
29
+ end
30
+ def create_user_before_save
31
+ Hickey.dump(:user => {:login => 'create_user_before_save'})
32
+ end
33
+ def validate
34
+ raise 'should bypass'
35
+ end
36
+ end
37
+
38
+ Hickey.dump(:simple => {})
39
+
40
+ assert_equal ['create_user_before_save', 'create_user_after_save'].sort, User.find(:all).collect(&:login).sort
41
+ end
42
+
43
+ def test_invoke_before_validation_on_create_after_configured_all_callbacks
44
+ Hickey.setup(:simple => {:callbacks => :all})
45
+ Simple.class_eval do
46
+ before_validation_on_create :create_user_before_validation_on_create
47
+ def create_user_before_validation_on_create
48
+ Hickey.dump(:user => {:login => 'create_user_before_validation_on_create'})
49
+ end
50
+ def validate
51
+ raise 'should bypass'
52
+ end
53
+ end
54
+
55
+ Hickey.dump(:simple => {})
56
+ assert_equal ['create_user_before_validation_on_create'], User.find(:all).collect(&:login)
57
+ end
58
+
59
+ def test_invoke_before_validation_after_configured_all_callbacks
60
+ Hickey.setup(:simple => {:callbacks => :all})
61
+ Simple.class_eval do
62
+ before_validation :create_user_before_validation
63
+ def create_user_before_validation
64
+ Hickey.dump(:user => {:login => 'create_user_before_validation'})
65
+ end
66
+ def validate
67
+ raise 'should bypass'
68
+ end
69
+ end
70
+
71
+ Hickey.dump(:simple => {})
72
+ assert_equal ['create_user_before_validation'], User.find(:all).collect(&:login)
73
+ end
74
+
75
+ def test_invoke_before_validation_after_configured_all_callbacks
76
+ Hickey.setup(:simple => {:callbacks => :all})
77
+ Simple.class_eval do
78
+ after_validation :create_user_after_validation
79
+ def create_user_after_validation
80
+ Hickey.dump(:user => {:login => 'create_user_after_validation'})
81
+ end
82
+ def validate
83
+ raise 'should bypass'
84
+ end
85
+ end
86
+
87
+ Hickey.dump(:simple => {})
88
+ assert_equal ['create_user_after_validation'], User.find(:all).collect(&:login)
89
+ end
90
+
91
+ def test_should_not_callback_before_validation_on_create_if_pass_in_existed_model
92
+ simple = Hickey.dump(:simple => {})
93
+ Hickey.setup(:simple => {:callbacks => :all})
94
+ Simple.class_eval do
95
+ before_validation_on_create :create_user_before_validation_on_create
96
+ def create_user_before_validation_on_create
97
+ Hickey.dump(:user => {:login => 'create_user_before_validation_on_create'})
98
+ end
99
+ def validate
100
+ raise 'should bypass'
101
+ end
102
+ end
103
+
104
+ Hickey.dump(simple => {})
105
+ assert_equal [], User.find(:all).collect(&:login)
106
+ end
107
+
108
+ def test_should_enable_configuration_of_invoking_all_callbacks_for_all_subclasses
109
+ Hickey.setup(:property_definition => {:callbacks => :all})
110
+ DatePropertyDefinition.class_eval do
111
+ after_validation :create_user_after_validation
112
+ def create_user_after_validation
113
+ Hickey.dump(:user => {:login => 'create_user_after_validation'})
114
+ end
115
+ def validate
116
+ raise 'should bypass'
117
+ end
118
+ end
119
+
120
+ Hickey.dump(:property_definition => {:type => 'DatePropertyDefinition'})
121
+
122
+ assert_equal ['create_user_after_validation'], User.find(:all).collect(&:login)
123
+ end
124
+
125
+ def test_invoke_callback_specified_after_configured
126
+ Hickey.setup(:simple => {:callbacks => [:after_create, :before_create]})
127
+ Simple.class_eval do
128
+ before_create :create_user_before_create
129
+ after_create :create_user_after_create
130
+ def create_user_before_create
131
+ Hickey.dump(:user => {:login => 'create_user_before_create'})
132
+ end
133
+ def create_user_after_create
134
+ Hickey.dump(:user => {:login => 'create_user_after_create'})
135
+ end
136
+ def validate
137
+ raise 'should bypass'
138
+ end
139
+ end
140
+
141
+ Hickey.dump(:simple => {})
142
+ assert_equal ['create_user_after_create', 'create_user_before_create'].sort, User.find(:all).collect(&:login).sort
143
+ end
144
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ class FindOrCreateActionsTest < Test::Unit::TestCase
4
+ def test_create_action
5
+ assert Hickey.dump(:simple => {:create => {}})
6
+ end
7
+
8
+ def test_create_multi_models
9
+ result = Hickey.dump(:simple => {:create => {}}, :user => {:create => {:login => 'xli'}})
10
+ assert_equal({:simple => Simple.find(:first), :user => User.find(:first)}, result)
11
+ end
12
+
13
+ def test_create_association_model
14
+ Hickey.dump(:project => {:identifier => 'hickey', :users => [{:create => {:login => 'xli', :admin => true}}]})
15
+
16
+ assert_equal 'xli', project.users.first.login
17
+ end
18
+
19
+ def test_find_action
20
+ simple1 = Hickey.dump(:simple => {})
21
+ simple2 = Hickey.dump(:simple => {:find => {}})
22
+ assert_equal simple1, simple2
23
+ assert_equal 1, Simple.count(:all)
24
+ end
25
+
26
+ def test_find_by_attributes
27
+ Hickey.dump(:user => {:login => 'mm'})
28
+ user1 = Hickey.dump(:user => {:login => 'xli'})
29
+ user2 = Hickey.dump(:user => {:find => {:login => 'xli'}})
30
+ assert_equal user1, user2
31
+ assert_equal 2, User.count(:all)
32
+ end
33
+
34
+ def test_should_find_model_without_association
35
+ Hickey.dump(:project => {:identifier => 'hickey', :users => [{:login => 'xli', :admin => true}]})
36
+
37
+ project = Hickey.dump(:project => {:find => {:identifier => 'hickey', :users => [{:login => 'xli', :admin => true}]}})
38
+ assert_equal 'hickey', project.identifier
39
+ assert_equal 'xli', project.users.first.login
40
+ assert_equal 1, Project.count(:all)
41
+
42
+ assert_equal 2, User.count(:all)
43
+ end
44
+
45
+ def test_find_model_with_finding_association
46
+ Hickey.dump(:project => {:identifier => 'hickey', :users => [{:login => 'xli', :admin => true}]})
47
+
48
+ project = Hickey.dump(:project => {:find => {:identifier => 'hickey', :users => [{:find => {:login => 'xli', :admin => true}}]}})
49
+ assert_equal 'hickey', project.identifier
50
+ assert_equal 'xli', project.users.first.login
51
+ assert_equal 1, Project.count(:all)
52
+
53
+ assert_equal 1, User.count(:all)
54
+ end
55
+
56
+ def test_find_or_create
57
+ Hickey.dump(:simple => {:find_or_create => {}})
58
+ assert_equal 1, Simple.count(:all)
59
+ Hickey.dump(:simple => {:find_or_create => {}})
60
+ assert_equal 1, Simple.count(:all)
61
+ end
62
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ class HasAndBelongsToManyAssociationTest < Test::Unit::TestCase
4
+ def test_create_associated_has_and_belongs_to_many_models
5
+ Hickey.dump :user => {:login => 'xli', :countries => [{:name => 'China'}]}
6
+
7
+ assert_equal 1, user.countries.size
8
+ assert_equal 'China', user.countries.first.name
9
+ end
10
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ class HasManyAssociationTest < Test::Unit::TestCase
4
+
5
+ def test_create_associated_empty_models
6
+ Hickey.dump(:project => {:identifier => 'hickey', :projects_members => []})
7
+ assert_equal [], project.projects_members
8
+ end
9
+
10
+ def test_create_associated_many_existed_models
11
+ Hickey.dump :project => {:identifier => 'hickey', :projects_members => [{}, {}]}
12
+
13
+ assert_equal 2, project.projects_members.size
14
+ assert_not_nil project.projects_members.first
15
+ assert_not_nil project.projects_members.last
16
+ end
17
+
18
+ def test_option_class_name
19
+ Hickey.dump :user => {:login => 'xli', :my_topics => [{:title => 'Bla bla...'}]}
20
+ assert_equal 1, user.my_topics.size
21
+ assert_equal 'Bla bla...', user.my_topics.first.title
22
+ end
23
+
24
+ def test_option_through_models
25
+ Hickey.dump :project => {:identifier => 'hickey', :users => [{:login => 'xli'}]}
26
+ assert_equal 1, project.projects_members.size
27
+ assert_not_nil project.projects_members.first.user
28
+ assert_equal 'xli', project.projects_members.first.user.login
29
+
30
+ assert_equal 'xli', project.users.first.login
31
+ end
32
+
33
+ def test_option_foreign_key
34
+ Hickey.dump :writer => {:login => 'xli', :addresses => [{:location => 'BeiJing'}, {:location => 'ShangHai'}]}
35
+ assert_equal 2, writer.addresses.size
36
+ assert_equal ['BeiJing', 'ShangHai'].sort, writer.addresses.collect(&:location).sort
37
+ end
38
+
39
+ def test_option_as
40
+ Hickey.dump :writer => {:topics => [{:title => 'Hello world'}, {:title => 'Hello world again'}]}
41
+ assert_equal ['Hello world', 'Hello world again'].sort, writer.topics.collect(&:title).sort
42
+ end
43
+
44
+ def test_option_through_and_as
45
+ Hickey.dump :writer => {:login => 'writer', :disscutions => [{:speaker => {:login => 'xli'}}, {:speaker => {:login => 'oo'}}]}
46
+ speakers = writer.disscutions.collect(&:speaker)
47
+ assert_equal ['writer', 'xli', 'oo'].sort, User.find(:all).collect(&:login).sort
48
+ assert_equal 2, speakers.size
49
+ speakers = [speakers.first.login, speakers.last.login]
50
+ assert_equal ['xli', 'oo'].sort, speakers.sort
51
+ end
52
+
53
+ def test_specifying_type_attribute_for_single_table_inheritance
54
+ Hickey.dump :project => {:all_property_definitions => [{:name => 'status', :type => 'EnumPropertyDefinition'}, {:name => 'owner', :type => 'UserPropertyDefinition'}]}
55
+
56
+ assert_equal ['status', 'owner'].sort, project.all_property_definitions.collect(&:name).sort
57
+ end
58
+
59
+ def test_subclass_relationship_of_single_table_inheritance
60
+ Hickey.dump :property_definition => {:type => 'EnumPropertyDefinition', :enum_values => [{:value => 'new'}, {:value => 'open'}]}
61
+
62
+ assert_equal ['new', 'open'].sort, property_definition.enum_values.collect(&:value).sort
63
+ end
64
+
65
+ def test_should_raise_active_record_subclass_not_found_error_when_cant_find_subclass
66
+ assert_raise ActiveRecord::SubclassNotFound do
67
+ Hickey.dump :property_definition => {:type => 'NotPropertyDefinition'}
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ class HasOneAssociationTest < Test::Unit::TestCase
4
+ def test_user_has_one_address
5
+ Hickey.dump :user => {:address => {:location => 'BeiJing'}}
6
+ assert_equal 'BeiJing', user.address.location
7
+ end
8
+
9
+ def test_with_option_foreign_key
10
+ Hickey.dump :author => {:address => {:location => 'BeiJing'}}
11
+ assert_equal 'BeiJing', author.address.location
12
+ end
13
+
14
+ def test_with_option_as_and_class_name
15
+ Hickey.dump :author => {:working_topic => {:title => 'Hello world'}}
16
+ assert_equal 'Hello world', author.working_topic.title
17
+ end
18
+
19
+ def test_with_option_through_has_one
20
+ Hickey.dump :author => {:country => {:name => 'China'}}
21
+ assert_equal 'China', author.country.name
22
+ end
23
+
24
+ def test_with_option_through_source
25
+ Hickey.dump :author => {:living_country => {:name => 'China'}}
26
+ assert_equal 'China', author.living_country.name
27
+ end
28
+
29
+ def test_with_option_through_source_type
30
+ Hickey.dump :disscution => {:speaker => {:login => 'xli'}}
31
+ assert_equal 'xli', disscution.speaker.login
32
+ end
33
+
34
+ def test_through_and_as
35
+ # fail('do we need this?')
36
+ end
37
+
38
+ #active_record couldn't work on has_one :through belongs to
39
+ def xtest_with_option_through_belongs_to
40
+ user = User.create(:login => 'xli')
41
+ DisscutionBelongsToTopic.create!(:owner => user)
42
+ assert_equal 'xli', d.owner.login
43
+
44
+ Hickey.dump :disscution_belongs_to_topic => {:owner => {:login => 'xli'}}
45
+ assert_equal 'xli', disscution_belongs_to_topic.owner.login
46
+ end
47
+
48
+ #active_record couldn't work on has_one :through belongs to
49
+ def xtest_with_option_through_source_type
50
+ Hickey.dump :disscution_belongs_to_topic => {:speaker => {:login => 'xli'}}
51
+ assert_equal 'xli', disscution_belongs_to_topic.speaker.login
52
+ end
53
+ end