hickey 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +1 -0
- data/LICENSE.TXT +203 -0
- data/LICENSE.txt +203 -0
- data/README.rdoc +106 -0
- data/Rakefile +129 -0
- data/TODO +53 -0
- data/hickey.gemspec +27 -0
- data/lib/hickey.rb +24 -0
- data/lib/hickey/acceptor.rb +25 -0
- data/lib/hickey/domain_detector.rb +17 -0
- data/lib/hickey/domain_detector/actions.rb +38 -0
- data/lib/hickey/domain_detector/associations.rb +80 -0
- data/lib/hickey/domain_detector/base.rb +55 -0
- data/lib/hickey/domain_detector/configurable.rb +38 -0
- data/lib/hickey/domain_detector/scopes.rb +30 -0
- data/test/belongs_to_association_test.rb +17 -0
- data/test/database_config.rb +20 -0
- data/test/enable_callbacks_test.rb +144 -0
- data/test/find_or_create_actions_test.rb +62 -0
- data/test/has_and_belongs_to_many_association_test.rb +10 -0
- data/test/has_many_association_test.rb +71 -0
- data/test/has_one_association_test.rb +53 -0
- data/test/model_association_test.rb +21 -0
- data/test/models/address.rb +5 -0
- data/test/models/author.rb +10 -0
- data/test/models/country.rb +4 -0
- data/test/models/project.rb +9 -0
- data/test/models/projects_member.rb +5 -0
- data/test/models/property_definition.rb +21 -0
- data/test/models/simple.rb +26 -0
- data/test/models/tag.rb +24 -0
- data/test/models/topic.rb +19 -0
- data/test/models/user.rb +9 -0
- data/test/models/writer.rb +9 -0
- data/test/schema.rb +88 -0
- data/test/single_model_test.rb +130 -0
- data/test/test_helper.rb +75 -0
- data/test/with_scope_test.rb +66 -0
- metadata +98 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
|
2
|
+
|
3
|
+
class ModelAssociationTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_should_return_same_with_models_loaded_from_db_after_created_models
|
6
|
+
project = Hickey.dump :project => {:identifier => 'hickey', :projects_members => [:user => {:login => 'xli'}]}
|
7
|
+
|
8
|
+
db_project = Project.find(:first)
|
9
|
+
assert_equal project, db_project
|
10
|
+
assert_equal project.projects_members.size, db_project.projects_members.size
|
11
|
+
assert_equal project.projects_members.first.user, db_project.projects_members.first.user
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_create_associated_both_has_many_association_and_belongs_to_association_models
|
15
|
+
Hickey.dump :project => {:identifier => 'hickey', :projects_members => [:user => {:login => 'xli'}]}
|
16
|
+
assert_equal 1, project.projects_members.size
|
17
|
+
assert_not_nil project.projects_members.first.user
|
18
|
+
assert_equal 'xli', project.projects_members.first.user.login
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Author < ActiveRecord::Base
|
2
|
+
set_table_name "users"
|
3
|
+
|
4
|
+
has_one :address, :foreign_key => 'user_id'
|
5
|
+
has_one :working_topic, :as => :writer, :class_name => 'Topic'
|
6
|
+
has_one :country, :through => :address
|
7
|
+
has_one :living_country, :through => :address, :source => :country
|
8
|
+
|
9
|
+
should_bypass_all_callbacks_and_validations
|
10
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Project < ActiveRecord::Base
|
2
|
+
has_many :projects_members
|
3
|
+
has_many :users, :through => :projects_members
|
4
|
+
has_many :admins, :through => :projects_members, :source => :user, :conditions => ["projects_members.admin = ?", true]
|
5
|
+
has_many :all_property_definitions, :class_name => 'PropertyDefinition'
|
6
|
+
has_many :tags
|
7
|
+
has_many :cards
|
8
|
+
should_bypass_all_callbacks_and_validations
|
9
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class PropertyDefinition < ActiveRecord::Base
|
2
|
+
belongs_to :project
|
3
|
+
end
|
4
|
+
|
5
|
+
class EnumPropertyDefinition < PropertyDefinition
|
6
|
+
has_many :enum_values, :foreign_key => 'property_definition_id'
|
7
|
+
should_bypass_all_callbacks_and_validations
|
8
|
+
end
|
9
|
+
|
10
|
+
class UserPropertyDefinition < PropertyDefinition
|
11
|
+
should_bypass_all_callbacks_and_validations
|
12
|
+
end
|
13
|
+
|
14
|
+
class EnumValue < ActiveRecord::Base
|
15
|
+
belongs_to :property_definition, :class_name => "EnumeratedPropertyDefinition", :foreign_key => "property_definition_id"
|
16
|
+
should_bypass_all_callbacks_and_validations
|
17
|
+
end
|
18
|
+
|
19
|
+
class DatePropertyDefinition < PropertyDefinition
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Simple < ActiveRecord::Base
|
2
|
+
end
|
3
|
+
|
4
|
+
class Prisoner < ActiveRecord::Base
|
5
|
+
set_table_name "users"
|
6
|
+
|
7
|
+
def login=(login)
|
8
|
+
raise 'unsupported operation'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class SimpleObserver < ActiveRecord::Observer
|
13
|
+
|
14
|
+
observe Simple
|
15
|
+
def after_save(simple)
|
16
|
+
raise 'should be bypass'
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_create(simple)
|
20
|
+
raise 'should be bypass'
|
21
|
+
end
|
22
|
+
|
23
|
+
def after_update(simple)
|
24
|
+
raise 'should be bypass'
|
25
|
+
end
|
26
|
+
end
|
data/test/models/tag.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
class Tag < ActiveRecord::Base
|
2
|
+
has_many :taggings, :class_name => '::Tagging'
|
3
|
+
belongs_to :project
|
4
|
+
before_save :validate_scopt_object
|
5
|
+
def validate_scopt_object
|
6
|
+
raise 'Project is nil' if project.nil?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Tagging < ActiveRecord::Base
|
11
|
+
belongs_to :tag
|
12
|
+
belongs_to :taggable, :polymorphic => true
|
13
|
+
should_bypass_all_callbacks_and_validations
|
14
|
+
end
|
15
|
+
|
16
|
+
class Card < ActiveRecord::Base
|
17
|
+
has_many :taggings, :as => :taggable
|
18
|
+
belongs_to :project
|
19
|
+
|
20
|
+
before_save :validate_scopt_object
|
21
|
+
def validate_scopt_object
|
22
|
+
raise 'Project is nil' if project.nil?
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Topic < ActiveRecord::Base
|
2
|
+
belongs_to :owner, :class_name => 'User', :foreign_key => :user_id
|
3
|
+
belongs_to :writer, :polymorphic => true
|
4
|
+
belongs_to :disscution
|
5
|
+
should_bypass_all_callbacks_and_validations
|
6
|
+
end
|
7
|
+
|
8
|
+
class Disscution < ActiveRecord::Base
|
9
|
+
has_one :topic
|
10
|
+
has_one :speaker, :through => :topic, :source => :writer, :source_type => 'Author'
|
11
|
+
should_bypass_all_callbacks_and_validations
|
12
|
+
end
|
13
|
+
|
14
|
+
class DisscutionBelongsToTopic < ActiveRecord::Base
|
15
|
+
belongs_to :topic
|
16
|
+
has_one :owner, :through => :topic
|
17
|
+
has_one :speaker, :through => :topic, :source => :writer, :source_type => 'Author'
|
18
|
+
should_bypass_all_callbacks_and_validations
|
19
|
+
end
|
data/test/models/user.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
has_and_belongs_to_many :countries
|
3
|
+
has_many :my_topics, :class_name => 'Topic'
|
4
|
+
has_many :projects_members
|
5
|
+
has_many :projects, :through => :projects_members
|
6
|
+
has_one :address
|
7
|
+
|
8
|
+
should_bypass_all_callbacks_and_validations
|
9
|
+
end
|
data/test/schema.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table :simples do |t|
|
3
|
+
end
|
4
|
+
|
5
|
+
create_table "projects", :force => true do |t|
|
6
|
+
t.column "identifier", :string
|
7
|
+
t.column "description", :text
|
8
|
+
t.column "created_at", :datetime
|
9
|
+
t.column "updated_at", :datetime
|
10
|
+
t.column "created_on", :datetime
|
11
|
+
t.column "updated_on", :datetime
|
12
|
+
t.column "hidden", :boolean
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table "users", :force => true do |t|
|
16
|
+
t.column "login", :string
|
17
|
+
t.column "admin", :boolean
|
18
|
+
end
|
19
|
+
|
20
|
+
create_table "topics", :force => true do |t|
|
21
|
+
t.column "user_id", :integer
|
22
|
+
t.column "writer_id", :integer
|
23
|
+
t.column "writer_type", :string
|
24
|
+
t.column "title", :string
|
25
|
+
t.column "disscution_id", :integer
|
26
|
+
end
|
27
|
+
|
28
|
+
create_table "projects_members", :force => true do |t|
|
29
|
+
t.column "user_id", :integer
|
30
|
+
t.column "project_id", :integer
|
31
|
+
t.column "admin", :boolean
|
32
|
+
end
|
33
|
+
|
34
|
+
create_table "countries_users", :id => false, :force => true do |t|
|
35
|
+
t.column "user_id", :integer, :null => false
|
36
|
+
t.column "country_id", :integer, :null => false
|
37
|
+
end
|
38
|
+
|
39
|
+
create_table "countries", :force => true do |t|
|
40
|
+
t.column "id", :integer
|
41
|
+
t.column "name", :string
|
42
|
+
end
|
43
|
+
|
44
|
+
create_table "addresses", :force => true do |t|
|
45
|
+
t.column "id", :integer
|
46
|
+
t.column "user_id", :integer
|
47
|
+
t.column "country_id", :integer
|
48
|
+
t.column "location", :string
|
49
|
+
end
|
50
|
+
|
51
|
+
create_table "disscutions", :force => true do |t|
|
52
|
+
t.column "id", :integer
|
53
|
+
end
|
54
|
+
|
55
|
+
create_table "disscution_belongs_to_topics", :force => true do |t|
|
56
|
+
t.column "id", :integer
|
57
|
+
t.column 'topic_id', :integer
|
58
|
+
end
|
59
|
+
|
60
|
+
create_table "property_definitions", :force => true do |t|
|
61
|
+
t.column "type", :string, :null => false
|
62
|
+
t.column "project_id", :integer
|
63
|
+
t.column "name", :string, :default => "", :null => false
|
64
|
+
end
|
65
|
+
|
66
|
+
create_table "enum_values", :force => true do |t|
|
67
|
+
t.column "value", :string, :default => "", :null => false
|
68
|
+
t.column "property_definition_id", :integer
|
69
|
+
t.column "position", :integer
|
70
|
+
end
|
71
|
+
|
72
|
+
create_table "tags", :force => true do |t|
|
73
|
+
t.column "name", :string, :default => "", :null => false
|
74
|
+
t.column "project_id", :integer, :null => false
|
75
|
+
end
|
76
|
+
|
77
|
+
create_table "taggings", :force => true do |t|
|
78
|
+
t.column "tag_id", :integer
|
79
|
+
t.column "taggable_id", :integer
|
80
|
+
t.column "taggable_type", :string
|
81
|
+
end
|
82
|
+
|
83
|
+
create_table "cards", :force => true do |t|
|
84
|
+
t.column "name", :string, :default => "", :null => false
|
85
|
+
t.column "project_id", :integer, :null => false
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
|
2
|
+
|
3
|
+
class SingleModelTest < Test::Unit::TestCase
|
4
|
+
def test_create_simple_model
|
5
|
+
Hickey.dump(:simple => {})
|
6
|
+
assert_equal 1, Simple.find(:all).size
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_return_created_domain
|
10
|
+
result = Hickey.dump(:simple => {})
|
11
|
+
assert_equal Simple.find(:first), result
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_return_created_domain
|
15
|
+
result = Hickey.dump(:simple => [{}])
|
16
|
+
assert_equal Simple.find(:all), result
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_return_created_domain_as_hash_when_dump_multi_models
|
20
|
+
result = Hickey.dump(:simple => {}, :user => {:login => 'xli'})
|
21
|
+
assert_equal({:simple => Simple.find(:first), :user => User.find(:first)}, result)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_bypass_validation_as_default
|
25
|
+
Simple.class_eval do
|
26
|
+
def validate
|
27
|
+
raise 'should bypass validation'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Hickey.dump(:simple => {})
|
32
|
+
ensure
|
33
|
+
Simple.class_eval do
|
34
|
+
def validate
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_create_simple_model_list
|
40
|
+
Hickey.dump(:simple => [{}, {}])
|
41
|
+
assert_equal 2, Simple.find(:all).size
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_should_bypass_callbacks
|
45
|
+
Simple.class_eval do
|
46
|
+
before_save :should_be_bypass
|
47
|
+
def should_be_bypass
|
48
|
+
raise 'should be bypass'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
Hickey.dump(:simple => {})
|
53
|
+
ensure
|
54
|
+
Simple.class_eval do
|
55
|
+
def should_be_bypass
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_bypass_notifications
|
61
|
+
SimpleObserver.instance
|
62
|
+
Hickey.dump(:simple => {})
|
63
|
+
assert_equal 1, Simple.count(:all)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_create_model_with_attributes
|
67
|
+
Hickey.dump(:user => {:login => 'xli', :admin => true})
|
68
|
+
user = User.find_by_login_and_admin('xli', true)
|
69
|
+
assert_not_nil user
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_create_model_with_nil_attribute
|
73
|
+
Hickey.dump(:user => {:login => 'xli', :admin => nil})
|
74
|
+
user = User.find_by_login_and_admin('xli')
|
75
|
+
assert_not_nil user
|
76
|
+
assert_nil user.admin
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_create_model_with_string_keys
|
80
|
+
Hickey.dump('user' => {'login' => 'xli'})
|
81
|
+
user = User.find_by_login_and_admin('xli')
|
82
|
+
assert_not_nil user
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_should_auto_set_created_at_and_updated_at_attributes
|
86
|
+
Hickey.dump(:project => {:identifier => 'hickey'})
|
87
|
+
assert_not_nil Project.find(:first).created_at
|
88
|
+
assert_not_nil Project.find(:first).updated_at
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_should_auto_set_created_on_and_updated_on_attributes
|
92
|
+
Hickey.dump(:project => {:identifier => 'hickey'})
|
93
|
+
assert_not_nil Project.find(:first).created_on
|
94
|
+
assert_not_nil Project.find(:first).updated_on
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_should_ignore_created_timestamp_attributes_when_they_have_value
|
98
|
+
t = Time.parse("1/1/2000")
|
99
|
+
Hickey.dump(:project => {:identifier => 'hickey', :created_on => t, :created_at => t})
|
100
|
+
|
101
|
+
assert_equal t, project.created_on
|
102
|
+
assert_equal t, project.created_at
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_should_update_object_specified
|
106
|
+
project = Hickey.dump(:project => {:identifier => 'hickey'})
|
107
|
+
Hickey.dump project => {:identifier => 'new project identifier'}
|
108
|
+
project.reload
|
109
|
+
|
110
|
+
assert_equal 'new project identifier', project.identifier
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_create_object_associating_with_exist_object
|
114
|
+
user = Hickey.dump(:user => {:login => 'xli', :admin => true})
|
115
|
+
Hickey.dump(:project => {:identifier => 'hickey', :users => [user]})
|
116
|
+
|
117
|
+
assert_equal 'xli', project.users.first.login
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_should_raise_error_when_create_model_failed_by_sql_error
|
121
|
+
assert_raise ActiveRecord::StatementInvalid do
|
122
|
+
Hickey.dump(:property_definition => {}) #type should not be nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_should_work_after_redefined_accessor_method_for_column
|
127
|
+
Hickey.dump(:prisoner => {:login => 'xli'})
|
128
|
+
assert_equal 'xli', prisoner.login
|
129
|
+
end
|
130
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
require 'hickey'
|
5
|
+
TEST_ROOT = File.expand_path(File.dirname(__FILE__))
|
6
|
+
ASSETS_ROOT = TEST_ROOT
|
7
|
+
FIXTURES_ROOT = TEST_ROOT
|
8
|
+
MIGRATIONS_ROOT = TEST_ROOT
|
9
|
+
SCHEMA_ROOT = TEST_ROOT
|
10
|
+
|
11
|
+
require 'active_record'
|
12
|
+
require 'active_record/fixtures'
|
13
|
+
require 'active_record/test_case'
|
14
|
+
require 'database_config'
|
15
|
+
require 'growling_test'
|
16
|
+
|
17
|
+
module Hickey
|
18
|
+
module ShouldBypassCallbacksAndValidations
|
19
|
+
def self.included(base)
|
20
|
+
base.extend(ClassMethods)
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def should_bypass_all_callbacks_and_validations
|
25
|
+
before_save :should_be_bypass
|
26
|
+
after_save :should_be_bypass
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate
|
31
|
+
should_be_bypass
|
32
|
+
end
|
33
|
+
|
34
|
+
def should_be_bypass
|
35
|
+
raise 'should be bypass'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
ActiveRecord::Base.send(:include, Hickey::ShouldBypassCallbacksAndValidations)
|
41
|
+
|
42
|
+
require 'models/projects_member'
|
43
|
+
require 'models/user'
|
44
|
+
require 'models/project'
|
45
|
+
require 'models/country'
|
46
|
+
require 'models/topic'
|
47
|
+
require 'models/simple'
|
48
|
+
require 'models/address'
|
49
|
+
require 'models/author'
|
50
|
+
require 'models/writer'
|
51
|
+
require 'models/property_definition'
|
52
|
+
require 'models/tag'
|
53
|
+
|
54
|
+
class Test::Unit::TestCase
|
55
|
+
self.use_transactional_fixtures = true
|
56
|
+
|
57
|
+
def method_missing(method, *args)
|
58
|
+
if models.include?(method.to_s)
|
59
|
+
method.to_s.classify.constantize.find(:first)
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def models
|
66
|
+
return @models if defined?(@models)
|
67
|
+
@models = []
|
68
|
+
ObjectSpace.each_object(Class) do |klass|
|
69
|
+
if(ActiveRecord::Base > klass)
|
70
|
+
@models << klass.name.underscore
|
71
|
+
end
|
72
|
+
end
|
73
|
+
@models
|
74
|
+
end
|
75
|
+
end
|