active_record_schema 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,66 +1,86 @@
1
1
  # ActiveRecordSchema
2
2
 
3
- *ActiveRecordSchema* is an ActiveRecord extension that allows you to write the database schema for a model within the model itself and to generate migrations directly from models.
3
+ **ActiveRecordSchema** is an `ActiveRecord` extension that allows you to write database schema for a model within the model itself and to generate migrations directly from models.
4
4
 
5
5
  Unlike other libraries (eg. mini_record) ActiveRecordSchema is not an alternative to Rails migrations, but rather a tool to simplify their use.
6
6
 
7
- Install
7
+ ## Features
8
+
9
+ * Defining columns and indexes directly in model
10
+ * Generation of migration from the model taking into account the current state of the database
11
+ * Automatically add code to migrate associations:
12
+ * Foreign key for `belongs_to`
13
+ * Join table for `has_and_belongs_to_many`
14
+
15
+ * Automatic indexing of foreign keys for both `belongs_to` and `has_and_belongs_to_many` (configurable)
16
+
17
+ ## Installation
18
+
19
+ Put this in your Gemfile
8
20
 
9
21
  gem 'active_record_schema'
10
22
 
11
- Update your bundle
23
+ and update your bundle
12
24
 
13
25
  bundle install
26
+
27
+ **NOTE:** ActiveRecordSchema depends on `rails ~> 3.0` and not only `ActiveRecord`
14
28
 
15
29
  ## Usage
16
30
 
17
- Create a model
18
-
19
- class Post < ActiveRecord::Base
20
- field :title
21
- field :body, :as => :text
22
- belongs_to :author, :class_name => "User"
23
- end
31
+ Create a model and use the class method `#field` to define columns
24
32
 
25
- Run a migration generator each time you want to commit changes to database
33
+ ``` rb
34
+ class Post < ActiveRecord::Base
35
+ field :title
36
+ field :body, :as => :text
37
+ belongs_to :author, :class_name => "User"
38
+ end
39
+ ```
40
+
41
+ Now run `rails g migration` with `--from` option
26
42
 
27
43
  rails g migration init_posts_schema --from Post
28
44
 
29
- Will generate the following migration
30
-
31
- class InitPostsSchema < ActiveRecord::Migration
32
- def change
33
- add_column :posts, :title, :string
34
- add_column :posts, :body, :text
35
-
36
- add_column :author_id, :integer
37
- index :author_id
38
- end
39
- end
40
-
41
- Now you can migrate the database.
42
-
43
- Later in the life cycle of the project... add a new field to `Post`
45
+ and the following migration will be generated
46
+
47
+ ``` rb
48
+ class InitPostsSchema < ActiveRecord::Migration
49
+ def change
50
+ add_column :posts, :title, :string
51
+ add_column :posts, :body, :text
52
+
53
+ add_column :author_id, :integer
54
+ index :author_id
55
+ end
56
+ end
57
+ ```
58
+
59
+ Generating a migration for new columns is the same, lets add a new field to `Post` (eg. `pubdate`):
60
+
61
+ ``` rb
62
+ class Post < ActiveRecord::Base
63
+ field :title
64
+ field :body, :as => :text
65
+ belongs_to :author, :class_name => "User"
44
66
 
45
- class Post < ActiveRecord::Base
46
- field :title
47
- field :body, :as => :text
48
- belongs_to :author, :class_name => "User"
49
- field :pubdate, :as => :datetime
50
- end
67
+ field :pubdate, :as => :datetime
68
+ end
69
+ ```
51
70
 
52
- Generate easily a new migration for the change:
71
+ Now run
53
72
 
54
73
  rails g migration add_pubdate_to_posts --from Post
55
74
 
56
- Will generate:
57
-
58
- class AddPubdateToPosts < ActiveRecord::Migration
59
- def change
60
- add_column :posts, :pubdate, :datetime
61
- end
62
- end
75
+ that will generate:
63
76
 
77
+ ``` rb
78
+ class AddPubdateToPosts < ActiveRecord::Migration
79
+ def change
80
+ add_column :posts, :pubdate, :datetime
81
+ end
82
+ end
83
+ ```
64
84
 
65
85
  ## Has and Belongs To Many (HBTM) associations
66
86
 
@@ -68,23 +88,26 @@ Lets try to add a HBTM association to our `Post` model
68
88
 
69
89
  _ex._
70
90
 
71
- # content.rb
72
- class Post < ActiveRecord::Base
73
- field :title
74
- field :body, :as => :text
75
- belongs_to :author, :class_name => "User"
76
- field :pubdate, :as => :datetime
91
+ ``` rb
92
+ # content.rb
93
+ class Post < ActiveRecord::Base
94
+ field :title
95
+ field :body, :as => :text
96
+ belongs_to :author, :class_name => "User"
97
+ field :pubdate, :as => :datetime
77
98
 
78
- has_and_belongs_to_many :voters, :class_name => "User"
79
- end
99
+ has_and_belongs_to_many :voters, :class_name => "User"
100
+ end
101
+ ```
80
102
 
81
103
 
82
104
  Now running
83
105
 
84
106
  rails g migration add_voters_to_posts --from Post
85
107
 
86
- Will generate:
108
+ will generate:
87
109
 
110
+ ``` rb
88
111
  class AddVotersToPosts < ActiveRecord::Migration
89
112
  def change
90
113
  create_table :contents_users, :id => false do |t|
@@ -95,38 +118,41 @@ Will generate:
95
118
  add_index :contents_users, "user_id"
96
119
  end
97
120
  end
121
+ ```
98
122
 
99
123
  ## Single Table Inheritance (STI)
100
124
 
101
- Call `#inheritable` inside the base class of your hierarchy to add the `type` column required by Single Table Inheritance.
125
+ Call `#inheritable` inside the base class of your hierarchy to add the inheritance column required by Single Table Inheritance.
102
126
 
103
127
  _ex._
104
128
 
105
- # content.rb
106
- class Content < ActiveRecord::Base
107
- inheritable
129
+ ``` rb
130
+ # content.rb
131
+ class Content < ActiveRecord::Base
132
+ inheritable
108
133
 
109
- field :title
134
+ field :title
110
135
 
111
- has_and_belongs_to_many :voters, :class_name => "User"
112
- belongs_to :author, :class_name => "User"
136
+ has_and_belongs_to_many :voters, :class_name => "User"
137
+ belongs_to :author, :class_name => "User"
113
138
 
114
- timestamps
115
- end
139
+ timestamps
140
+ end
116
141
 
117
142
 
118
- # article.rb
119
- class Article < Content
120
- field :body, :as => :text
121
- end
143
+ # article.rb
144
+ class Article < Content
145
+ field :body, :as => :text
146
+ end
122
147
 
123
148
 
124
- # video.rb
125
- class Video < Content
126
- field :url
127
- end
149
+ # video.rb
150
+ class Video < Content
151
+ field :url
152
+ end
153
+ ```
128
154
 
129
- run
155
+ Running
130
156
 
131
157
  rails g migration init_contents --from Content
132
158
 
@@ -138,27 +164,128 @@ same as
138
164
 
139
165
  rails g migration init_contents --from Video
140
166
 
141
- Will generate the following migration
167
+ will generate the following migration
168
+
169
+ ``` rb
170
+ class InitContents < ActiveRecord::Migration
171
+ def change
172
+ add_column :contents, :type, :string
173
+ add_column :contents, :title, :string
174
+ add_column :contents, :author_id, :string
175
+ add_column :contents, :body, :text
176
+ add_column :contents, :url, :string
177
+
178
+ add_index :contents, :author_id
179
+
180
+ create_table :contents_users, :id => false do |t|
181
+ t.integer "content_id"
182
+ t.integer "user_id"
183
+ end
184
+ add_index :contents_users, "content_id"
185
+ add_index :contents_users, "user_id"
186
+ end
187
+ end
188
+ ```
142
189
 
143
- class InitContents < ActiveRecord::Migration
144
- def change
145
- add_column :contents, :type, :string
146
- add_column :contents, :title, :string
147
- add_column :contents, :author_id, :string
148
- add_column :contents, :body, :text
149
- add_column :contents, :url, :string
150
190
 
151
- add_index :contents, :author_id
191
+ ## Mixins
152
192
 
153
- create_table :contents_users, :id => false do |t|
154
- t.integer "content_id"
155
- t.integer "user_id"
156
- end
157
- add_index :contents_users, "content_id"
158
- add_index :contents_users, "user_id"
159
- end
160
- end
193
+ Probably one of the most significant advantage given by ActiveRecordSchema is to allow the definition of fields in modules and reuse them through mixin
194
+
195
+ _ex._
161
196
 
197
+ ``` rb
198
+ module Profile
199
+ extend ActiveSupport::Concern
200
+ included do
201
+ field :name
202
+ field :age, :as => :integer
203
+
204
+ end
205
+ end
206
+
207
+ class User < ActiveRecord::Base
208
+ include Profile
209
+
210
+ end
211
+
212
+ class Player < ActiveRecord::Base
213
+ include Profile
214
+
215
+ end
216
+ ```
217
+
218
+
219
+ ## DSL (Domain Specific Language) reference
220
+
221
+ * ### `field(name, *args)`
222
+
223
+ Adds a new column with name `name` to the schema. The type of column can be passed either as second argument or as option, if not specified is intended to be `:string`
224
+
225
+ #### options
226
+
227
+ * **:as _or_ :type** : Specify the type of the column. The value can be a `String`, a `Symbol` or a `Class`, default to `:string`
228
+ * **:index** : Specify wether or not the field should be indexed, default to `false`
229
+
230
+ #### examples
231
+
232
+ ``` rb
233
+ field :name
234
+
235
+ field :name, :string
236
+ field :name, "string"
237
+ field :name, String
238
+
239
+ field :name, :as => :string
240
+ field :name, :as => "string"
241
+ field :name, :as => String
242
+
243
+ field :name, :type => :string
244
+ field :name, :type => "string"
245
+ field :name, :type => String
246
+
247
+ field :age, :as => :integer, :index => true
248
+ ```
249
+
250
+
251
+ * ### `belongs_to(name, options = {})`
252
+
253
+ Adds a new foreign key column for the association to the schema and then delegates to `ActiveRecord::Base.belongs_to`. If the association is polimorphic a column for foreign type is also generated.
254
+
255
+ #### options
256
+
257
+ * **:index** : Specify wether or not the foreing key column should be indexed, default to `true`. If the association is polimorphic creates an index on both foreign key and foreing type
258
+
259
+
260
+ * ### `has_and_belongs_to_many(name, options = {}, &extension)`
261
+
262
+ Adds a new join table for the association to the schema and then delegates to `ActiveRecord::Base.has_and_belongs_to_many`
263
+
264
+ * ### `index(column_name, options = {})`
265
+
266
+ Adds a new index for `column_name` column to the schema
267
+
268
+ * ### `timestamps`
269
+
270
+ Same as
271
+
272
+ ``` rb
273
+ field :created_at, :datetime
274
+ field :updated_at, :datetime
275
+ ```
276
+
277
+ * ### `inheritable`
278
+
279
+ Same as
280
+
281
+ ``` rb
282
+ field :"#{inheritance_column}"
283
+ ```
284
+
285
+
286
+ ## Why do not also generate irreversible changes (change/remove columns or indexes)?
287
+
288
+ ActiveRecordSchema does not take into account the removal of columns and indexes or changes in the types of columns. The reason for this is that these changes are not reversible, so it's a better idea to introduce them by hand rather than let them be generated automatically. Anyway the need to resort to harsh measures such as irreversible changes is limited to non-routine situations.
162
289
 
163
290
 
164
291
  ## Contributing to active_record_schema
@@ -171,7 +298,6 @@ Will generate the following migration
171
298
  * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
172
299
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
173
300
 
174
-
175
301
  ---
176
302
 
177
303
  Copyright (c) 2012 mcasimir
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.2.2
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "active_record_schema"
8
- s.version = "0.2.1"
8
+ s.version = "0.2.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["mcasimir"]
@@ -17,7 +17,7 @@ module ActiveRecordSchema
17
17
  # field :name, :string, :default => "Joe"
18
18
  def field(name, *args)
19
19
  options = args.extract_options!
20
- type = options.delete(:as) || options.delete(:type) || args.first || :string
20
+ type = options.delete(:as) || options.delete(:type) || args.first || :string
21
21
  type = type.name.underscore.to_sym if (type.class == Class)
22
22
  index = options.delete(:index)
23
23
 
@@ -27,9 +27,6 @@ module ActiveRecordSchema
27
27
  schema.add_index(name)
28
28
  end
29
29
  end
30
- alias :key :field
31
- alias :property :field
32
- alias :col :field
33
30
 
34
31
  def belongs_to(name, options = {})
35
32
  options.symbolize_keys!
@@ -64,21 +61,18 @@ module ActiveRecordSchema
64
61
  super(name, options, &extension)
65
62
  end
66
63
 
67
- def add_index(column_name, options = {})
64
+ def index(column_name, options = {})
68
65
  schema.add_index(column_name, options)
69
66
  end
70
- alias :index :add_index
71
67
 
72
- def timestamps!
68
+ def timestamps
73
69
  field :created_at, :datetime
74
70
  field :updated_at, :datetime
75
71
  end
76
- alias :timestamps :timestamps!
77
72
 
78
- def inheritable!
73
+ def inheritable
79
74
  field :"#{inheritance_column}"
80
75
  end
81
- alias :inheritable :inheritable!
82
76
 
83
77
  end
84
78
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -89,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
89
89
  version: '0'
90
90
  segments:
91
91
  - 0
92
- hash: -757246031215524947
92
+ hash: -4255216891486240966
93
93
  required_rubygems_version: !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements: