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.
- 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
|