active_hash 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07f278485648e475f69c32f40ae5f647a7e275c5
4
- data.tar.gz: 04811d2113fdf923916200ebfe3966f6f6d3e4be
3
+ metadata.gz: 652802c90d3e70506b8997f124021284e8b073be
4
+ data.tar.gz: a4b876f9bc3c7316c6d12f3945e2b74b20b8a11f
5
5
  SHA512:
6
- metadata.gz: 76e9b4d4d67e4863473388961024dd66af1b2b81771798f1fb24417060ffd93b93887dadea24dce45cde7d13ccf0759c93775710987281ed18a05009bb083bb1
7
- data.tar.gz: c29c149a4db09945d9c616d616223b629771d74316d43465d6b412b7b02b0146fe09f37270734579bc11b77b71315cde671387ea1cace714f39eb9c1bff92b8c
6
+ metadata.gz: 53e0ad1f1e45a7adb6cd51ea367102ec959a21c19245d52ec9534c6976754fdf888efe3da463818ff1c14c9c0048fa2c0e51a9b4164857ee811076eb6af11612
7
+ data.tar.gz: cb66a911b00f3b9b4c25de6485fc0e7b9fff3b66efeabd5e70a5dcf52134afba7d990951cc232beaec45dc4ed12b1760c3fe79e1a818b7d317bd8f6a15692d67
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 2015-09-13 (v1.4.1)
2
+ - fix bug where `#attributes` didn't contain default values #107
3
+ - add support for `.find_by` and `#_read_attribute`. Thanks, @andrewfader!
4
+
1
5
  2014-09-03 (v1.4.0)
2
6
  - support Rails 4.2 (agraves, al2o3cr)
3
7
 
data/README.md CHANGED
@@ -18,38 +18,38 @@ ActiveHash also ships with:
18
18
  ## Installation
19
19
 
20
20
  Bundler:
21
-
22
- gem 'active_hash'
23
-
21
+ ```ruby
22
+ gem 'active_hash'
23
+ ```
24
24
  Other:
25
-
26
- gem install active_hash
27
-
25
+ ```ruby
26
+ gem install active_hash
27
+ ```
28
28
  ## Reason for being
29
29
 
30
30
  We wrote ActiveHash so that we could use simple, in-memory, ActiveRecord-like data structures that play well with Rails forms, like:
31
-
32
- # in app/models/country.rb
33
- class Country < ActiveHash::Base
34
- self.data = [
35
- {:id => 1, :name => "US"},
36
- {:id => 2, :name => "Canada"}
37
- ]
38
- end
39
-
40
- # in some view
41
- <%= collection_select :person, :country_id, Country.all, :id, :name %>
42
-
31
+ ```ruby
32
+ # in app/models/country.rb
33
+ class Country < ActiveHash::Base
34
+ self.data = [
35
+ {:id => 1, :name => "US"},
36
+ {:id => 2, :name => "Canada"}
37
+ ]
38
+ end
39
+
40
+ # in some view
41
+ <%= collection_select :person, :country_id, Country.all, :id, :name %>
42
+ ```
43
43
  Before ActiveHash, we did things like:
44
-
45
- # in app/models/person.rb
46
- class Person < ActiveRecord::Base
47
- COUNTRIES = ["US", "Canada"]
48
- end
49
-
50
- # in some view
51
- <%= collection_select :person, :country_id, Person::COUNTRIES, :to_s, :to_s %>
52
-
44
+ ```ruby
45
+ # in app/models/person.rb
46
+ class Person < ActiveRecord::Base
47
+ COUNTRIES = ["US", "Canada"]
48
+ end
49
+
50
+ # in some view
51
+ <%= collection_select :person, :country_id, Person::COUNTRIES, :to_s, :to_s %>
52
+ ```
53
53
  The majority of ActiveHash uses involve setting up some data at boot time, and never modifying that data at runtime.
54
54
 
55
55
  ## Usage
@@ -61,261 +61,261 @@ To use ActiveHash, you need to:
61
61
  * Define your fields and/or default values
62
62
 
63
63
  A quick example would be:
64
-
65
- class Country < ActiveHash::Base
66
- self.data = [
67
- {:id => 1, :name => "US"},
68
- {:id => 2, :name => "Canada"}
69
- ]
70
- end
71
-
72
- country = Country.new(:name => "Mexico")
73
- country.name # => "Mexico"
74
- country.name? # => true
75
-
64
+ ```ruby
65
+ class Country < ActiveHash::Base
66
+ self.data = [
67
+ {:id => 1, :name => "US"},
68
+ {:id => 2, :name => "Canada"}
69
+ ]
70
+ end
71
+
72
+ country = Country.new(:name => "Mexico")
73
+ country.name # => "Mexico"
74
+ country.name? # => true
75
+ ```
76
76
  You can also use _create_:
77
-
78
- class Country < ActiveHash::Base
79
- field :name
80
- create :id => 1, :name => "US"
81
- create :id => 2, :name => "Canada"
82
- end
83
-
77
+ ```ruby
78
+ class Country < ActiveHash::Base
79
+ field :name
80
+ create :id => 1, :name => "US"
81
+ create :id => 2, :name => "Canada"
82
+ end
83
+ ```
84
84
  You can also use _add_:
85
-
86
- class Country < ActiveHash::Base
87
- field :name
88
- add :id => 1, :name => "US"
89
- add :id => 2, :name => "Canada"
90
- end
91
-
85
+ ```ruby
86
+ class Country < ActiveHash::Base
87
+ field :name
88
+ add :id => 1, :name => "US"
89
+ add :id => 2, :name => "Canada"
90
+ end
91
+ ```
92
92
  ## Auto-Defined fields
93
93
 
94
94
  ActiveHash will auto-define all fields for you when you load the hash. For example, if you have the following class:
95
-
96
- class CustomField < ActiveHash::Base
97
- self.data = [
98
- {:custom_field_1 => "foo"},
99
- {:custom_field_2 => "foo"},
100
- {:custom_field_3 => "foo"}
101
- ]
102
- end
103
-
95
+ ```ruby
96
+ class CustomField < ActiveHash::Base
97
+ self.data = [
98
+ {:custom_field_1 => "foo"},
99
+ {:custom_field_2 => "foo"},
100
+ {:custom_field_3 => "foo"}
101
+ ]
102
+ end
103
+ ```
104
104
  Once you call CustomField.all it will define methods for :custom_field_1, :custom_field_2 etc...
105
105
 
106
106
  If you need the fields at load time, as opposed to after .all is called, you can also define them manually, like so:
107
-
108
- class CustomField < ActiveHash::Base
109
- fields :custom_field_1, :custom_field_2, :custom_field_3
110
- end
111
-
107
+ ```ruby
108
+ class CustomField < ActiveHash::Base
109
+ fields :custom_field_1, :custom_field_2, :custom_field_3
110
+ end
111
+ ```
112
112
  NOTE: auto-defined fields will _not_ override fields you've defined, either on the class or on the instance.
113
113
 
114
114
  ## Defining Fields with default values
115
115
 
116
116
  If some of your hash values contain nil, and you want to provide a default, you can specify defaults with the :field method:
117
-
118
- class Country < ActiveHash::Base
119
- field :is_axis_of_evil, :default => false
120
- end
121
-
117
+ ```ruby
118
+ class Country < ActiveHash::Base
119
+ field :is_axis_of_evil, :default => false
120
+ end
121
+ ```
122
122
  ## Defining Data
123
123
 
124
124
  You can define data inside your class or outside. For example, you might have a class like this:
125
-
126
- # app/models/country.rb
127
- class Country < ActiveHash::Base
128
- end
129
-
130
- # config/initializers/data.rb
131
- Rails.application.config.to_prepare do
132
- Country.data = [
133
- {:id => 1, :name => "US"},
134
- {:id => 2, :name => "Canada"}
135
- ]
136
- end
137
-
125
+ ```ruby
126
+ # app/models/country.rb
127
+ class Country < ActiveHash::Base
128
+ end
129
+
130
+ # config/initializers/data.rb
131
+ Rails.application.config.to_prepare do
132
+ Country.data = [
133
+ {:id => 1, :name => "US"},
134
+ {:id => 2, :name => "Canada"}
135
+ ]
136
+ end
137
+ ```
138
138
  If you prefer to store your data in YAML, see below.
139
139
 
140
140
  ## Class Methods
141
141
 
142
142
  ActiveHash gives you ActiveRecord-esque methods like:
143
-
144
- Country.all # => returns all Country objects
145
- Country.count # => returns the length of the .data array
146
- Country.first # => returns the first country object
147
- Country.last # => returns the last country object
148
- Country.find 1 # => returns the first country object with that id
149
- Country.find [1,2] # => returns all Country objects with ids in the array
150
- Country.find :all # => same as .all
151
- Country.find :all, args # => the second argument is totally ignored, but allows it to play nicely with AR
152
- Country.find_by_id 1 # => find the first object that matches the id
153
-
143
+ ```ruby
144
+ Country.all # => returns all Country objects
145
+ Country.count # => returns the length of the .data array
146
+ Country.first # => returns the first country object
147
+ Country.last # => returns the last country object
148
+ Country.find 1 # => returns the first country object with that id
149
+ Country.find [1,2] # => returns all Country objects with ids in the array
150
+ Country.find :all # => same as .all
151
+ Country.find :all, args # => the second argument is totally ignored, but allows it to play nicely with AR
152
+ Country.find_by_id 1 # => find the first object that matches the id
153
+ ```
154
154
  It also gives you a few dynamic finder methods. For example, if you defined :name as a field, you'd get:
155
-
156
- Country.find_by_name "foo" # => returns the first object matching that name
157
- Country.find_all_by_name "foo" # => returns an array of the objects with matching names
158
- Country.find_by_id_and_name 1, "Germany" # => returns the first object matching that id and name
159
- Country.find_all_by_id_and_name 1, "Germany" # => returns an array of objects matching that name and id
160
-
155
+ ```ruby
156
+ Country.find_by_name "foo" # => returns the first object matching that name
157
+ Country.find_all_by_name "foo" # => returns an array of the objects with matching names
158
+ Country.find_by_id_and_name 1, "Germany" # => returns the first object matching that id and name
159
+ Country.find_all_by_id_and_name 1, "Germany" # => returns an array of objects matching that name and id
160
+ ```
161
161
  ## Instance Methods
162
162
 
163
163
  ActiveHash objects implement enough of the ActiveRecord api to satisfy most common needs. For example:
164
-
165
- Country#id # => returns the id or nil
166
- Country#id= # => sets the id attribute
167
- Country#quoted_id # => returns the numeric id
168
- Country#to_param # => returns the id as a string
169
- Country#new_record? # => returns true if is not part of Country.all, false otherwise
170
- Country#readonly? # => true
171
- Country#hash # => the hash of the id (or the hash of nil)
172
- Country#eql? # => compares type and id, returns false if id is nil
173
-
164
+ ```
165
+ Country#id # => returns the id or nil
166
+ Country#id= # => sets the id attribute
167
+ Country#quoted_id # => returns the numeric id
168
+ Country#to_param # => returns the id as a string
169
+ Country#new_record? # => returns true if is not part of Country.all, false otherwise
170
+ Country#readonly? # => true
171
+ Country#hash # => the hash of the id (or the hash of nil)
172
+ Country#eql? # => compares type and id, returns false if id is nil
173
+ ```
174
174
  ActiveHash also gives you methods related to the fields you defined. For example, if you defined :name as a field, you'd get:
175
-
176
- Country#name # => returns the passed in name
177
- Country#name? # => returns true if the name is not blank
178
- Country#name= # => sets the name
179
-
175
+ ```
176
+ Country#name # => returns the passed in name
177
+ Country#name? # => returns true if the name is not blank
178
+ Country#name= # => sets the name
179
+ ```
180
180
  ## Saving in-memory records
181
181
 
182
182
  The ActiveHash::Base.all method functions like an in-memory data store. You can save your records to the the .all array by using standard ActiveRecord create and save methods:
183
-
184
- Country.all # => []
185
- Country.create
186
- Country.all # [ <Country :id => 1> ]
187
- country = Country.new
188
- country.new_record? # => true
189
- country.save
190
- country.new_record? # => false
191
- Country.all # [ <Country :id => 1>, <Country :id => 2> ]
192
-
183
+ ```ruby
184
+ Country.all # => []
185
+ Country.create
186
+ Country.all # [ <Country :id => 1> ]
187
+ country = Country.new
188
+ country.new_record? # => true
189
+ country.save
190
+ country.new_record? # => false
191
+ Country.all # [ <Country :id => 1>, <Country :id => 2> ]
192
+ ```
193
193
  Notice that when adding records to the collection, it will auto-increment the id for you by default. If you use string ids, it will not auto-increment the id. Available methods are:
194
-
195
- Country.insert( record )
196
- Country#save
197
- Country#save!
198
- Country.create
199
- Country.create!
200
-
194
+ ```
195
+ Country.insert( record )
196
+ Country#save
197
+ Country#save!
198
+ Country.create
199
+ Country.create!
200
+ ```
201
201
  As such, ActiveHash::Base and its descendants should work with Fixjour or FactoryGirl, so you can treat ActiveHash records the same way you would any other ActiveRecord model in tests.
202
202
 
203
203
  To clear all records from the in-memory array, call delete_all:
204
-
205
- Country.delete_all # => does not affect the yaml files in any way - just clears the in-memory array which can be useful for testing
206
-
204
+ ```ruby
205
+ Country.delete_all # => does not affect the yaml files in any way - just clears the in-memory array which can be useful for testing
206
+ ```
207
207
  ## Referencing ActiveHash objects from ActiveRecord Associations
208
208
 
209
209
  One common use case for ActiveHash is to have top-level objects in memory that ActiveRecord objects belong to.
210
210
 
211
211
  In versions of ActiveRecord previous to 3.1, you should be able to do the following:
212
-
213
- class Country < ActiveHash::Base
214
- end
215
-
216
- class Person < ActiveRecord::Base
217
- belongs_to :country
218
- end
219
-
212
+ ```ruby
213
+ class Country < ActiveHash::Base
214
+ end
215
+
216
+ class Person < ActiveRecord::Base
217
+ belongs_to :country
218
+ end
219
+ ```
220
220
  However, as of ActiveRecord 3.1 support for ActiveRecord's `belong_to` is broken. Instead, you must extend ActiveHash::Associations::ActiveRecordExtensions method:
221
-
222
- class Country < ActiveHash::Base
223
- end
224
-
225
- class Person < ActiveRecord::Base
226
- extend ActiveHash::Associations::ActiveRecordExtensions
227
- belongs_to :country
228
- end
229
-
221
+ ```ruby
222
+ class Country < ActiveHash::Base
223
+ end
224
+
225
+ class Person < ActiveRecord::Base
226
+ extend ActiveHash::Associations::ActiveRecordExtensions
227
+ belongs_to :country
228
+ end
229
+ ```
230
230
  NOTE: this needs to be called on a subclass of ActiveRecord::Base. If you extend ActiveRecord::Base, it will not work.
231
231
  If you want to extend ActiveRecord::Base so all your AR models can belong to ActiveHash::Base objects, you can use the
232
232
  `belongs_to_active_hash` method:
233
+ ```ruby
234
+ ActiveRecord::Base.extend ActiveHash::Associations::ActiveRecordExtensions
233
235
 
234
- ActiveRecord::Base.extend ActiveHash::Associations::ActiveRecordExtensions
235
-
236
- class Country < ActiveHash::Base
237
- end
238
-
239
- class Person < ActiveRecord::Base
240
- belongs_to_active_hash :country
241
- end
236
+ class Country < ActiveHash::Base
237
+ end
242
238
 
239
+ class Person < ActiveRecord::Base
240
+ belongs_to_active_hash :country
241
+ end
242
+ ```
243
243
  With ActiveRecord versions < 3.1, ActiveHash will also work as a polymorphic parent:
244
-
245
- class Country < ActiveHash::Base
246
- end
247
-
248
- class Person < ActiveRecord::Base
249
- belongs_to :location, :polymorphic => true
250
- end
251
-
252
- person = Person.new
253
- person.location = Country.first
254
- person.save
255
- person.location # => Country.first
256
-
244
+ ```ruby
245
+ class Country < ActiveHash::Base
246
+ end
247
+
248
+ class Person < ActiveRecord::Base
249
+ belongs_to :location, :polymorphic => true
250
+ end
251
+
252
+ person = Person.new
253
+ person.location = Country.first
254
+ person.save
255
+ person.location # => Country.first
256
+ ```
257
257
  However, as of ActiveRecord 3.1 this will not work. If you need support for that, please open an issue.
258
258
 
259
259
  ### Using shortcuts
260
260
 
261
261
  Since ActiveHashes usually are static, we can use shortcuts to assign via an easy to remember string instead of an obscure ID number.
262
-
263
- # app/models/country.rb
264
- class Country < ActiveHash::Base
265
- end
266
-
267
- # app/models/person.rb
268
- class Person < ActiveRecord::Base
269
- extend ActiveHash::Associations::ActiveRecordExtensions
270
- belongs_to_active_hash :country, :shortcuts => [:name]
271
- end
272
-
273
- # config/initializers/data.rb
274
- Rails.application.config.to_prepare do
275
- Country.data = [
276
- {:id => 1, :name => "US"},
277
- {:id => 2, :name => "Canada"}
278
- ]
279
- end
280
-
281
- # Using `rails console`
282
- john = Person.new
283
- john.country_name = "US"
284
- # Is the same as doing `john.country = Country.find_by_name("US")`
285
- john.country_name
286
- # Will return "US", and is the same as doing `john.country.try(:name)`
287
-
262
+ ```ruby
263
+ # app/models/country.rb
264
+ class Country < ActiveHash::Base
265
+ end
266
+
267
+ # app/models/person.rb
268
+ class Person < ActiveRecord::Base
269
+ extend ActiveHash::Associations::ActiveRecordExtensions
270
+ belongs_to_active_hash :country, :shortcuts => [:name]
271
+ end
272
+
273
+ # config/initializers/data.rb
274
+ Rails.application.config.to_prepare do
275
+ Country.data = [
276
+ {:id => 1, :name => "US"},
277
+ {:id => 2, :name => "Canada"}
278
+ ]
279
+ end
280
+
281
+ # Using `rails console`
282
+ john = Person.new
283
+ john.country_name = "US"
284
+ # Is the same as doing `john.country = Country.find_by_name("US")`
285
+ john.country_name
286
+ # Will return "US", and is the same as doing `john.country.try(:name)`
287
+ ```
288
288
  You can have multiple shortcuts, so settings `:shortcuts => [:name, :friendly_name]` will enable you to use `#country_name=` and `#country_friendly_name=`.
289
289
 
290
290
  ## Referencing ActiveRecord objects from ActiveHash
291
291
 
292
292
  If you include the ActiveHash::Associations module, you can also create associations from your ActiveHash classes, like so:
293
-
294
- class Country < ActiveHash::Base
295
- include ActiveHash::Associations
296
- has_many :people
297
- end
298
-
299
- class Person < ActiveHash::Base
300
- include ActiveHash::Associations
301
- belongs_to :country
302
- has_many :pets
303
- end
304
-
305
- class Pet < ActiveRecord::Base
306
- end
307
-
293
+ ```ruby
294
+ class Country < ActiveHash::Base
295
+ include ActiveHash::Associations
296
+ has_many :people
297
+ end
298
+
299
+ class Person < ActiveHash::Base
300
+ include ActiveHash::Associations
301
+ belongs_to :country
302
+ has_many :pets
303
+ end
304
+
305
+ class Pet < ActiveRecord::Base
306
+ end
307
+ ```
308
308
  Once you define a belongs to, you also get the setter method:
309
-
310
- class City < ActiveHash::Base
311
- include ActiveHash::Associations
312
- belongs_to :state
313
- end
314
-
315
- city = City.new
316
- city.state = State.first
317
- city.state_id # is State.first.id
318
-
309
+ ```ruby
310
+ class City < ActiveHash::Base
311
+ include ActiveHash::Associations
312
+ belongs_to :state
313
+ end
314
+
315
+ city = City.new
316
+ city.state = State.first
317
+ city.state_id # is State.first.id
318
+ ```
319
319
  NOTE: You cannot use ActiveHash objects as children of ActiveRecord and I don't plan on adding support for that. It doesn't really make any sense, since you'd have to hard-code your database ids in your class or yaml files, which is a dependency inversion.
320
320
 
321
321
  Thanks to baldwindavid for the ideas and code on that one.
@@ -323,138 +323,138 @@ Thanks to baldwindavid for the ideas and code on that one.
323
323
  ## ActiveYaml
324
324
 
325
325
  If you want to store your data in YAML files, just inherit from ActiveYaml and specify your path information:
326
-
327
- class Country < ActiveYaml::Base
328
- end
329
-
326
+ ```ruby
327
+ class Country < ActiveYaml::Base
328
+ end
329
+ ```
330
330
  By default, this class will look for a yml file named "countries.yml" in the same directory as the file. You can either change the directory it looks in, the filename it looks for, or both:
331
-
332
- class Country < ActiveYaml::Base
333
- set_root_path "/u/data"
334
- set_filename "sample"
335
- end
336
-
331
+ ```ruby
332
+ class Country < ActiveYaml::Base
333
+ set_root_path "/u/data"
334
+ set_filename "sample"
335
+ end
336
+ ```
337
337
  The above example will look for the file "/u/data/sample.yml".
338
338
 
339
339
  Since ActiveYaml just creates a hash from the YAML file, you will have all fields specified in YAML auto-defined for you. You can format your YAML as an array, or as a hash:
340
-
341
- # array style
342
- - id: 1
343
- name: US
344
- - id: 2
345
- name: Canada
346
- - id: 3
347
- name: Mexico
348
-
349
- # hash style
350
- us:
351
- id: 1
352
- name: US
353
- canada:
354
- id: 2
355
- name: Canada
356
- mexico:
357
- id: 3
358
- name: Mexico
359
-
340
+ ```
341
+ # array style
342
+ - id: 1
343
+ name: US
344
+ - id: 2
345
+ name: Canada
346
+ - id: 3
347
+ name: Mexico
348
+
349
+ # hash style
350
+ us:
351
+ id: 1
352
+ name: US
353
+ canada:
354
+ id: 2
355
+ name: Canada
356
+ mexico:
357
+ id: 3
358
+ name: Mexico
359
+ ```
360
360
  ### Multiple files per model
361
361
 
362
362
  You can use multiple files to store your data. You will have to choose between hash or array style as you cannot use both for one model.
363
-
364
- class Country < ActiveYaml::Base
365
- use_mutliple_files
366
- set_filenames "europe", "america", "asia", "africa"
367
- end
368
-
363
+ ```ruby
364
+ class Country < ActiveYaml::Base
365
+ use_mutliple_files
366
+ set_filenames "europe", "america", "asia", "africa"
367
+ end
368
+ ```
369
369
  ### Using aliases in YAML
370
370
 
371
371
  Aliases can be used in ActiveYaml using either array or hash style by including `ActiveYaml::Aliases`.
372
372
  With that module included, keys beginning with a '/' character can be safely added, and will be ignored, allowing you to add aliases anywhere in your code:
373
-
374
- # Array Style
375
- - /aliases:
376
- soda_flavor: &soda_flavor
377
- sweet
378
- soda_price: &soda_price
379
- 1.0
380
-
381
- - id: 1
382
- name: Coke
383
- flavor: *soda_flavor
384
- price: *soda_price
385
-
386
-
387
- # Key style
388
- /aliases:
389
- soda_flavor: &soda_flavor
390
- sweet
391
- soda_price: &soda_price
392
- 1.0
393
-
394
- coke:
395
- id: 1
396
- name: Coke
397
- flavor: *soda_flavor
398
- price: *soda_price
399
-
400
- class Soda < ActiveYaml::Base
401
- include ActiveYaml::Aliases
402
- end
403
-
404
- Soda.length # => 1
405
- Soda.first.flavor # => sweet
406
- Soda.first.price # => 1.0
407
-
373
+ ```
374
+ # Array Style
375
+ - /aliases:
376
+ soda_flavor: &soda_flavor
377
+ sweet
378
+ soda_price: &soda_price
379
+ 1.0
380
+
381
+ - id: 1
382
+ name: Coke
383
+ flavor: *soda_flavor
384
+ price: *soda_price
385
+
386
+
387
+ # Key style
388
+ /aliases:
389
+ soda_flavor: &soda_flavor
390
+ sweet
391
+ soda_price: &soda_price
392
+ 1.0
393
+
394
+ coke:
395
+ id: 1
396
+ name: Coke
397
+ flavor: *soda_flavor
398
+ price: *soda_price
399
+
400
+ class Soda < ActiveYaml::Base
401
+ include ActiveYaml::Aliases
402
+ end
403
+
404
+ Soda.length # => 1
405
+ Soda.first.flavor # => sweet
406
+ Soda.first.price # => 1.0
407
+ ```
408
408
  ## ActiveJSON
409
409
 
410
410
  If you want to store your data in JSON files, just inherit from ActiveJSON and specify your path information:
411
-
412
- class Country < ActiveJSON::Base
413
- end
414
-
411
+ ```ruby
412
+ class Country < ActiveJSON::Base
413
+ end
414
+ ```
415
415
  By default, this class will look for a json file named "countries.json" in the same directory as the file. You can either change the directory it looks in, the filename it looks for, or both:
416
-
417
- class Country < ActiveJSON::Base
418
- set_root_path "/u/data"
419
- set_filename "sample"
420
- end
421
-
416
+ ```ruby
417
+ class Country < ActiveJSON::Base
418
+ set_root_path "/u/data"
419
+ set_filename "sample"
420
+ end
421
+ ```
422
422
  The above example will look for the file "/u/data/sample.json".
423
423
 
424
424
  Since ActiveJSON just creates a hash from the JSON file, you will have all fields specified in JSON auto-defined for you. You can format your JSON as an array, or as a hash:
425
-
426
- # array style
427
- [
428
- {
429
- "id": 1,
430
- "name": "US",
431
- "custom_field_1": "value1"
432
- },
433
- {
434
- "id": 2,
435
- "name": "Canada",
436
- "custom_field_2": "value2"
437
- }
438
- ]
439
-
440
- # hash style
441
- {
442
- { "us":
443
- {
444
- "id": 1,
445
- "name": "US",
446
- "custom_field_1": "value1"
447
- }
448
- },
449
- { "canada":
450
- {
451
- "id": 2,
452
- "name": "Canada",
453
- "custom_field_2": "value2"
454
- }
455
- }
425
+ ```ruby
426
+ # array style
427
+ [
428
+ {
429
+ "id": 1,
430
+ "name": "US",
431
+ "custom_field_1": "value1"
432
+ },
433
+ {
434
+ "id": 2,
435
+ "name": "Canada",
436
+ "custom_field_2": "value2"
437
+ }
438
+ ]
439
+
440
+ # hash style
441
+ {
442
+ { "us":
443
+ {
444
+ "id": 1,
445
+ "name": "US",
446
+ "custom_field_1": "value1"
456
447
  }
457
-
448
+ },
449
+ { "canada":
450
+ {
451
+ "id": 2,
452
+ "name": "Canada",
453
+ "custom_field_2": "value2"
454
+ }
455
+ }
456
+ }
457
+ ```
458
458
  ### Multiple files per model
459
459
 
460
460
  This works as it does for `ActiveYaml`
@@ -462,29 +462,29 @@ Since ActiveJSON just creates a hash from the JSON file, you will have all field
462
462
  ## ActiveFile
463
463
 
464
464
  If you store encrypted data, or you'd like to store your flat files as CSV or XML or any other format, you can easily include ActiveHash to parse and load your file. Just add a custom ::load_file method, and define the extension you want the file to use:
465
+ ```ruby
466
+ class Country < ActiveFile::Base
467
+ set_root_path "/u/data"
468
+ set_filename "sample"
465
469
 
466
- class Country < ActiveFile::Base
467
- set_root_path "/u/data"
468
- set_filename "sample"
469
-
470
- class << self
471
- def extension
472
- ".super_secret"
473
- end
474
-
475
- def load_file
476
- MyAwesomeDecoder.load_file(full_path)
477
- end
478
- end
470
+ class << self
471
+ def extension
472
+ ".super_secret"
479
473
  end
480
474
 
475
+ def load_file
476
+ MyAwesomeDecoder.load_file(full_path)
477
+ end
478
+ end
479
+ end
480
+ ```
481
481
  The two methods you need to implement are load_file, which needs to return an array of hashes, and .extension, which returns the file extension you are using. You have full_path available to you if you wish, or you can provide your own path.
482
482
 
483
483
  Setting the default file location in Rails:
484
-
485
- # config/initializers/active_file.rb
486
- ActiveFile::Base.set_root_path "config/activefiles"
487
-
484
+ ```ruby
485
+ # config/initializers/active_file.rb
486
+ ActiveFile::Base.set_root_path "config/activefiles"
487
+ ```
488
488
  In Rails, in development mode, it reloads the entire class, which reloads the file. In production, the data cached in memory.
489
489
 
490
490
  NOTE: By default, .full_path refers to the current working directory. In a rails app, this will be RAILS_ROOT.
@@ -494,17 +494,17 @@ NOTE: By default, .full_path refers to the current working directory. In a rai
494
494
  ActiveHash can expose its data in an Enumeration by setting constants for each record. This allows records to be accessed in code through a constant set in the ActiveHash class.
495
495
 
496
496
  The field to be used as the constant is set using _enum_accessor_ which takes the name of a field as an argument.
497
-
498
- class Country < ActiveHash::Base
499
- include ActiveHash::Enum
500
- self.data = [
501
- {:id => 1, :name => "US", :capital => "Washington, DC"},
502
- {:id => 2, :name => "Canada", :capital => "Ottawa"},
503
- {:id => 3, :name => "Mexico", :capital => "Mexico City"}
504
- ]
505
- enum_accessor :name
506
- end
507
-
497
+ ```ruby
498
+ class Country < ActiveHash::Base
499
+ include ActiveHash::Enum
500
+ self.data = [
501
+ {:id => 1, :name => "US", :capital => "Washington, DC"},
502
+ {:id => 2, :name => "Canada", :capital => "Ottawa"},
503
+ {:id => 3, :name => "Mexico", :capital => "Mexico City"}
504
+ ]
505
+ enum_accessor :name
506
+ end
507
+ ```
508
508
  Records can be accessed by looking up the field constant:
509
509
 
510
510
  >> Country::US.capital
@@ -515,19 +515,19 @@ Records can be accessed by looking up the field constant:
515
515
  => #<Country:0x10229fb28 @attributes={:name=>"Canada", :id=>2}
516
516
 
517
517
  You may also use multiple attributes to generate the constant, like so:
518
-
519
- class Town < ActiveHash::Base
520
- include ActiveHash::Enum
521
- self.data = [
522
- {:id => 1, :name => "Columbus", :state => "NY"},
523
- {:id => 2, :name => "Columbus", :state => "OH"}
524
- ]
525
- enum_accessor :name, :state
526
- end
527
-
528
- >> Town::COLUMBUS_NY
529
- >> Town::COLUMBUS_OH
530
-
518
+ ```ruby
519
+ class Town < ActiveHash::Base
520
+ include ActiveHash::Enum
521
+ self.data = [
522
+ {:id => 1, :name => "Columbus", :state => "NY"},
523
+ {:id => 2, :name => "Columbus", :state => "OH"}
524
+ ]
525
+ enum_accessor :name, :state
526
+ end
527
+
528
+ >> Town::COLUMBUS_NY
529
+ >> Town::COLUMBUS_OH
530
+ ```
531
531
  Constants are formed by first stripping all non-word characters and then upcasing the result. This means strings like "Blazing Saddles", "ReBar", "Mike & Ike" and "Ho! Ho! Ho!" become BLAZING_SADDLES, REBAR, MIKE_IKE and HO_HO_HO.
532
532
 
533
533
  The field specified as the _enum_accessor_ must contain unique data values.
@@ -15,9 +15,9 @@ module ActiveHash
15
15
  class Base
16
16
 
17
17
  if respond_to?(:class_attribute)
18
- class_attribute :_data, :dirty
18
+ class_attribute :_data, :dirty, :default_attributes
19
19
  else
20
- class_inheritable_accessor :_data, :dirty
20
+ class_inheritable_accessor :_data, :dirty, :default_attributes
21
21
  end
22
22
 
23
23
  if Object.const_defined?(:ActiveModel)
@@ -35,7 +35,7 @@ module ActiveHash
35
35
  if Object.const_defined?(:ActiveModel)
36
36
  model_name.cache_key
37
37
  else
38
- ActiveSupport::Inflector.tableize(self)
38
+ ActiveSupport::Inflector.tableize(self).downcase
39
39
  end
40
40
  end
41
41
 
@@ -61,6 +61,10 @@ module ActiveHash
61
61
  true
62
62
  end
63
63
 
64
+ def empty?
65
+ false
66
+ end
67
+
64
68
  def data
65
69
  _data
66
70
  end
@@ -157,6 +161,10 @@ module ActiveHash
157
161
  end
158
162
  end
159
163
 
164
+ def find_by(options)
165
+ where(options).first
166
+ end
167
+
160
168
  def count
161
169
  all.length
162
170
  end
@@ -210,6 +218,7 @@ module ActiveHash
210
218
  validate_field(field_name)
211
219
  field_names << field_name
212
220
 
221
+ add_default_value(field_name, options[:default]) if options[:default]
213
222
  define_getter_method(field_name, options[:default])
214
223
  define_setter_method(field_name)
215
224
  define_interrogator_method(field_name)
@@ -266,6 +275,11 @@ module ActiveHash
266
275
 
267
276
  private :configuration_for_custom_finder
268
277
 
278
+ def add_default_value field_name, default_value
279
+ self.default_attributes ||= {}
280
+ self.default_attributes[field_name] = default_value
281
+ end
282
+
269
283
  def define_getter_method(field, default_value)
270
284
  unless has_instance_method?(field)
271
285
  define_method(field) do
@@ -385,8 +399,6 @@ module ActiveHash
385
399
 
386
400
  end
387
401
 
388
- attr_reader :attributes
389
-
390
402
  def initialize(attributes = {})
391
403
  attributes.symbolize_keys!
392
404
  @attributes = attributes
@@ -395,10 +407,22 @@ module ActiveHash
395
407
  end
396
408
  end
397
409
 
410
+ def attributes
411
+ if self.class.default_attributes
412
+ self.class.default_attributes.merge @attributes
413
+ else
414
+ @attributes
415
+ end
416
+ end
417
+
398
418
  def [](key)
399
419
  attributes[key]
400
420
  end
401
421
 
422
+ def _read_attribute(key)
423
+ attributes[key]
424
+ end
425
+
402
426
  def []=(key, val)
403
427
  attributes[key] = val
404
428
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveHash
2
2
  module Gem
3
- VERSION = "1.4.0"
3
+ VERSION = "1.4.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_hash
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dean
@@ -28,7 +28,7 @@ authors:
28
28
  autorequire:
29
29
  bindir: bin
30
30
  cert_chain: []
31
- date: 2014-09-04 00:00:00.000000000 Z
31
+ date: 2015-09-13 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  version: '0'
87
87
  requirements: []
88
88
  rubyforge_project:
89
- rubygems_version: 2.2.2
89
+ rubygems_version: 2.4.8
90
90
  signing_key:
91
91
  specification_version: 4
92
92
  summary: An ActiveRecord-like model that uses a hash or file as a datasource