mini_record 0.4.0 → 0.4.1
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +150 -59
- data/lib/mini_record/auto_schema.rb +7 -22
- data/lib/mini_record/version.rb +1 -1
- data/mini_record.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee891eba3f9e58c760acce562bd83a6595c4b9ef
|
4
|
+
data.tar.gz: 9aba338c47d2a027e73c4b81347a4f4cf35d0964
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eee2c19a616f355e653d37be8c7a9a913d001c01af3486cde45ca6ba755d35152b872ed803786efdbe6e79730c679dd053bea90e9c648951b66446e82a0013d9
|
7
|
+
data.tar.gz: 90e4353472d858b08a3124e8ac56d265cb4d2a0326583c89375f4ed0dd1c3a6f8019ea82a7782e1e0ca151765741ed4afb0ab9442f99eecdc56a8b3d63cd7dc8
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
[](http://travis-ci.org/DAddYE/mini_record)
|
2
2
|
|
3
3
|
|
4
|
-
MiniRecord is a micro extension for
|
5
|
-
|
6
|
-
|
7
|
-
like DataMapper, MongoMapper or MongoID.
|
4
|
+
MiniRecord is a **micro** extension for the `ActiveRecord` gem.
|
5
|
+
|
6
|
+
MiniRecord will allow you to create/edit/manage columns, directly in your **model**.
|
8
7
|
|
9
|
-
My inspiration come from this handy [project](https://github.com/pjhyett/auto_migrations).
|
10
8
|
|
11
9
|
## Features
|
12
10
|
|
13
11
|
* Define columns/properties inside your model
|
14
12
|
* Perform migrations automatically
|
15
|
-
* Auto upgrade your schema
|
16
|
-
* Add, Remove, Change
|
13
|
+
* Auto upgrade your schema
|
14
|
+
* Add, Remove, Change **columns**
|
15
|
+
* Add, Remove, Change **indexes**
|
17
16
|
|
18
17
|
## Instructions
|
19
18
|
|
@@ -22,7 +21,7 @@ This avoid conflicts.
|
|
22
21
|
|
23
22
|
Add to your `Gemfile`:
|
24
23
|
|
25
|
-
```
|
24
|
+
```sh
|
26
25
|
gem 'mini_record'
|
27
26
|
```
|
28
27
|
|
@@ -33,53 +32,67 @@ That's all!
|
|
33
32
|
Remember that inside properties you can use all migrations methods,
|
34
33
|
see [documentation](http://api.rubyonrails.org/classes/ActiveRecord/Migration.html)
|
35
34
|
|
36
|
-
```
|
35
|
+
```ruby
|
37
36
|
class Post < ActiveRecord::Base
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
field :title_en, :title_jp
|
38
|
+
field :description_en, :description_jp, as: :text
|
39
|
+
field :permalink, index: true, limit: 50
|
40
|
+
field :comments_count, as: :integer
|
41
|
+
field :category, as: :references, index: true
|
43
42
|
end
|
44
43
|
Post.auto_upgrade!
|
45
44
|
```
|
46
45
|
|
47
|
-
|
46
|
+
Instead of `field` you can pick an alias: `key, field, property, col`
|
48
47
|
|
49
|
-
|
48
|
+
If the option `:as` is omitted, minirecord will assume it's a `:string`.
|
50
49
|
|
51
|
-
|
50
|
+
Remember that as for `ActiveRecord` you can choose different types:
|
52
51
|
|
53
|
-
```
|
52
|
+
```ruby
|
54
53
|
:primary_key, :string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time,
|
55
54
|
:date, :binary, :boolean, :references, :belongs_to, :timestamp
|
56
55
|
```
|
57
56
|
|
58
|
-
You can provide
|
57
|
+
You can also provide other options like:
|
59
58
|
|
60
|
-
```
|
59
|
+
```ruby
|
61
60
|
:limit, :default, :null, :precision, :scale
|
62
61
|
|
63
62
|
# example
|
64
63
|
class Foo < ActiveRecord::Base
|
65
|
-
|
66
|
-
|
64
|
+
field :title, default: "MyTitle" # as: :string is not necessary since is a default
|
65
|
+
field :price, as: :decimal, scale: 8, precision: 2
|
67
66
|
end
|
68
67
|
```
|
69
68
|
|
70
69
|
See [ActiveRecord::TableDefinition](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html)
|
71
70
|
for more details.
|
72
71
|
|
73
|
-
|
74
|
-
|
72
|
+
### Perform upgrades
|
73
|
+
|
74
|
+
Finally, when you execute `MyModel.auto_upgrade!`, missing columns, indexes and tables will be created on the fly.
|
75
|
+
|
76
|
+
Indexes and columns present in the db but **not** in your model schema/definition will be **deleted** also from your db.
|
75
77
|
|
76
78
|
### Single Table Inheritance
|
77
79
|
|
78
|
-
MiniRecord as ActiveRecord support STI
|
80
|
+
MiniRecord as ActiveRecord support STI:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class Pet < ActiveRecord::Base; end
|
84
|
+
class Dog < Pet; end
|
85
|
+
class Cat < Pet; end
|
86
|
+
ActiveRecord::Base.auto_upgrade!
|
87
|
+
```
|
88
|
+
|
89
|
+
When you perform `ActiveRecord::Base.auto_upgrade!`, just **1** table will be created with the `type` column (indexed as well).
|
79
90
|
|
80
91
|
### ActiveRecord Relations
|
81
92
|
|
82
|
-
MiniRecord has built-in support of belongs_to
|
93
|
+
MiniRecord has built-in support of `belongs_to`, _polymorphic associations_ as well with _habtm_ relations.
|
94
|
+
|
95
|
+
You don't need to do anything in particular, is not even necessary define the field for them since they will be handled automatically.
|
83
96
|
|
84
97
|
#### belongs_to
|
85
98
|
```ruby
|
@@ -87,27 +100,42 @@ class Address < ActiveRecord::Base
|
|
87
100
|
belongs_to :person
|
88
101
|
end
|
89
102
|
```
|
90
|
-
Will result in a person_id column
|
103
|
+
Will result in a indexed `person_id` column. You can use a different one using the `foreign_key` option:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
belongs_to :person, foreign_key: :person_pk
|
107
|
+
```
|
91
108
|
|
92
109
|
#### belongs_to with foreign key in database
|
110
|
+
|
93
111
|
```ruby
|
94
112
|
class Address < ActiveRecord::Base
|
95
113
|
belongs_to :person
|
96
|
-
index :person_id, :
|
114
|
+
index :person_id, foreign: true
|
97
115
|
end
|
98
116
|
```
|
99
|
-
The same as in the previous case, but foreign key will be added to the database with help of [foreigner](https://github.com/matthuhiggins/foreigner) gem.
|
100
117
|
|
101
|
-
|
118
|
+
This is the same example, but foreign key will be added to the database with help of
|
119
|
+
[foreigner](https://github.com/matthuhiggins/foreigner) gem.
|
120
|
+
|
121
|
+
In this case you have more control (if needed).
|
122
|
+
|
123
|
+
To remove the key please use `:foreign => false`
|
102
124
|
If you simple remove the index, the foreign key will not be removed.
|
103
125
|
|
104
126
|
#### belongs_to (polymorphic)
|
127
|
+
|
105
128
|
```ruby
|
106
129
|
class Address < ActiveRecord::Base
|
107
|
-
belongs_to :addressable, :
|
130
|
+
belongs_to :addressable, polymorphic: true
|
108
131
|
end
|
109
132
|
```
|
110
|
-
|
133
|
+
|
134
|
+
Will create an `addressable_id` and an `addressable_type` column with composite indexes:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
add_index(:addresses), [:addressable_id, :addressable_type]
|
138
|
+
```
|
111
139
|
|
112
140
|
#### habtm
|
113
141
|
```ruby
|
@@ -115,75 +143,138 @@ class Address < ActiveRecord::Base
|
|
115
143
|
has_and_belongs_to_many :people
|
116
144
|
end
|
117
145
|
```
|
118
|
-
|
146
|
+
|
147
|
+
Will generate a "addresses_people" (aka: join table) with indexes on the id columns
|
119
148
|
|
120
149
|
### Adding a new column
|
121
150
|
|
122
151
|
Super easy, open your model and just add it:
|
123
152
|
|
124
|
-
```
|
153
|
+
```ruby
|
125
154
|
class Post < ActiveRecord::Base
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
155
|
+
field :title
|
156
|
+
field :body, as: :text # <<- this
|
157
|
+
field :permalink, index: true
|
158
|
+
field :comments_count, as: :integer
|
159
|
+
field :category, as: :references, index: true
|
131
160
|
end
|
132
161
|
Post.auto_upgrade!
|
133
162
|
```
|
134
163
|
|
135
|
-
So now when you invoke `MyModel.auto_upgrade!`
|
136
|
-
records are happy and safe.
|
164
|
+
So now when you invoke `MyModel.auto_upgrade!` a diff between the old schema an the new one will detect changes and create the new column.
|
137
165
|
|
138
166
|
### Removing a column
|
139
167
|
|
140
|
-
It's exactly the same
|
168
|
+
It's exactly the same as in the previous example.
|
169
|
+
|
170
|
+
### Rename columns
|
171
|
+
|
172
|
+
Simply adding a `rename_field` declaration and mini_record will do a `connection.rename_column` in the next `auto_upgrade!` but **only** if the db has the old column and not the new column.
|
173
|
+
|
174
|
+
This means that you still need to have a `field` declaration for the new column name so subsequent `MyModel.auto_upgrade!` will not remove the column.
|
175
|
+
|
176
|
+
You are free to leave the `rename_field` declaration in place or you can remove it once the new column exists in the db.
|
141
177
|
|
142
|
-
|
178
|
+
Moving from:
|
179
|
+
```ruby
|
180
|
+
class Vehicle < ActiveRecord::Base
|
181
|
+
field :color
|
182
|
+
end
|
183
|
+
```
|
184
|
+
|
185
|
+
To:
|
186
|
+
```ruby
|
187
|
+
class Vehicle < ActiveRecord::Base
|
188
|
+
rename_field :color, new_name: :body_color
|
189
|
+
field :body_color
|
190
|
+
end
|
191
|
+
```
|
192
|
+
|
193
|
+
Then perhaps later:
|
194
|
+
```ruby
|
195
|
+
class Vehicle < ActiveRecord::Base
|
196
|
+
rename_field :color, new_name: :body_color
|
197
|
+
rename_field :body_color, new_name: :chassis_color
|
198
|
+
field :chassis_color
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
### Change the type of columns
|
203
|
+
|
204
|
+
Where when you rename a column the task should be _explicit_ changing the type is _implicit_.
|
205
|
+
|
206
|
+
This means that if you have
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
field :total, as: :integer
|
210
|
+
```
|
211
|
+
|
212
|
+
and later on you'll figure out that you wanted a `float`
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
field :total, as: :float
|
216
|
+
```
|
217
|
+
|
218
|
+
Will automatically change the type the the first time you'll invoke `auto_upgrade`.
|
143
219
|
|
144
|
-
It's not possible for us know when/what column you have renamed, but we can know if you changed the `type` so
|
145
|
-
if you change `t.string :name` to `t.text :name` we are be able to perform an `ALTER TABLE`
|
146
220
|
|
147
221
|
### Add/Remove indexes
|
148
222
|
|
149
|
-
In the same
|
223
|
+
In the same way we manage columns MiniRecord will detect new indexes and indexes that needs to be removed.
|
224
|
+
|
150
225
|
So when you perform `MyModel.auto_upgrade!` a SQL command like:
|
151
226
|
|
152
|
-
```
|
227
|
+
```SQL
|
153
228
|
PRAGMA index_info('index_people_on_name')
|
154
229
|
CREATE INDEX "index_people_on_surname" ON "people" ("surname")
|
155
230
|
```
|
156
231
|
|
157
|
-
|
232
|
+
A quick hint, sometimes index gets too verbose/long:
|
158
233
|
|
159
|
-
```
|
234
|
+
```ruby
|
160
235
|
class Fox < ActiveRecord::Base
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
236
|
+
field :foo, index: true
|
237
|
+
field :foo, index: :custom_name
|
238
|
+
field :foo, index: [:foo, :bar]
|
239
|
+
field :foo, index: { column: [:branch_id, :party_id], unique: true, name: 'by_branch_party' }
|
165
240
|
end
|
166
241
|
```
|
167
242
|
|
168
|
-
|
243
|
+
Here is where `add_index` comes handy, so you can rewrite the above in:
|
169
244
|
|
170
|
-
```
|
245
|
+
```ruby
|
171
246
|
class Fox < ActiveRecord::Base
|
172
|
-
|
247
|
+
field :foo
|
173
248
|
add_index :foo
|
174
249
|
add_index :custom_name
|
175
250
|
add_index [:foo, :bar]
|
176
|
-
add_index [:branch_id, :party_id], :
|
251
|
+
add_index [:branch_id, :party_id], unique: true, name: 'by_branch_party'
|
177
252
|
end
|
178
253
|
```
|
179
254
|
|
255
|
+
## Contributors
|
256
|
+
|
257
|
+
A special thanks to all who have contributed in this project:
|
258
|
+
|
259
|
+
* Dmitriy Partsyrniy
|
260
|
+
* Steven Garcia
|
261
|
+
* Carlo Bertini
|
262
|
+
* Nate Wiger
|
263
|
+
* Dan Watson
|
264
|
+
* Guy Boertje
|
265
|
+
* virtax
|
266
|
+
* Nagy Bence
|
267
|
+
* Takeshi Yabe
|
268
|
+
* blahutka
|
269
|
+
* 4r2r
|
270
|
+
|
180
271
|
## Author
|
181
272
|
|
182
273
|
DAddYE, you can follow me on twitter [@daddye](http://twitter.com/daddye) or take a look at my site [daddye.it](http://www.daddye.it)
|
183
274
|
|
184
275
|
## Copyright
|
185
276
|
|
186
|
-
Copyright (C) 2011 Davide D'Agostino - [@daddye](http://twitter.com/daddye)
|
277
|
+
Copyright (C) 2011-2014 Davide D'Agostino - [@daddye](http://twitter.com/daddye)
|
187
278
|
|
188
279
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
189
280
|
associated documentation files (the “Software”), to deal in the Software without restriction, including without
|
@@ -195,4 +286,4 @@ The above copyright notice and this permission notice shall be included in all c
|
|
195
286
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
196
287
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM,
|
197
288
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
198
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
289
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -52,11 +52,9 @@ module MiniRecord
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def get_sql_field_type(field)
|
55
|
-
if
|
56
|
-
# Rails 3.2 and earlier
|
55
|
+
if ActiveRecord::VERSION::MAJOR.to_i < 4
|
57
56
|
field.sql_type.to_s.downcase
|
58
57
|
else
|
59
|
-
# Rails 4
|
60
58
|
connection.type_to_sql(field.type.to_sym, field.limit, field.precision, field.scale)
|
61
59
|
end
|
62
60
|
end
|
@@ -261,7 +259,7 @@ module MiniRecord
|
|
261
259
|
field inheritance_column, :as => :string unless fields.key?(inheritance_column.to_s)
|
262
260
|
index inheritance_column
|
263
261
|
end
|
264
|
-
|
262
|
+
|
265
263
|
# Rename fields
|
266
264
|
rename_fields.each do |old_name, new_name|
|
267
265
|
old_column = fields_in_db[old_name.to_s]
|
@@ -292,24 +290,8 @@ module MiniRecord
|
|
292
290
|
(fields.keys & fields_in_db.keys).each do |field|
|
293
291
|
if field != primary_key #ActiveRecord::Base.get_primary_key(table_name)
|
294
292
|
changed = false # flag
|
295
|
-
new_type = fields[field].type.to_sym
|
296
293
|
new_attr = {}
|
297
294
|
|
298
|
-
# First, check if the field type changed
|
299
|
-
old_sql_type = get_sql_field_type(fields_in_db[field])
|
300
|
-
new_sql_type = get_sql_field_type(fields[field])
|
301
|
-
|
302
|
-
# Strip off the "(10,0)", from "decimal(10,0)" - we re-check this below.
|
303
|
-
# This is all a bit hacky but different versions of Rails act differently.
|
304
|
-
old_base_type = old_sql_type.sub(/\(.*/,'')
|
305
|
-
new_base_type = new_sql_type.sub(/\(.*/,'')
|
306
|
-
|
307
|
-
if old_sql_type != new_sql_type and old_base_type != new_base_type
|
308
|
-
logger.debug "[MiniRecord] Detected schema change for #{table_name}.#{field}#type " +
|
309
|
-
" from #{old_sql_type.inspect} to #{new_sql_type.inspect}" if logger
|
310
|
-
changed = true
|
311
|
-
end
|
312
|
-
|
313
295
|
# Special catch for precision/scale, since *both* must be specified together
|
314
296
|
# Always include them in the attr struct, but they'll only get applied if changed = true
|
315
297
|
new_attr[:precision] = fields[field][:precision]
|
@@ -339,6 +321,7 @@ module MiniRecord
|
|
339
321
|
end
|
340
322
|
|
341
323
|
# Change the column if applicable
|
324
|
+
new_type = fields[field].type.to_sym
|
342
325
|
connection.change_column table_name, field, new_type, new_attr if changed
|
343
326
|
end
|
344
327
|
end
|
@@ -346,14 +329,16 @@ module MiniRecord
|
|
346
329
|
remove_foreign_keys if connection.respond_to?(:foreign_keys)
|
347
330
|
|
348
331
|
# Remove old index
|
349
|
-
|
332
|
+
index_names = indexes.collect{|name,opts| opts[:name] || name }
|
333
|
+
(indexes_in_db.keys - index_names).each do |name|
|
350
334
|
connection.remove_index(table_name, :name => name)
|
351
335
|
end
|
352
336
|
|
353
337
|
# Add indexes
|
354
338
|
indexes.each do |name, options|
|
355
339
|
options = options.dup
|
356
|
-
|
340
|
+
index_name = options[:name] || name
|
341
|
+
unless connection.indexes(table_name).detect { |i| i.name == index_name }
|
357
342
|
connection.add_index(table_name, options.delete(:column), options)
|
358
343
|
end
|
359
344
|
end
|
data/lib/mini_record/version.rb
CHANGED
data/mini_record.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "mini_record"
|
7
7
|
s.version = MiniRecord::VERSION
|
8
8
|
s.authors = ["Davide D'Agostino"]
|
9
|
-
s.email = ["
|
9
|
+
s.email = ["info@daddye.it"]
|
10
10
|
s.homepage = "https://github.com/DAddYE/mini_record"
|
11
11
|
s.summary = %q{MiniRecord is a micro gem that allow you to write schema inside your model as you can do in DataMapper.}
|
12
12
|
s.description = %q{
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Davide D'Agostino
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -28,7 +28,7 @@ description: "\nWith it you can add the ability to create columns outside the de
|
|
28
28
|
schema, directly\nin your model in a similar way that you just know in others projects\nlike
|
29
29
|
\ DataMapper or MongoMapper.\n "
|
30
30
|
email:
|
31
|
-
-
|
31
|
+
- info@daddye.it
|
32
32
|
executables: []
|
33
33
|
extensions: []
|
34
34
|
extra_rdoc_files: []
|