fixed_record 0.1.2 → 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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +70 -14
- data/lib/fixed_record.rb +74 -21
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0eea6e2937878d931df67a139cff38882002163f62f43e9f6b4e9440c84bbc60
|
4
|
+
data.tar.gz: 8d51b0834f97783271b77fd8762289efad419c463aa3a6f705affded0a07de2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39687e91690bd8426119d2c41b77298dc3a48c2da4000a57bc6160f14ea2eb021d4495eac2ca27d50189fa5fcedbb2196c4c543bda44ff936aba2cf27d4f9b42
|
7
|
+
data.tar.gz: '0697f532ce75a0e808fefe5a94a9fa42b9fa00e346c7e6dda1288066aab857ab36d196a57473134d04d66ad4aa0b4b91a4db57a8197284a5c49ff9cfaf18b432'
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -4,13 +4,11 @@ FixedRecord provides ActiveRecord-like read-only access to a set of records
|
|
4
4
|
described in a YAML file.
|
5
5
|
|
6
6
|
Why is this useful? Occasionally you have tabular data which hardly ever
|
7
|
-
changes and can easily be edited by hand. Although this
|
8
|
-
|
9
|
-
It's quicker and simpler to implement this as an array of objects in a YAML file.
|
10
|
-
|
11
|
-
See the Usage section below
|
7
|
+
changes and can easily be edited by hand. Although this data could be placed in a database, it may not be worth the overhead involved (loading a database, maintaining database code, etc.).
|
12
8
|
|
9
|
+
It may be quicker and simpler to implement this as an array or hash of objects in a YAML file, and use this gem to provide access to the data.
|
13
10
|
|
11
|
+
See the Usage section below.
|
14
12
|
|
15
13
|
## Installation
|
16
14
|
|
@@ -30,6 +28,8 @@ Or install it yourself as:
|
|
30
28
|
|
31
29
|
## Usage
|
32
30
|
|
31
|
+
### Array of Records
|
32
|
+
|
33
33
|
Create a YAML file defining an array of records like this:
|
34
34
|
|
35
35
|
```yaml
|
@@ -45,7 +45,7 @@ Create a YAML file defining an array of records like this:
|
|
45
45
|
Then to load these, create a class
|
46
46
|
|
47
47
|
```ruby
|
48
|
-
require '
|
48
|
+
require 'fixed_record'
|
49
49
|
|
50
50
|
class MyFavoriteWebsite < FixedRecord
|
51
51
|
data "#{Rails.root}/data/my_favorite_websites.yml"
|
@@ -68,19 +68,78 @@ end
|
|
68
68
|
Or can be accessed as an array:
|
69
69
|
|
70
70
|
```ruby
|
71
|
-
|
71
|
+
MyFavoriteWebsite.all.is_a?(Array) # true
|
72
|
+
```
|
73
|
+
A count of the number of records is available:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
puts MyFavoriteWebsite.count
|
77
|
+
```
|
78
|
+
|
79
|
+
The declared class will also include all the methods from the `Enumerable` module.
|
80
|
+
|
81
|
+
### Hash of Records
|
82
|
+
|
83
|
+
Create a YAML file `my_web_pages.yml` defining a hash of records like this:
|
84
|
+
|
85
|
+
```yaml
|
86
|
+
StaticPage#first:
|
87
|
+
title: First Page
|
88
|
+
description: Welcome to the First Page
|
89
|
+
|
90
|
+
StaticPage#last:
|
91
|
+
title: Last Page
|
92
|
+
description: Welcome to the Last Page
|
93
|
+
|
94
|
+
```
|
95
|
+
|
96
|
+
Then to load these, create a class
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
require 'fixed_record'
|
100
|
+
|
101
|
+
class MyWebPages < FixedRecord
|
102
|
+
data "#{Rails.root}/data/my_web_pages.yml"
|
103
|
+
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
The collection can be accessed by index:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
MyWebPages['StaticPage#first'].title # First Page
|
111
|
+
MyWebPages['StaticPage#last'].description # Welcome to he Last page
|
112
|
+
MyWebPages['StaticPage#first'].key # StaticPage#fifst
|
113
|
+
```
|
114
|
+
|
115
|
+
The collection can then be enumerated as required:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
MyWebPages.each do |k,v|
|
119
|
+
puts k
|
120
|
+
puts v.title
|
121
|
+
end
|
122
|
+
```
|
123
|
+
Or can be accessed as an hash:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
MyWebPages.all.is_a?(Hash) # true
|
72
127
|
```
|
73
128
|
A count of the number of records is available:
|
74
129
|
|
75
130
|
```ruby
|
76
|
-
puts
|
131
|
+
puts MyWebPages.count
|
77
132
|
```
|
78
133
|
|
79
|
-
The class also
|
134
|
+
The declared class will also include all the methods from the `Enumerable` module.
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
## Error Checking
|
80
139
|
|
81
140
|
Some basic sanity checks are performed on the YAML file to catch common errors:
|
82
141
|
|
83
|
-
* It must define a non-empty array of records
|
142
|
+
* It must define a non-empty array or hash of records
|
84
143
|
* All records must have the same set of attributes
|
85
144
|
|
86
145
|
An `ArgumentError` exception will be thrown if any errors are detected.
|
@@ -89,9 +148,6 @@ Additional validations can be performed by overriding the `validate_yaml` and
|
|
89
148
|
`validate_item` class functions.
|
90
149
|
|
91
150
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
151
|
## Development
|
96
152
|
|
97
153
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -100,4 +156,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
100
156
|
|
101
157
|
## Contributing
|
102
158
|
|
103
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
159
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/m-z-b/fixed_record.
|
data/lib/fixed_record.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'yaml'
|
3
3
|
|
4
4
|
class FixedRecord
|
5
|
-
VERSION = "0.
|
5
|
+
VERSION = "0.2.0"
|
6
6
|
|
7
7
|
# Lazy load data from given filename
|
8
8
|
# creating accessors for top level attributes
|
@@ -28,43 +28,96 @@ class FixedRecord
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.count
|
31
|
-
all.
|
31
|
+
all.length
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.[]( k )
|
35
|
+
if all.is_a?(Hash)
|
36
|
+
all[k]
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.has_key?( k )
|
43
|
+
if all.is_a?(Hash)
|
44
|
+
all.has_key?( k )
|
45
|
+
else
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
34
50
|
def self.load!
|
35
51
|
if @@items.nil?
|
36
52
|
y = YAML.load_file( filename )
|
37
53
|
validate_yaml( y )
|
38
|
-
valid_keys =
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
54
|
+
valid_keys = nil
|
55
|
+
if y.is_a?(Array)
|
56
|
+
valid_keys = y.first.keys
|
57
|
+
@@items = y.map.with_index do |values,i|
|
58
|
+
validate_item( valid_keys, values, i )
|
59
|
+
r = new
|
60
|
+
r.instance_variable_set( :@values, values )
|
61
|
+
r
|
62
|
+
end
|
63
|
+
elsif y.is_a?(Hash)
|
64
|
+
@@items = Hash.new
|
65
|
+
add_key = true
|
66
|
+
y.each do |k,values|
|
67
|
+
if valid_keys.nil?
|
68
|
+
valid_keys = values.keys
|
69
|
+
add_key = !values.has_key?('key')
|
70
|
+
end
|
71
|
+
validate_item( valid_keys, values, k )
|
72
|
+
values['key'] = k if add_key
|
73
|
+
r = new
|
74
|
+
r.instance_variable_set( :@values, values )
|
75
|
+
@@items[k] = r
|
76
|
+
end
|
77
|
+
valid_keys << 'key' if add_key
|
48
78
|
end
|
79
|
+
create_methods( valid_keys )
|
49
80
|
end
|
50
81
|
end
|
51
82
|
}
|
52
83
|
end
|
53
84
|
|
85
|
+
# Create access methods for each of valid_keys
|
86
|
+
def self.create_methods( valid_keys )
|
87
|
+
valid_keys.each do |k|
|
88
|
+
define_method( k.to_sym) { @values[k] }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
54
92
|
# Validate the top level of the data structure returned
|
55
93
|
def self.validate_yaml( y )
|
56
|
-
|
57
|
-
|
94
|
+
if y.is_a?(Array)
|
95
|
+
if y.length <= 0
|
96
|
+
throw ArgumentError.new "#{filename} contain a zero length array"
|
97
|
+
end
|
98
|
+
if y.any?{ |i| !i.is_a?(Hash)}
|
99
|
+
throw ArgumentError.new "#{filename} does not contain an array of items (hashes)"
|
100
|
+
end
|
101
|
+
elsif y.is_a?(Hash)
|
102
|
+
if y.count <= 0
|
103
|
+
throw ArgumentError.new "#{filename} contain an empty hash"
|
104
|
+
end
|
105
|
+
if y.any?{ |k,v| !v.is_a?(Hash) }
|
106
|
+
throw ArgumentError.new "#{filename} does not contain an array of items (hashes)"
|
107
|
+
end
|
108
|
+
else
|
109
|
+
throw ArgumentError.new "#{filename} does not contain a hash of items or an array of items"
|
58
110
|
end
|
111
|
+
|
59
112
|
end
|
60
113
|
|
61
|
-
# Validate a
|
62
|
-
def self.validate_item(
|
63
|
-
raise ArgumentError, "#{filename} item #{index
|
64
|
-
raise ArgumentError, "#{filename} item #{index
|
65
|
-
|
66
|
-
unless
|
67
|
-
raise ArgumentError, "#{filename} item #{index
|
114
|
+
# Validate a values of name -> value
|
115
|
+
def self.validate_item( valid_keys, values, index )
|
116
|
+
raise ArgumentError, "#{filename} item #{index} should be name value pairs" unless values.is_a?(Hash)
|
117
|
+
raise ArgumentError, "#{filename} item #{index} has wrong number of values" if valid_keys.length != values.length
|
118
|
+
valid_keys.each do |name|
|
119
|
+
unless values.has_key? name
|
120
|
+
raise ArgumentError, "#{filename} item #{index} is missing value for '#{name}'"
|
68
121
|
end
|
69
122
|
end
|
70
123
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fixed_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Bell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -91,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '0'
|
93
93
|
requirements: []
|
94
|
-
rubygems_version: 3.
|
94
|
+
rubygems_version: 3.1.2
|
95
95
|
signing_key:
|
96
96
|
specification_version: 4
|
97
97
|
summary: Provide ActiveRecord like read-only access to a small dataset stored in a
|