schemaker 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -6
- data/VERSION +1 -1
- data/lib/schemaker/models/base_model.rb +195 -193
- data/lib/schemaker/models/join_model.rb +29 -27
- data/lib/schemaker/models/object_model.rb +22 -20
- data/lib/schemaker/models/subject_model.rb +28 -26
- data/lib/schemaker/models.rb +2 -0
- data/lib/schemaker.rb +6 -11
- data/schemaker.gemspec +13 -19
- data/spec/models_helper.rb +0 -1
- data/spec/schemaker/model/join_spec.rb +3 -3
- data/spec/schemaker/model/object_spec.rb +4 -4
- data/spec/schemaker/model/subject_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -0
- metadata +36 -58
data/Gemfile
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
source :rubygems
|
2
2
|
|
3
|
-
gem '
|
4
|
-
gem 'require_all', '~> 1.2.0'
|
3
|
+
gem 'sweetloader', '>= 0.1.1'
|
5
4
|
|
6
5
|
group :development, :test do
|
7
6
|
gem "activerecord", ">= 3.0.1"
|
8
7
|
gem "rspec", ">= 2.6.0"
|
8
|
+
gem 'database_cleaner', '~> 0.6.8', :git => "git://github.com/kristianmandrup/database_cleaner.git"
|
9
|
+
|
10
|
+
gem 'sqlite3'
|
11
|
+
gem 'cutter' # for inspection!
|
12
|
+
|
13
|
+
# gem 'require_all', '~> 1.2.0'
|
14
|
+
end
|
15
|
+
|
16
|
+
group :development do
|
9
17
|
gem "bundler", ">= 1"
|
10
18
|
gem "jeweler", ">= 1.6"
|
11
19
|
gem "rcov", ">= 0"
|
12
20
|
gem 'yard'
|
13
|
-
gem 'database_cleaner', '~> 0.6.8', :git => "git://github.com/kristianmandrup/database_cleaner.git"
|
14
|
-
gem 'sqlite3'
|
15
|
-
gem 'shoulda'
|
16
|
-
gem 'cutter'
|
17
21
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
@@ -6,199 +6,201 @@
|
|
6
6
|
# Each type of model to be configured shares some common functionality and state, that is encapsulated here for reuse
|
7
7
|
#
|
8
8
|
module Schemaker
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
class Models
|
10
|
+
class BaseModel
|
11
|
+
attr_accessor :models, :my_class
|
12
|
+
attr_reader :logs # can be used to later check which relationships were set up
|
13
|
+
|
14
|
+
# @param [Schema::Models] each model needs to have access to the collection of models it may need to create relations with
|
15
|
+
# @param [Class] each model must have a reference to the Class it aims to configure!
|
16
|
+
def initialize models, my_class
|
17
|
+
raise ArgumentError, "The first argument must be a Schema::Models instance, was #{models}" if !models.is_a?(Schemaker::Models)
|
18
|
+
raise ArgumentError, "The second argument must be the Class that is to be configured, was #{my_class}" if !my_class.is_a?(Class)
|
19
|
+
|
20
|
+
@models = models
|
21
|
+
@my_class = my_class
|
22
|
+
@logs = []
|
23
|
+
end
|
24
|
+
|
25
|
+
# The models :subject and :object must both be configured
|
26
|
+
# with a has_many relationship to the join model which the has_many :through references
|
27
|
+
def configure
|
28
|
+
create_has_many :join, class_name_option(join_class)
|
29
|
+
end
|
30
|
+
|
31
|
+
# The class name of the Class to be configured
|
32
|
+
# @return [String] class name
|
33
|
+
def clazz_name
|
34
|
+
my_class.to_s
|
35
|
+
end
|
36
|
+
alias_method :my_class_name, :clazz_name
|
37
|
+
|
38
|
+
def self.model_types
|
39
|
+
[:object, :subject, :join]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Generate convenience methods for: :object, :subject, :join
|
43
|
+
# - object_model
|
44
|
+
# - object_class
|
45
|
+
# - object_class_name
|
46
|
+
|
47
|
+
model_types.each do |model_type|
|
48
|
+
class_eval %{
|
49
|
+
def #{model_type}_model
|
50
|
+
models.#{model_type}_model
|
51
|
+
end
|
52
|
+
|
53
|
+
def #{model_type}_class
|
54
|
+
models.#{model_type}_class
|
55
|
+
end
|
56
|
+
|
57
|
+
def #{model_type}_class_name
|
58
|
+
#{model_type}_class.clazz_name
|
59
|
+
end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
# Is global logging turned on
|
66
|
+
def log_on?
|
67
|
+
Schemaker.log_on?
|
68
|
+
end
|
69
|
+
|
70
|
+
# Create a 'belongs_to' relationship on the model (Class)
|
71
|
+
# Example:
|
72
|
+
# Role.belongs_to :user, :class_name => 'User'
|
73
|
+
def create_belongs_to clazz, options = {}
|
74
|
+
make_relationship :belongs_to, clazz, options.merge(:key => singular_key(clazz))
|
75
|
+
end
|
76
|
+
|
77
|
+
# Create a 'has_many' relationship on the model (Class)
|
78
|
+
# Example:
|
79
|
+
# User.has_many :roles, :class_name => 'Role'
|
80
|
+
def create_has_many clazz, options = {}
|
81
|
+
make_relationship :has_many, clazz, options
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create a 'has_many' relationship on the model (Class)
|
85
|
+
# Example:
|
86
|
+
# User.has_one :roles, :class_name => 'Role'
|
87
|
+
def create_has_one clazz, options = {}
|
88
|
+
make_relationship :has_one, clazz, options.merge(:key => singular_key(clazz))
|
89
|
+
end
|
90
|
+
|
91
|
+
# Create a 'has_many :through' relationship on the model (Class)
|
92
|
+
# Example:
|
93
|
+
# User.has_many :roles, :class_name => 'Role', :through => 'UsersRoles'
|
94
|
+
def create_has_many_through clazz, options = {}
|
95
|
+
create_has_many clazz, through_options(options)
|
96
|
+
end
|
97
|
+
|
98
|
+
# To setup symmetrical has_and_belongs_to_many relationship:
|
99
|
+
#
|
100
|
+
# Example:
|
101
|
+
#
|
102
|
+
# class UserAccount < ActiveRecord::Base
|
103
|
+
# has_and_belongs_to_many :troles, :class_name => 'Role'
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# class Role < ActiveRecord::Base
|
107
|
+
# has_and_belongs_to_many :user_accounts, :class_name => 'User'
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
def has_and_belongs_many to_clazz, options = {}
|
111
|
+
make_relationship :has_and_belongs_to_many, to_clazz, options[:from]
|
112
|
+
to_clazz.make_relationship :has_and_belongs_to_many, my_class, options[:to]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Creates a given type of relationship
|
116
|
+
# @param [Symbol] the type of relationship, fx :has_many
|
117
|
+
# @param [Class, Symbol] the Class that is the object of the relationship, fx Role for a User.has_many relationship
|
118
|
+
# @param [Hash] any extra relationship options, fx for a :through relationship, or to indicate :class_name etc.
|
119
|
+
def make_relationship relationship_name, clazz, options = {}
|
120
|
+
# inspect!(binding)
|
121
|
+
key_name = (options.delete(:key) || key(clazz)).to_sym # first must be a sym too
|
122
|
+
opts_str = options.empty? ? '' : options.inspect.insert(0, ', ').gsub(/[{}]/ , '')
|
123
|
+
log "#{my_class_name}.#{relationship_name} :#{key_name}#{opts_str}" if log_on?
|
124
|
+
|
125
|
+
return my_class.send(relationship_name, key_name) if options.empty?
|
126
|
+
|
127
|
+
my_class.send(relationship_name, key_name, options)
|
128
|
+
end
|
129
|
+
|
130
|
+
# creates a key for a given type
|
131
|
+
# @param type [Symbol] - either :object, :subject or :join
|
132
|
+
def key type
|
133
|
+
models.key type
|
134
|
+
end
|
135
|
+
|
136
|
+
def get_class type
|
137
|
+
models.get_class type
|
138
|
+
end
|
139
|
+
|
140
|
+
def singular_key cls_name
|
141
|
+
model = get_class(cls_name)
|
142
|
+
model.to_s.singularize.underscore
|
143
|
+
end
|
144
|
+
|
145
|
+
def make_key cls_name
|
146
|
+
models.make_key cls_name
|
147
|
+
end
|
148
|
+
|
149
|
+
# log the relationship being added
|
150
|
+
# - to STDOUT via puts
|
151
|
+
# - to a logs list
|
152
|
+
def log msg
|
153
|
+
puts msg
|
154
|
+
logs << msg
|
155
|
+
end
|
156
|
+
|
157
|
+
# sets up the :source relationship option, typically for a has_many through relationship
|
158
|
+
def source_option cls_name
|
159
|
+
model = get_class(cls_name)
|
160
|
+
{:source => source(model) }
|
161
|
+
end
|
162
|
+
|
163
|
+
# sets up the :class_name relationship option for a given class (model
|
164
|
+
# @param [Class, String] the class to point to
|
165
|
+
def class_name_option cls_name
|
166
|
+
model = get_class(cls_name)
|
167
|
+
{:class_name => model.to_s }
|
168
|
+
end
|
169
|
+
|
170
|
+
# sets up the :through relationship option, always points to the join model
|
171
|
+
def through_option
|
172
|
+
{:through => join_model.through_key }
|
173
|
+
end
|
174
|
+
|
175
|
+
# sets up the :foreign_key relationship option
|
176
|
+
# the foreign key name should always correspond to 'my own' class name
|
177
|
+
def foreign_key_option cls_name
|
178
|
+
model = get_class(cls_name)
|
179
|
+
{:foreign_key => foreign_key(model) }
|
180
|
+
end
|
181
|
+
|
182
|
+
# sets up the full :through relationship options
|
183
|
+
# Example:
|
184
|
+
# :class_name => 'Role', :through => 'UsersRoles', :source => :role, :foreign_key => :user_id)
|
185
|
+
def through_options cls_name
|
186
|
+
model = get_class(cls_name)
|
187
|
+
through_option.merge(source_option model).merge(class_name_option model)
|
188
|
+
end
|
189
|
+
|
190
|
+
# creates the source
|
191
|
+
# Role becomes :role
|
192
|
+
def source cls_name
|
193
|
+
model = get_class(cls_name)
|
194
|
+
model.to_s.underscore.singularize.to_sym
|
195
|
+
end
|
196
|
+
|
197
|
+
# creates the foreign key
|
198
|
+
# RefManyAccount becomes :account_id
|
199
|
+
def foreign_key cls_name
|
200
|
+
model = get_class(cls_name)
|
201
|
+
name = model.to_s.underscore.split('_').last.singularize
|
202
|
+
:"#{name}_id"
|
203
|
+
end
|
22
204
|
end
|
23
|
-
|
24
|
-
# The models :subject and :object must both be configured
|
25
|
-
# with a has_many relationship to the join model which the has_many :through references
|
26
|
-
def configure
|
27
|
-
create_has_many :join, class_name_option(join_class)
|
28
|
-
end
|
29
|
-
|
30
|
-
# The class name of the Class to be configured
|
31
|
-
# @return [String] class name
|
32
|
-
def clazz_name
|
33
|
-
my_class.to_s
|
34
|
-
end
|
35
|
-
alias_method :my_class_name, :clazz_name
|
36
|
-
|
37
|
-
def self.model_types
|
38
|
-
[:object, :subject, :join]
|
39
|
-
end
|
40
|
-
|
41
|
-
# Generate convenience methods for: :object, :subject, :join
|
42
|
-
# - object_model
|
43
|
-
# - object_class
|
44
|
-
# - object_class_name
|
45
|
-
|
46
|
-
model_types.each do |model_type|
|
47
|
-
class_eval %{
|
48
|
-
def #{model_type}_model
|
49
|
-
models.#{model_type}_model
|
50
|
-
end
|
51
|
-
|
52
|
-
def #{model_type}_class
|
53
|
-
models.#{model_type}_class
|
54
|
-
end
|
55
|
-
|
56
|
-
def #{model_type}_class_name
|
57
|
-
#{model_type}_class.clazz_name
|
58
|
-
end
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
protected
|
63
|
-
|
64
|
-
# Is global logging turned on
|
65
|
-
def log_on?
|
66
|
-
Schemaker.log_on?
|
67
|
-
end
|
68
|
-
|
69
|
-
# Create a 'belongs_to' relationship on the model (Class)
|
70
|
-
# Example:
|
71
|
-
# Role.belongs_to :user, :class_name => 'User'
|
72
|
-
def create_belongs_to clazz, options = {}
|
73
|
-
make_relationship :belongs_to, clazz, options.merge(:key => singular_key(clazz))
|
74
|
-
end
|
75
|
-
|
76
|
-
# Create a 'has_many' relationship on the model (Class)
|
77
|
-
# Example:
|
78
|
-
# User.has_many :roles, :class_name => 'Role'
|
79
|
-
def create_has_many clazz, options = {}
|
80
|
-
make_relationship :has_many, clazz, options
|
81
|
-
end
|
82
|
-
|
83
|
-
# Create a 'has_many' relationship on the model (Class)
|
84
|
-
# Example:
|
85
|
-
# User.has_one :roles, :class_name => 'Role'
|
86
|
-
def create_has_one clazz, options = {}
|
87
|
-
make_relationship :has_one, clazz, options.merge(:key => singular_key(clazz))
|
88
|
-
end
|
89
|
-
|
90
|
-
# Create a 'has_many :through' relationship on the model (Class)
|
91
|
-
# Example:
|
92
|
-
# User.has_many :roles, :class_name => 'Role', :through => 'UsersRoles'
|
93
|
-
def create_has_many_through clazz, options = {}
|
94
|
-
create_has_many clazz, through_options(options)
|
95
|
-
end
|
96
|
-
|
97
|
-
# To setup symmetrical has_and_belongs_to_many relationship:
|
98
|
-
#
|
99
|
-
# Example:
|
100
|
-
#
|
101
|
-
# class UserAccount < ActiveRecord::Base
|
102
|
-
# has_and_belongs_to_many :troles, :class_name => 'Role'
|
103
|
-
# end
|
104
|
-
#
|
105
|
-
# class Role < ActiveRecord::Base
|
106
|
-
# has_and_belongs_to_many :user_accounts, :class_name => 'User'
|
107
|
-
# end
|
108
|
-
#
|
109
|
-
def has_and_belongs_many to_clazz, options = {}
|
110
|
-
make_relationship :has_and_belongs_to_many, to_clazz, options[:from]
|
111
|
-
to_clazz.make_relationship :has_and_belongs_to_many, my_class, options[:to]
|
112
|
-
end
|
113
|
-
|
114
|
-
# Creates a given type of relationship
|
115
|
-
# @param [Symbol] the type of relationship, fx :has_many
|
116
|
-
# @param [Class, Symbol] the Class that is the object of the relationship, fx Role for a User.has_many relationship
|
117
|
-
# @param [Hash] any extra relationship options, fx for a :through relationship, or to indicate :class_name etc.
|
118
|
-
def make_relationship relationship_name, clazz, options = {}
|
119
|
-
# inspect!(binding)
|
120
|
-
key_name = (options.delete(:key) || key(clazz)).to_sym # first must be a sym too
|
121
|
-
opts_str = options.empty? ? '' : options.inspect.insert(0, ', ').gsub(/[{}]/ , '')
|
122
|
-
log "#{my_class_name}.#{relationship_name} :#{key_name}#{opts_str}" if log_on?
|
123
|
-
|
124
|
-
return my_class.send(relationship_name, key_name) if options.empty?
|
125
|
-
|
126
|
-
my_class.send(relationship_name, key_name, options)
|
127
|
-
end
|
128
|
-
|
129
|
-
# creates a key for a given type
|
130
|
-
# @param type [Symbol] - either :object, :subject or :join
|
131
|
-
def key type
|
132
|
-
models.key type
|
133
|
-
end
|
134
|
-
|
135
|
-
def get_class type
|
136
|
-
models.get_class type
|
137
|
-
end
|
138
|
-
|
139
|
-
def singular_key cls_name
|
140
|
-
model = get_class(cls_name)
|
141
|
-
model.to_s.singularize.underscore
|
142
|
-
end
|
143
|
-
|
144
|
-
def make_key cls_name
|
145
|
-
models.make_key cls_name
|
146
|
-
end
|
147
|
-
|
148
|
-
# log the relationship being added
|
149
|
-
# - to STDOUT via puts
|
150
|
-
# - to a logs list
|
151
|
-
def log msg
|
152
|
-
puts msg
|
153
|
-
logs << msg
|
154
|
-
end
|
155
|
-
|
156
|
-
# sets up the :source relationship option, typically for a has_many through relationship
|
157
|
-
def source_option cls_name
|
158
|
-
model = get_class(cls_name)
|
159
|
-
{:source => source(model) }
|
160
|
-
end
|
161
|
-
|
162
|
-
# sets up the :class_name relationship option for a given class (model
|
163
|
-
# @param [Class, String] the class to point to
|
164
|
-
def class_name_option cls_name
|
165
|
-
model = get_class(cls_name)
|
166
|
-
{:class_name => model.to_s }
|
167
|
-
end
|
168
|
-
|
169
|
-
# sets up the :through relationship option, always points to the join model
|
170
|
-
def through_option
|
171
|
-
{:through => join_model.through_key }
|
172
|
-
end
|
173
|
-
|
174
|
-
# sets up the :foreign_key relationship option
|
175
|
-
# the foreign key name should always correspond to 'my own' class name
|
176
|
-
def foreign_key_option cls_name
|
177
|
-
model = get_class(cls_name)
|
178
|
-
{:foreign_key => foreign_key(model) }
|
179
|
-
end
|
180
|
-
|
181
|
-
# sets up the full :through relationship options
|
182
|
-
# Example:
|
183
|
-
# :class_name => 'Role', :through => 'UsersRoles', :source => :role, :foreign_key => :user_id)
|
184
|
-
def through_options cls_name
|
185
|
-
model = get_class(cls_name)
|
186
|
-
through_option.merge(source_option model).merge(class_name_option model)
|
187
|
-
end
|
188
|
-
|
189
|
-
# creates the source
|
190
|
-
# Role becomes :role
|
191
|
-
def source cls_name
|
192
|
-
model = get_class(cls_name)
|
193
|
-
model.to_s.underscore.singularize.to_sym
|
194
|
-
end
|
195
|
-
|
196
|
-
# creates the foreign key
|
197
|
-
# RefManyAccount becomes :account_id
|
198
|
-
def foreign_key cls_name
|
199
|
-
model = get_class(cls_name)
|
200
|
-
name = model.to_s.underscore.split('_').last.singularize
|
201
|
-
:"#{name}_id"
|
202
|
-
end
|
203
205
|
end
|
204
206
|
end
|
@@ -6,35 +6,37 @@
|
|
6
6
|
# Knows how to configure the Join model between a subject model (the main target of the behavior fx UserAccount) and the object model (the behavior to be added, fx Role)
|
7
7
|
#
|
8
8
|
module Schemaker
|
9
|
-
class
|
9
|
+
class Models
|
10
|
+
class JoinModel < BaseModel
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# @param [Schema::Models] each model needs to have access to the collection of models it may need to create relations with
|
13
|
+
# @param [Class] reference to the Class it aims to configure!
|
14
|
+
def initialize models, clazz
|
15
|
+
super
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def simple_key
|
19
|
+
clazz_name.to_s.underscore
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def through_key
|
23
|
+
make_key clazz_name
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
26
|
+
# The join model always belongs to both the object and subject model
|
27
|
+
# the subject and object model can then each have a has_many relationship to the join model
|
28
|
+
# thus creating a Many-to-Many relationship via the join model
|
29
|
+
|
30
|
+
# Example:
|
31
|
+
# UsersRoles
|
32
|
+
# belongs_to :user, :class_name => 'UserAccount' (subject)
|
33
|
+
# belongs_to :role, :class_name => 'Role' (object)
|
34
|
+
#
|
35
|
+
# @note Do not call super here!
|
36
|
+
def configure
|
37
|
+
create_belongs_to :subject, class_name_option(:subject)
|
38
|
+
create_belongs_to :object, class_name_option(:object)
|
39
|
+
end
|
40
|
+
end
|
39
41
|
end
|
40
|
-
end
|
42
|
+
end
|
@@ -6,28 +6,30 @@
|
|
6
6
|
# Knows how to configure the relationship fro the Object model to the subject model via the Join model
|
7
7
|
#
|
8
8
|
module Schemaker
|
9
|
-
class
|
9
|
+
class Models
|
10
|
+
class ObjectModel < BaseModel
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# @param [Schema::Models] each model needs to have access to the collection of models it may need to create relations with
|
13
|
+
# @param [Class] reference to the Class it aims to configure!
|
14
|
+
def initialize models, clazz
|
15
|
+
super
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
# Configures has_many through relationship via Join model for the object model (fx Role)
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
# Role (object)
|
22
|
+
# has_many :accounts, :class_name => 'RefManyAccount', :through => :accounts_roles (subject)
|
23
|
+
# has_many :user_roles, :class_name => 'UserRole' (join)
|
24
|
+
def configure
|
25
|
+
super
|
26
|
+
create_has_many_through :subject
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
# @note important to use super to avoid recursive stack overflow!
|
30
|
+
def through_options options = {}
|
31
|
+
options.merge super(:subject)
|
32
|
+
end
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
@@ -6,36 +6,38 @@
|
|
6
6
|
# Knows how to configure the relationship fro the Object model to the subject model via the Join model
|
7
7
|
#
|
8
8
|
module Schemaker
|
9
|
-
class
|
9
|
+
class Models
|
10
|
+
class SubjectModel < BaseModel
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
# the main field for the behavior to add, fx :troles for adding roles behavior
|
13
|
+
attr_accessor :main_field
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
# @param [Schema::Models] each model needs to have access to the collection of models it may need to create relations with
|
16
|
+
# @param [Class] reference to the Class it aims to configure!
|
17
|
+
# @param [Symbol] the name of the main field for the behavior to add, fx :troles for adding roles behavior
|
18
|
+
def initialize models, clazz, main_field
|
19
|
+
super models, clazz
|
20
|
+
@main_field = main_field
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
# Used to set up a 'quick join' using Rails conventions and 'has_and_belongs_to_many' on the subject and object
|
24
|
+
def quick_join options = {}
|
25
|
+
create_has_and_belongs_to_many :object
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
# Example:
|
29
|
+
# UserAccount (subject)
|
30
|
+
# has_many :user_roles, :class_name => 'UserRole' (join)
|
31
|
+
# has_many :roles, :class_name => 'Role', :through => :users_roles (subject)
|
32
|
+
def configure
|
33
|
+
super
|
34
|
+
create_has_many_through :object, :key => main_field
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
# @note important to use super to avoid recursive stack overflow!
|
38
|
+
def through_options options = {}
|
39
|
+
options.merge super(:object).merge(foreign_key_option :subject)
|
40
|
+
end
|
41
|
+
end
|
40
42
|
end
|
41
43
|
end
|
data/lib/schemaker/models.rb
CHANGED
data/lib/schemaker.rb
CHANGED
@@ -1,15 +1,10 @@
|
|
1
|
-
require '
|
1
|
+
require 'sweetloader'
|
2
|
+
|
2
3
|
module Schemaker
|
4
|
+
autoload_modules :Models
|
5
|
+
|
3
6
|
class << self
|
4
|
-
attr_accessor :log_on
|
5
|
-
|
7
|
+
attr_accessor :log_on
|
6
8
|
alias_method :log_on?, :log_on
|
7
|
-
end
|
8
|
-
|
9
|
-
autoload :Models, 'schemaker/models'
|
10
|
-
|
11
|
-
autoload :BaseModel, 'schemaker/models/base_model'
|
12
|
-
autoload :JoinModel, 'schemaker/models/join_model'
|
13
|
-
autoload :ObjectModel, 'schemaker/models/object_model'
|
14
|
-
autoload :SubjectModel, 'schemaker/models/subject_model'
|
9
|
+
end
|
15
10
|
end
|
data/schemaker.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "schemaker"
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kristian Mandrup"]
|
@@ -52,45 +52,39 @@ Gem::Specification.new do |s|
|
|
52
52
|
s.specification_version = 3
|
53
53
|
|
54
54
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
-
s.add_runtime_dependency(%q<
|
56
|
-
s.add_runtime_dependency(%q<require_all>, ["~> 1.2.0"])
|
55
|
+
s.add_runtime_dependency(%q<sweetloader>, [">= 0.1.1"])
|
57
56
|
s.add_development_dependency(%q<activerecord>, [">= 3.0.1"])
|
58
57
|
s.add_development_dependency(%q<rspec>, [">= 2.6.0"])
|
58
|
+
s.add_development_dependency(%q<database_cleaner>, ["~> 0.6.8"])
|
59
|
+
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
60
|
+
s.add_development_dependency(%q<cutter>, [">= 0"])
|
59
61
|
s.add_development_dependency(%q<bundler>, [">= 1"])
|
60
62
|
s.add_development_dependency(%q<jeweler>, [">= 1.6"])
|
61
63
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
62
64
|
s.add_development_dependency(%q<yard>, [">= 0"])
|
63
|
-
s.add_development_dependency(%q<database_cleaner>, ["~> 0.6.8"])
|
64
|
-
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
65
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
66
|
-
s.add_development_dependency(%q<cutter>, [">= 0"])
|
67
65
|
else
|
68
|
-
s.add_dependency(%q<
|
69
|
-
s.add_dependency(%q<require_all>, ["~> 1.2.0"])
|
66
|
+
s.add_dependency(%q<sweetloader>, [">= 0.1.1"])
|
70
67
|
s.add_dependency(%q<activerecord>, [">= 3.0.1"])
|
71
68
|
s.add_dependency(%q<rspec>, [">= 2.6.0"])
|
69
|
+
s.add_dependency(%q<database_cleaner>, ["~> 0.6.8"])
|
70
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
71
|
+
s.add_dependency(%q<cutter>, [">= 0"])
|
72
72
|
s.add_dependency(%q<bundler>, [">= 1"])
|
73
73
|
s.add_dependency(%q<jeweler>, [">= 1.6"])
|
74
74
|
s.add_dependency(%q<rcov>, [">= 0"])
|
75
75
|
s.add_dependency(%q<yard>, [">= 0"])
|
76
|
-
s.add_dependency(%q<database_cleaner>, ["~> 0.6.8"])
|
77
|
-
s.add_dependency(%q<sqlite3>, [">= 0"])
|
78
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
79
|
-
s.add_dependency(%q<cutter>, [">= 0"])
|
80
76
|
end
|
81
77
|
else
|
82
|
-
s.add_dependency(%q<
|
83
|
-
s.add_dependency(%q<require_all>, ["~> 1.2.0"])
|
78
|
+
s.add_dependency(%q<sweetloader>, [">= 0.1.1"])
|
84
79
|
s.add_dependency(%q<activerecord>, [">= 3.0.1"])
|
85
80
|
s.add_dependency(%q<rspec>, [">= 2.6.0"])
|
81
|
+
s.add_dependency(%q<database_cleaner>, ["~> 0.6.8"])
|
82
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
83
|
+
s.add_dependency(%q<cutter>, [">= 0"])
|
86
84
|
s.add_dependency(%q<bundler>, [">= 1"])
|
87
85
|
s.add_dependency(%q<jeweler>, [">= 1.6"])
|
88
86
|
s.add_dependency(%q<rcov>, [">= 0"])
|
89
87
|
s.add_dependency(%q<yard>, [">= 0"])
|
90
|
-
s.add_dependency(%q<database_cleaner>, ["~> 0.6.8"])
|
91
|
-
s.add_dependency(%q<sqlite3>, [">= 0"])
|
92
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
93
|
-
s.add_dependency(%q<cutter>, [">= 0"])
|
94
88
|
end
|
95
89
|
end
|
96
90
|
|
data/spec/models_helper.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'models_helper'
|
2
2
|
|
3
|
-
class UsersRoles < ActiveRecord::Base
|
3
|
+
class UsersRoles < ActiveRecord::Base
|
4
4
|
end
|
5
5
|
|
6
6
|
def join_model_class
|
7
|
-
Schemaker::JoinModel
|
7
|
+
Schemaker::Models::JoinModel
|
8
8
|
end
|
9
9
|
|
10
10
|
describe join_model_class do
|
@@ -24,4 +24,4 @@ describe join_model_class do
|
|
24
24
|
matches_all last_log, 'belongs_to :role', ':class_name=>"Role"'
|
25
25
|
end
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'models_helper'
|
2
2
|
|
3
3
|
def object_model_class
|
4
|
-
Schemaker::ObjectModel
|
4
|
+
Schemaker::Models::ObjectModel
|
5
5
|
end
|
6
6
|
|
7
7
|
describe object_model_class do
|
8
8
|
let(:object_model) do
|
9
9
|
object_model_class.new models, Role
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
describe '#configure' do
|
13
13
|
it 'should configure object model' do
|
14
14
|
object_model.configure
|
@@ -19,6 +19,6 @@ describe object_model_class do
|
|
19
19
|
|
20
20
|
matches_all first_log, 'has_many :user_roles', ':class_name=>"UsersRoles"'
|
21
21
|
matches_all last_log, 'Role.has_many :user_accounts', ':through=>:user_roles', ':source=>:user_account', ':class_name=>"UserAccount"'
|
22
|
-
end
|
22
|
+
end
|
23
23
|
end
|
24
|
-
end
|
24
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'models_helper'
|
2
2
|
|
3
3
|
def subject_model_class
|
4
|
-
Schemaker::SubjectModel
|
4
|
+
Schemaker::Models::SubjectModel
|
5
5
|
end
|
6
6
|
|
7
7
|
describe subject_model_class do
|
8
8
|
let(:subject_model) do
|
9
9
|
subject_model_class.new models, UserAccount, :troles
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
describe '#configure' do
|
13
13
|
it 'should configure subject model' do
|
14
14
|
subject_model.configure
|
@@ -20,6 +20,6 @@ describe subject_model_class do
|
|
20
20
|
matches_all first_log, 'has_many :user_roles', ':class_name=>"UsersRoles"'
|
21
21
|
# has_many :roles, {:through=>:user_roles, :source=>:role, :class_name=>"Role", :foreign_key=>:account_id}
|
22
22
|
matches_all last_log, 'UserAccount.has_many :troles', ':through=>:user_roles', ':source=>:role', ':class_name=>"Role"', ':foreign_key=>:account_id'
|
23
|
-
end
|
23
|
+
end
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schemaker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,30 +12,19 @@ cert_chain: []
|
|
12
12
|
date: 2011-10-12 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement: &
|
15
|
+
name: sweetloader
|
16
|
+
requirement: &2157347720 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 0.1.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: require_all
|
27
|
-
requirement: &2165518620 !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
|
-
requirements:
|
30
|
-
- - ~>
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 1.2.0
|
33
|
-
type: :runtime
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: *2165518620
|
24
|
+
version_requirements: *2157347720
|
36
25
|
- !ruby/object:Gem::Dependency
|
37
26
|
name: activerecord
|
38
|
-
requirement: &
|
27
|
+
requirement: &2157346060 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
29
|
requirements:
|
41
30
|
- - ! '>='
|
@@ -43,10 +32,10 @@ dependencies:
|
|
43
32
|
version: 3.0.1
|
44
33
|
type: :development
|
45
34
|
prerelease: false
|
46
|
-
version_requirements: *
|
35
|
+
version_requirements: *2157346060
|
47
36
|
- !ruby/object:Gem::Dependency
|
48
37
|
name: rspec
|
49
|
-
requirement: &
|
38
|
+
requirement: &2157342600 !ruby/object:Gem::Requirement
|
50
39
|
none: false
|
51
40
|
requirements:
|
52
41
|
- - ! '>='
|
@@ -54,32 +43,21 @@ dependencies:
|
|
54
43
|
version: 2.6.0
|
55
44
|
type: :development
|
56
45
|
prerelease: false
|
57
|
-
version_requirements: *
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: bundler
|
60
|
-
requirement: &2165517040 !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
|
-
requirements:
|
63
|
-
- - ! '>='
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
version: '1'
|
66
|
-
type: :development
|
67
|
-
prerelease: false
|
68
|
-
version_requirements: *2165517040
|
46
|
+
version_requirements: *2157342600
|
69
47
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
-
requirement: &
|
48
|
+
name: database_cleaner
|
49
|
+
requirement: &2157340920 !ruby/object:Gem::Requirement
|
72
50
|
none: false
|
73
51
|
requirements:
|
74
|
-
- -
|
52
|
+
- - ~>
|
75
53
|
- !ruby/object:Gem::Version
|
76
|
-
version:
|
54
|
+
version: 0.6.8
|
77
55
|
type: :development
|
78
56
|
prerelease: false
|
79
|
-
version_requirements: *
|
57
|
+
version_requirements: *2157340920
|
80
58
|
- !ruby/object:Gem::Dependency
|
81
|
-
name:
|
82
|
-
requirement: &
|
59
|
+
name: sqlite3
|
60
|
+
requirement: &2157338840 !ruby/object:Gem::Requirement
|
83
61
|
none: false
|
84
62
|
requirements:
|
85
63
|
- - ! '>='
|
@@ -87,10 +65,10 @@ dependencies:
|
|
87
65
|
version: '0'
|
88
66
|
type: :development
|
89
67
|
prerelease: false
|
90
|
-
version_requirements: *
|
68
|
+
version_requirements: *2157338840
|
91
69
|
- !ruby/object:Gem::Dependency
|
92
|
-
name:
|
93
|
-
requirement: &
|
70
|
+
name: cutter
|
71
|
+
requirement: &2157337240 !ruby/object:Gem::Requirement
|
94
72
|
none: false
|
95
73
|
requirements:
|
96
74
|
- - ! '>='
|
@@ -98,32 +76,32 @@ dependencies:
|
|
98
76
|
version: '0'
|
99
77
|
type: :development
|
100
78
|
prerelease: false
|
101
|
-
version_requirements: *
|
79
|
+
version_requirements: *2157337240
|
102
80
|
- !ruby/object:Gem::Dependency
|
103
|
-
name:
|
104
|
-
requirement: &
|
81
|
+
name: bundler
|
82
|
+
requirement: &2157336480 !ruby/object:Gem::Requirement
|
105
83
|
none: false
|
106
84
|
requirements:
|
107
|
-
- -
|
85
|
+
- - ! '>='
|
108
86
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
87
|
+
version: '1'
|
110
88
|
type: :development
|
111
89
|
prerelease: false
|
112
|
-
version_requirements: *
|
90
|
+
version_requirements: *2157336480
|
113
91
|
- !ruby/object:Gem::Dependency
|
114
|
-
name:
|
115
|
-
requirement: &
|
92
|
+
name: jeweler
|
93
|
+
requirement: &2157334900 !ruby/object:Gem::Requirement
|
116
94
|
none: false
|
117
95
|
requirements:
|
118
96
|
- - ! '>='
|
119
97
|
- !ruby/object:Gem::Version
|
120
|
-
version: '
|
98
|
+
version: '1.6'
|
121
99
|
type: :development
|
122
100
|
prerelease: false
|
123
|
-
version_requirements: *
|
101
|
+
version_requirements: *2157334900
|
124
102
|
- !ruby/object:Gem::Dependency
|
125
|
-
name:
|
126
|
-
requirement: &
|
103
|
+
name: rcov
|
104
|
+
requirement: &2157333940 !ruby/object:Gem::Requirement
|
127
105
|
none: false
|
128
106
|
requirements:
|
129
107
|
- - ! '>='
|
@@ -131,10 +109,10 @@ dependencies:
|
|
131
109
|
version: '0'
|
132
110
|
type: :development
|
133
111
|
prerelease: false
|
134
|
-
version_requirements: *
|
112
|
+
version_requirements: *2157333940
|
135
113
|
- !ruby/object:Gem::Dependency
|
136
|
-
name:
|
137
|
-
requirement: &
|
114
|
+
name: yard
|
115
|
+
requirement: &2157332720 !ruby/object:Gem::Requirement
|
138
116
|
none: false
|
139
117
|
requirements:
|
140
118
|
- - ! '>='
|
@@ -142,7 +120,7 @@ dependencies:
|
|
142
120
|
version: '0'
|
143
121
|
type: :development
|
144
122
|
prerelease: false
|
145
|
-
version_requirements: *
|
123
|
+
version_requirements: *2157332720
|
146
124
|
description: Configures relationships between subject, join and object model for a
|
147
125
|
given behavior
|
148
126
|
email: kmandrup@gmail.com
|
@@ -191,7 +169,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
191
169
|
version: '0'
|
192
170
|
segments:
|
193
171
|
- 0
|
194
|
-
hash:
|
172
|
+
hash: 2528253751213112279
|
195
173
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
174
|
none: false
|
197
175
|
requirements:
|