mini_record 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  MiniRecord is a micro extension for our `ActiveRecord` gem.
2
- With it you can add the ability to create columns outside the default schema, directly
3
- in your **model** in a similar way that you just know in others projects
4
- like DataMapper or MongoMapper.
2
+ With MiniRecord you can add the ability to create columns outside the default `schema.rb`, directly
3
+ in your **model** in a similar way that should know in others projects
4
+ like DataMapper, MongoMapper or MongoID.
5
5
 
6
6
  My inspiration come from this handy [project](https://github.com/pjhyett/auto_migrations).
7
7
 
@@ -14,8 +14,8 @@ My inspiration come from this handy [project](https://github.com/pjhyett/auto_mi
14
14
 
15
15
  ## Instructions
16
16
 
17
- What you need is to move/remove `db/migrations` and `db/schema.rb`.
18
- It's no more necessary and it avoid conflicts.
17
+ What you need is to move/remove your `db/schema.rb`.
18
+ This avoid conflicts.
19
19
 
20
20
  Add to your `Gemfile`:
21
21
 
@@ -36,38 +36,50 @@ class Person < ActiveRecord::Base
36
36
  s.string :name
37
37
  s.integer :address_id
38
38
  end
39
+ add_index :address_id
40
+
39
41
  belongs_to :address
40
42
  end
41
43
  Person.auto_upgrade!
42
44
 
43
- # you can use also this way
44
- class Address < ActiveRecord::Base
45
- key.string :city
46
- key.string :state
47
- key.integer :number
48
- has_many :people
45
+ # you can use also this SEXY way
46
+ class Post < ActiveRecord::Base
47
+ key :title
48
+ key :permalink, :index => true, :limit => 50
49
+ key :comments_count, :as => :integer
50
+ key :category, :as => :references, :index => true
49
51
  end
52
+ Post.auto_upgrade!
53
+ ```
50
54
 
51
- # or this
52
- class Address < ActiveRecord::Base
53
- col.string :city
54
- col.string :state
55
- col.integer :number
56
- has_many :people
57
- end
55
+ If you don't like `key` there are also few aliases: `col, field, property`
58
56
 
59
- # or this
60
- class Address < ActiveRecord::Base
61
- property.string :city
62
- property.string :state
63
- property.integer :number
64
- has_many :people
65
- end
57
+ Instead of `:as => :my_type` you can use `:type => :my_type`
58
+
59
+ Option `:as` or `:type` if not provided are `:string`, you can use all ActiveRecord types:
60
+
61
+ ``` rb
62
+ :primary_key, :string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean
63
+ :references, :belongs_to, :primary_key, :timestamp
64
+ ```
66
65
 
67
- Address.auto_upgrade!
66
+ You can provide others ActiveRecord options like:
67
+
68
+ ``` rb
69
+ :limit, :default, :null, :precision, :scale
70
+
71
+ # example
72
+ class Foo < ActiveRecord::Base
73
+ key :title, :default => "MyTitle" # :as => :string is by default
74
+ key :price, :as => :decimal, :scale => 8, :precision => 2
75
+ end
68
76
  ```
69
77
 
70
- Once you bootstrap your **app**, missing columns and tables will be created on the fly.
78
+ See [ActiveRecord::TableDefinition](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html)
79
+ for more details.
80
+
81
+ Finally, when you execute `MyModel.auto_upgrade!`, missing columns, indexes and tables will be created on the fly.
82
+ Indexes and columns present in the db but **not** in your model schema will be **deleted*** also in your db.
71
83
 
72
84
  ### Adding a new column
73
85
 
@@ -82,17 +94,20 @@ class Person < ActiveRecord::Base
82
94
  end
83
95
  belongs_to :address
84
96
  end
97
+ Person.auto_upgrade!
85
98
 
86
- # or if you use others ways
87
- class Person < ActiveRecord::Base
88
- col.string :name
89
- col.string :surname # <<- this
90
- col.integer :address_id
91
- belongs_to :address
99
+ # or you can use a more interesting way
100
+ class Post < ActiveRecord::Base
101
+ key :title
102
+ key :body, :as => :text # <<- this
103
+ key :permalink, :index => true
104
+ key :comments_count, :as => :integer
105
+ key :category, :as => :references, :index => true
92
106
  end
107
+ Post.auto_upgrade!
93
108
  ```
94
109
 
95
- So now when you start your **webserver** you can see an `ALTER TABLE` statement, this mean that your existing
110
+ So now when you invoke `MyModel.auto_upgrade!` you should see a SQL query like `ALTER TABLE` that mean that your existing
96
111
  records are happy and safe.
97
112
 
98
113
  ### Removing a column
@@ -104,12 +119,44 @@ It's exactly the same, but the column will be _really_ deleted without affect ot
104
119
  It's not possible for us know when/what column you have renamed, but we can know if you changed the `type` so
105
120
  if you change `t.string :name` to `t.text :name` we are be able to perform an `ALTER TABLE`
106
121
 
122
+ ### Add/Remove indexes
123
+
124
+ In the same ways we manage columns MiniRecord will detect new indexes and indexes that needs to be removed.
125
+ So when you perform `MyModel.auto_upgrade!` a SQL command like:
126
+
127
+ ``` SQL
128
+ PRAGMA index_info('index_people_on_name')
129
+ CREATE INDEX "index_people_on_surname" ON "people" ("surname")
130
+ ```
131
+
132
+ Note that writing it in DSL way you have same options as `add_index` so you are be able to write:
133
+
134
+ ``` rb
135
+ class Fox < ActiveRecord::Base
136
+ key :foo, :index => true
137
+ key :foo, :index => :custom_name
138
+ key :foo, :index => [:foo, :bar]
139
+ key :foo, :index => { :column => [:branch_id, :party_id], :unique => true, :name => 'by_branch_party' }
140
+ end
141
+ ```
142
+
143
+ That is the same of:
144
+
145
+ ``` rb
146
+ class Fox < ActiveRecord::Base
147
+ key :foo
148
+ add_index :foo
149
+ add_index :custom_name
150
+ add_index [:foo, :bar]
151
+ add_index [:branch_id, :party_id], :unique => true, :name => 'by_branch_party'
152
+ end
153
+ ```
154
+
107
155
  ## Warnings
108
156
 
109
157
  This software is not yet tested in a production project, now is only heavy development and if you can
110
158
  pleas fork it, find bug add a spec and then come back with a pull request. Thanks!
111
159
 
112
-
113
160
  ## Author
114
161
 
115
162
  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)
@@ -11,9 +11,23 @@ module MiniRecord
11
11
  tb.primary_key(primary_key)
12
12
  end
13
13
  end
14
- alias :col :table_definition
15
- alias :key :table_definition
16
- alias :property :table_definition
14
+
15
+ def col(column_name, options={})
16
+ type = options.delete(:as) || options.delete(:type) || :string
17
+ table_definition.send(type, column_name, options)
18
+ column_name = table_definition.columns[-1].name
19
+ case index_name = options.delete(:index)
20
+ when Hash
21
+ add_index(options.delete(:column) || column_name, index_name)
22
+ when TrueClass
23
+ add_index(column_name)
24
+ when String, Symbol, Array
25
+ add_index(index_name)
26
+ end
27
+ end
28
+ alias :key :col
29
+ alias :property :col
30
+ alias :field :col
17
31
 
18
32
  def reset_table_definition!
19
33
  @_table_definition = nil
@@ -26,6 +40,17 @@ module MiniRecord
26
40
  alias :keys :schema
27
41
  alias :properties :schema
28
42
 
43
+ def add_index(column_name, options={})
44
+ index_name = connection.index_name(table_name, :column => column_name)
45
+ indexes[index_name] = options.merge(:column => column_name)
46
+ index_name
47
+ end
48
+ alias :index :add_index
49
+
50
+ def indexes
51
+ @_indexes ||= {}
52
+ end
53
+
29
54
  def auto_upgrade!
30
55
  # Table doesn't exist, create it
31
56
  unless connection.tables.include?(table_name)
@@ -95,6 +120,20 @@ module MiniRecord
95
120
  end
96
121
  end
97
122
 
123
+ # Remove old index
124
+ indexes_in_db = connection.indexes(table_name).map(&:name)
125
+ (indexes_in_db - indexes.keys).each do |name|
126
+ connection.remove_index(table_name, :name => name)
127
+ end
128
+
129
+ # Add indexes
130
+ indexes.each do |name, options|
131
+ options = options.dup
132
+ unless connection.indexes(table_name).detect { |i| i.name == name }
133
+ connection.add_index(table_name, options.delete(:column), options)
134
+ end
135
+ end
136
+
98
137
  # Reload column information
99
138
  reset_column_information
100
139
  end
@@ -1,3 +1,3 @@
1
1
  module MiniRecord
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -59,8 +59,8 @@ describe MiniRecord do
59
59
  ActiveRecord::Base.connection.table_exists?(Post.table_name).must_equal false
60
60
  ActiveRecord::Base.connection.table_exists?(Category.table_name).must_equal false
61
61
  Post.auto_upgrade!; Category.auto_upgrade!
62
- Post.column_names.must_equal Post.db_columns
63
- Category.column_names.must_equal Category.schema_columns
62
+ Post.column_names.sort.must_equal Post.db_columns
63
+ Category.column_names.sort.must_equal Category.schema_columns
64
64
 
65
65
  # Check default properties
66
66
  category = Category.create(:title => 'category')
@@ -70,15 +70,40 @@ describe MiniRecord do
70
70
  post.body.must_equal 'bar'
71
71
  post.category.must_equal category
72
72
 
73
+
73
74
  # Remove a column
74
75
  Post.reset_table_definition!
75
76
  Post.class_eval do
76
- key.string :name
77
- key.references :category
77
+ key :name
78
+ key :category, :as => :references
78
79
  end
79
80
  Post.auto_upgrade!
80
81
  post = Post.first
81
82
  post.name.must_be_nil
82
83
  post.category.must_equal category
84
+ post.wont_respond_to :title
85
+ end
86
+
87
+ it 'has indexes inside model' do
88
+ # Check indexes
89
+ Animal.auto_upgrade!
90
+ Animal.db_indexes.size.must_be :>, 0
91
+ Animal.db_indexes.must_equal Animal.indexes.keys.sort
92
+
93
+ indexes_was = Animal.db_indexes
94
+
95
+ # Remove an index
96
+ Animal.indexes.delete(indexes_was.pop)
97
+ Animal.auto_upgrade!
98
+ Animal.indexes.keys.sort.must_equal indexes_was
99
+ Animal.db_indexes.must_equal indexes_was
100
+
101
+ # Add a new index
102
+ Animal.class_eval do
103
+ key :category, :as => :references, :index => true
104
+ end
105
+ Animal.auto_upgrade!
106
+ Animal.db_columns.must_include "category_id"
107
+ Animal.db_indexes.must_equal((indexes_was << "index_animals_on_category_id").sort)
83
108
  end
84
109
  end
data/spec/models.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require 'logger'
2
2
 
3
3
  ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
4
- # ActiveRecord::Base.connection.tables.each { |t| ActiveRecord::Base.connection.drop_table(t) }
5
- # ActiveRecord::Base.logger = Logger.new($stdout)
4
+ # ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new($stdout)
6
5
 
7
6
  module SpecHelper
8
7
  def self.included(base)
@@ -11,11 +10,15 @@ module SpecHelper
11
10
 
12
11
  module ClassMethods
13
12
  def db_columns
14
- connection.columns(table_name).map(&:name)
13
+ connection.columns(table_name).map(&:name).sort
14
+ end
15
+
16
+ def db_indexes
17
+ connection.indexes(table_name).map(&:name).sort
15
18
  end
16
19
 
17
20
  def schema_columns
18
- table_definition.columns.map { |c| c.name.to_s }
21
+ table_definition.columns.map { |c| c.name.to_s }.sort
19
22
  end
20
23
  end
21
24
  end
@@ -30,15 +33,22 @@ end
30
33
  class Post < ActiveRecord::Base
31
34
  include SpecHelper
32
35
 
33
- key.string :title
34
- key.string :body
35
- key.references :category
36
+ key :title
37
+ key :body
38
+ key :category, :as => :references
36
39
  belongs_to :category
37
40
  end
38
41
 
39
42
  class Category < ActiveRecord::Base
40
43
  include SpecHelper
41
44
 
42
- key.string :title
45
+ key :title
43
46
  has_many :posts
44
47
  end
48
+
49
+ class Animal < ActiveRecord::Base
50
+ include SpecHelper
51
+
52
+ key :name, :index => true
53
+ index :id
54
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_record
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Davide D'Agostino
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-09-06 00:00:00 +02:00
18
+ date: 2011-09-10 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -55,7 +55,6 @@ files:
55
55
  - lib/mini_record/auto_schema.rb
56
56
  - lib/mini_record/version.rb
57
57
  - mini_record.gemspec
58
- - rakefile.compiled.rbc
59
58
  - spec/mini_record_spec.rb
60
59
  - spec/models.rb
61
60
  - spec/spec_helper.rb
@@ -1,309 +0,0 @@
1
- !RBIX
2
- 16846133056282117387
3
- x
4
- M
5
- 1
6
- n
7
- n
8
- x
9
- 10
10
- __script__
11
- i
12
- 86
13
- 5
14
- 7
15
- 0
16
- 64
17
- 47
18
- 49
19
- 1
20
- 1
21
- 15
22
- 5
23
- 7
24
- 2
25
- 64
26
- 47
27
- 49
28
- 1
29
- 1
30
- 15
31
- 5
32
- 7
33
- 3
34
- 64
35
- 47
36
- 49
37
- 1
38
- 1
39
- 15
40
- 45
41
- 4
42
- 5
43
- 43
44
- 6
45
- 7
46
- 7
47
- 56
48
- 8
49
- 50
50
- 9
51
- 1
52
- 15
53
- 5
54
- 44
55
- 43
56
- 10
57
- 79
58
- 49
59
- 11
60
- 1
61
- 13
62
- 7
63
- 12
64
- 7
65
- 7
66
- 49
67
- 13
68
- 2
69
- 15
70
- 47
71
- 49
72
- 14
73
- 1
74
- 15
75
- 5
76
- 44
77
- 43
78
- 10
79
- 79
80
- 49
81
- 11
82
- 1
83
- 13
84
- 7
85
- 15
86
- 7
87
- 7
88
- 49
89
- 13
90
- 2
91
- 15
92
- 47
93
- 49
94
- 14
95
- 1
96
- 15
97
- 2
98
- 11
99
- I
100
- 5
101
- I
102
- 0
103
- I
104
- 0
105
- I
106
- 0
107
- n
108
- p
109
- 16
110
- s
111
- 17
112
- bundler/gem_tasks
113
- x
114
- 7
115
- require
116
- s
117
- 4
118
- rake
119
- s
120
- 13
121
- rake/testtask
122
- x
123
- 4
124
- Rake
125
- n
126
- x
127
- 8
128
- TestTask
129
- x
130
- 4
131
- test
132
- M
133
- 1
134
- p
135
- 2
136
- x
137
- 9
138
- for_block
139
- t
140
- n
141
- x
142
- 9
143
- __block__
144
- i
145
- 46
146
- 57
147
- 19
148
- 0
149
- 15
150
- 20
151
- 0
152
- 49
153
- 0
154
- 0
155
- 7
156
- 1
157
- 64
158
- 49
159
- 2
160
- 1
161
- 15
162
- 20
163
- 0
164
- 45
165
- 3
166
- 4
167
- 7
168
- 5
169
- 64
170
- 49
171
- 6
172
- 1
173
- 13
174
- 18
175
- 2
176
- 49
177
- 7
178
- 1
179
- 15
180
- 15
181
- 20
182
- 0
183
- 2
184
- 13
185
- 18
186
- 2
187
- 49
188
- 8
189
- 1
190
- 15
191
- 11
192
- I
193
- 5
194
- I
195
- 1
196
- I
197
- 1
198
- I
199
- 1
200
- n
201
- p
202
- 9
203
- x
204
- 4
205
- libs
206
- s
207
- 4
208
- spec
209
- x
210
- 2
211
- <<
212
- x
213
- 3
214
- Dir
215
- n
216
- s
217
- 17
218
- spec/**/*_spec.rb
219
- x
220
- 2
221
- []
222
- x
223
- 11
224
- test_files=
225
- x
226
- 8
227
- verbose=
228
- p
229
- 9
230
- I
231
- 0
232
- I
233
- 5
234
- I
235
- 4
236
- I
237
- 6
238
- I
239
- 10
240
- I
241
- 7
242
- I
243
- 23
244
- I
245
- 8
246
- I
247
- 2e
248
- x
249
- 42
250
- /Developer/src/Extras/mini_record/rakefile
251
- p
252
- 1
253
- x
254
- 4
255
- test
256
- x
257
- 3
258
- new
259
- x
260
- 4
261
- Hash
262
- x
263
- 16
264
- new_from_literal
265
- x
266
- 7
267
- default
268
- x
269
- 3
270
- []=
271
- x
272
- 4
273
- task
274
- x
275
- 4
276
- spec
277
- p
278
- 13
279
- I
280
- 0
281
- I
282
- 1
283
- I
284
- 9
285
- I
286
- 2
287
- I
288
- 12
289
- I
290
- 3
291
- I
292
- 1b
293
- I
294
- 5
295
- I
296
- 28
297
- I
298
- b
299
- I
300
- 3e
301
- I
302
- c
303
- I
304
- 56
305
- x
306
- 42
307
- /Developer/src/Extras/mini_record/rakefile
308
- p
309
- 0