active_cabinet 0.1.1 → 0.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9adb36f6d291c160a960599e7de79f3f9d08afb3f1536364dfc57c103d81254f
4
- data.tar.gz: 5a4bfd4907203cb963f1b7102b14701dcfbcefe44fb8dc2e7f0d4ab87af2f03b
3
+ metadata.gz: 8dd6fedc3ca5771467baee667ae128cf77f2042394e28169057c3707205391fc
4
+ data.tar.gz: c89be55b4d4d6d4bbebe6a6044fd24145027454716c4118da2b8c57e75acca9e
5
5
  SHA512:
6
- metadata.gz: b4df4f37043c8285d3333e21161d4a681f375a8a80e63a57f1c0f797bbd6669617e95d4ccdee653aac9ed7bd488dfe4f10ebe00477c147f0c47c4185415e7a42
7
- data.tar.gz: f76c0f806f6aa0d14c392243cea42585ef108daf8a059659344893a21eee7044d0420bc39045eb39c20effe6ebccdfde9d59b664a5393209598837fa08c7eb45
6
+ metadata.gz: 5cdcf93a07fc0ff445812239c21f5602eb10ce014a242359351bc1d5bb5109964ebaf6a9975891ea090a5efa639c516d14c078ea24c44920664d444308be1f2b
7
+ data.tar.gz: 2bc8d3fcac688ea0b0625ea28787b3f7d39222e943ae5f0aa1e4887e40fa8899b079fe743536280488313fcdf5c19d961c05ebb8bd6bf0d163ae643174cebc58
data/README.md CHANGED
@@ -8,7 +8,7 @@ ActiveCabinet
8
8
  ---
9
9
 
10
10
  An ActiveRecord-inspired interface for [HashCabinet], the
11
- file-basd key-object store.
11
+ file-based key-object store.
12
12
 
13
13
  It allows you to create models that are stored in a file-based key-value
14
14
  store, backed by Ruby's built in [SDBM].
@@ -67,8 +67,8 @@ song.update! year: 1988, artist: 'Metallica' # this variant also saves
67
67
 
68
68
  ### Restricting / allowing certain attributes
69
69
 
70
- You may specify required arguments. Records without these attributes will
71
- not be saved. Note that `id` is always required
70
+ You may specify required attributes. Records without these attributes will
71
+ not be saved. Note that `id` is always required.
72
72
 
73
73
  ```ruby
74
74
  class Song < ActiveCabinet
@@ -114,15 +114,31 @@ song.valid? # => false
114
114
  song.error # => "invalid attributes: [:artist]"
115
115
  ```
116
116
 
117
+ ### Declaring default attribute values
118
+
119
+ You may specify default values for some attributes. These attrributes will
120
+ be merged into newly created record instances.
121
+
122
+ ```ruby
123
+ class Song < ActiveCabinet
124
+ required_attributes :title
125
+ default_attributes format: :mp3
126
+ end
127
+
128
+ song = Song.new title: "Moonchild"
129
+ song.format # => :mp3
130
+ ```
131
+
132
+
117
133
  ### Configuring storage path
118
134
 
119
135
  By default, `ActiveCabinet` stores all its files (two files per model) in the
120
136
  `./db` directory. The file name is determined by the name of the class.
121
137
 
122
- You can override both of these values
138
+ You can override both of these values:
123
139
 
124
140
  ```ruby
125
- # Set the based directory for all cabinets
141
+ # Set the base directory for all cabinets
126
142
  ActiveCabinet::Config.dir = "cabinets"
127
143
 
128
144
  # Set the filename of your model
@@ -14,7 +14,7 @@ class ActiveCabinet
14
14
  #
15
15
  # @param [Hash] attributes record attributes
16
16
  def initialize(attributes = {})
17
- @attributes = attributes.transform_keys(&:to_sym)
17
+ @attributes = default_attributes.merge attributes.transform_keys(&:to_sym)
18
18
  end
19
19
 
20
20
  # @!group Attribute Management
@@ -42,6 +42,10 @@ class ActiveCabinet
42
42
  self.class.optional_attributes
43
43
  end
44
44
 
45
+ def default_attributes
46
+ self.class.default_attributes
47
+ end
48
+
45
49
  # Returns +true+ if the object is valid.
46
50
  #
47
51
  # @return [Boolean] +true+ if the record is valid.
@@ -63,6 +67,23 @@ class ActiveCabinet
63
67
  true
64
68
  end
65
69
 
70
+ # @!group Attribute Accessors
71
+
72
+ # Returns the attribute value for the given key.
73
+ #
74
+ # @return [Object] the attribute value.
75
+ def [](key)
76
+ attributes[key]
77
+ end
78
+
79
+ # Sets the attribute value for the given key.
80
+ #
81
+ # @param [Symbol] key the attribute key.
82
+ # @param [Object] value the attribute value.
83
+ def []=(key, value)
84
+ attributes[key] = value
85
+ end
86
+
66
87
  # @!group Dynamic Attribute Accessors
67
88
 
68
89
  # Provides read/write access to {attributes}
@@ -138,7 +159,7 @@ class ActiveCabinet
138
159
  #
139
160
  # @param [Hash] new_attributes record attributes
140
161
  def update(new_attributes)
141
- @attributes = attributes.merge new_attributes
162
+ @attributes = attributes.merge(new_attributes.transform_keys &:to_sym)
142
163
  end
143
164
 
144
165
  # Update the record with new or modified attributes, and save.
@@ -69,24 +69,82 @@ class ActiveCabinet
69
69
  end
70
70
 
71
71
  # Returns an array of records for which the block returns true.
72
+ # When +query+ is provided, it should be a Hash with a single key and
73
+ # value. The result will be records that have a matching attribute.
74
+ #
75
+ # @example Search using a Hash query
76
+ # Song.where artist: "Iron Maiden"
77
+ #
78
+ # @example Search using a block
79
+ # Song.where { |record| record[:artist] == "Iron Maiden" }
72
80
  #
73
81
  # @yieldparam [Object] record all record instances.
74
- def where
75
- all.select { |record| yield record }
82
+ # @return [Array<Object>] record all record instances.
83
+ def where(query = nil)
84
+ if query
85
+ key, value = query.first
86
+ all.select { |record| record[key] == value }
87
+ else
88
+ all.select { |record| yield record }
89
+ end
76
90
  end
77
91
 
78
92
  # Returns the record matching the +id+.
93
+ # When providing a Hash with a single key-value pair, it will return the
94
+ # first matching object from the respective {where} query.
95
+ #
96
+ # @example Retrieve a record by ID
97
+ # Song.find 1
98
+ # Song[1]
99
+ #
100
+ # @example Retrieve a different attributes
101
+ # Song.find artist: "Iron Maiden"
102
+ # Song[artist: "Iron Maiden"]
79
103
  #
80
104
  # @return [Object, nil] the object if found, or +nil+.
81
105
  def find(id)
82
- attributes = cabinet[id]
83
- attributes ? new(attributes) : nil
106
+ if id.is_a? Hash
107
+ where(id).first
108
+ else
109
+ attributes = cabinet[id]
110
+ attributes ? new(attributes) : nil
111
+ end
84
112
  end
85
113
  alias [] find
86
114
 
115
+ # Yields each record to the given block.
116
+ #
117
+ # @yieldparam [Object] record all record instances.
118
+ def each
119
+ cabinet.each_value do |attributes|
120
+ yield new(attributes)
121
+ end
122
+ end
123
+
124
+ # Returns the first record.
125
+ #
126
+ # @return [Object] the record.
127
+ def first
128
+ find keys.first
129
+ end
130
+
131
+ # Returns the last record.
132
+ #
133
+ # @return [Object] the record.
134
+ def last
135
+ find keys.last
136
+ end
137
+
138
+ # Returns a random racord.
139
+ #
140
+ # @return [Object] the record.
141
+ def random
142
+ find keys.sample
143
+ end
144
+
87
145
  # @!group Deleting Records
88
146
 
89
- # Deletes a record matching the +id+
147
+ # Deletes a record matching the +id+.
90
148
  #
91
149
  # @param [String] id the record ID.
92
150
  # @return [Boolean] +true+ on success, +false+ otherwise.
@@ -94,6 +152,14 @@ class ActiveCabinet
94
152
  !!cabinet.delete(id)
95
153
  end
96
154
 
155
+ # Deletes a record for which the block returns true.
156
+ #
157
+ # @example Delete records using a block
158
+ # Song.delete_if { |record| record[:artist] == "Iron Maiden" }
159
+ def delete_if
160
+ cabinet.delete_if { |key, _value| yield self[key] }
161
+ end
162
+
97
163
  # Deletes all records.
98
164
  def drop
99
165
  cabinet.clear
@@ -101,11 +167,13 @@ class ActiveCabinet
101
167
 
102
168
  # @!group Attribute Management
103
169
 
104
- # Returns an array containing {required_attributes} and {optional_attributes}.
170
+ # Returns an array containing the keys of all allowed attributes as
171
+ # defined by {required_attributes}, {optional_attributes} and
172
+ # {default_attributes}.
105
173
  #
106
174
  # @return [Array<Symbol>] array of required attribute keys.
107
175
  def allowed_attributes
108
- (optional_attributes || []) + required_attributes
176
+ (optional_attributes || []) + required_attributes + default_attributes.keys
109
177
  end
110
178
 
111
179
  # Sets the required record attribute names.
@@ -138,6 +206,18 @@ class ActiveCabinet
138
206
  end
139
207
  end
140
208
 
209
+ # Sets the default record attribute values.
210
+ #
211
+ # @param [Hash<Symbol, Object>] **attributes one or more attribute names and values.
212
+ # @return [Hash<Symbol, Object>] the hash of the default attributes.
213
+ def default_attributes(args = nil)
214
+ if args
215
+ @default_attributes = args
216
+ else
217
+ @default_attributes ||= {}
218
+ end
219
+ end
220
+
141
221
  # @!group Utilities
142
222
 
143
223
  # Returns all records as a hash, with record IDs as the keys.
@@ -1,3 +1,3 @@
1
1
  class ActiveCabinet
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_cabinet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-08 00:00:00.000000000 Z
11
+ date: 2021-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hash_cabinet
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.1.3
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
29
  version: '0.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.1.3
27
33
  description: ActiveRecord-inspired interface for HashCabinet, the file-basd key-object
28
34
  store.
29
35
  email: db@dannyben.com
@@ -58,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
64
  - !ruby/object:Gem::Version
59
65
  version: '0'
60
66
  requirements: []
61
- rubygems_version: 3.1.2
67
+ rubygems_version: 3.2.3
62
68
  signing_key:
63
69
  specification_version: 4
64
70
  summary: Database-like interface for HashCabinet