csv_record 2.1.2 → 3.0.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 +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -1
- data/README.md +51 -39
- data/Rakefile +1 -1
- data/csv_record.gemspec +8 -6
- data/lib/csv_record.rb +0 -23
- data/lib/csv_record/associations.rb +1 -1
- data/lib/csv_record/callback.rb +4 -2
- data/lib/csv_record/callbacks.rb +21 -19
- data/lib/csv_record/{csv_queries/condition.rb → condition.rb} +4 -2
- data/lib/csv_record/connector.rb +9 -7
- data/lib/csv_record/csv_validations/custom_validation.rb +8 -5
- data/lib/csv_record/csv_validations/presence_validation.rb +6 -4
- data/lib/csv_record/csv_validations/uniqueness_validation.rb +8 -5
- data/lib/csv_record/csv_validations/validations.rb +23 -28
- data/lib/csv_record/document.rb +12 -12
- data/lib/csv_record/field.rb +6 -4
- data/lib/csv_record/fields.rb +45 -0
- data/lib/csv_record/helpers.rb +10 -6
- data/lib/csv_record/{csv_queries/query.rb → query.rb} +8 -15
- data/lib/csv_record/reader.rb +120 -0
- data/lib/csv_record/timestamps.rb +4 -2
- data/lib/csv_record/version.rb +3 -3
- data/lib/csv_record/writer.rb +143 -0
- data/test/csv_record/associations_test.rb +1 -1
- data/test/csv_record/connector_test.rb +3 -3
- data/test/csv_record/reader_test.rb +6 -6
- data/test/csv_record/validation_test.rb +1 -1
- data/test/models/callback_test_class.rb +1 -2
- data/test/models/custom_errors_class.rb +2 -1
- data/test/models/customized_class.rb +1 -1
- data/test/models/jedi.rb +4 -3
- data/test/models/jedi_order.rb +2 -2
- data/test/models/padawan.rb +1 -1
- data/test/test_helper.rb +3 -3
- data/test/{helpers.rb → test_helpers.rb} +2 -2
- metadata +80 -52
- data/lib/csv_record/csv_fields.rb +0 -45
- data/lib/csv_record/csv_readers/class_reader.rb +0 -82
- data/lib/csv_record/csv_readers/instance_reader.rb +0 -29
- data/lib/csv_record/csv_readers/reader.rb +0 -9
- data/lib/csv_record/csv_writers/class_writer.rb +0 -52
- data/lib/csv_record/csv_writers/instance_writer.rb +0 -86
- data/lib/csv_record/csv_writers/writer.rb +0 -9
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b56ddc51a9bc473b810efc0342ede311cf20fc01
|
4
|
+
data.tar.gz: 26a034a21daf07b878aa68ace0668ca689a567e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1f849ebfc371659527501acc487df4c0a78d001edb8deb5027c242369bce46aef9cbfd0f7c94265fa8070972d99678204a8243adf59c876545d68032f652acac
|
7
|
+
data.tar.gz: 6a934c1164d1ea2605bc4884b82efbe355b210cbb434d772c1a825a2c0a69e9f1873f91f34dd386af94cef2191867bb18bb350d16861f1b8aa9baae8b31e8ecc
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
csv_record
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.4.2
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# CsvRecord
|
2
2
|
|
3
|
-
[](https://travis-ci.org/lukelex/csv_record)
|
3
|
+
[](https://travis-ci.org/lukelex/csv_record)
|
4
|
+
[](https://codeclimate.com/github/lukelex/csv_record)
|
5
|
+
[](http://badge.fury.io/rb/csv_record)
|
4
6
|
|
5
|
-
CSV Record connects Ruby classes to CSV documents
|
7
|
+
CSV Record connects Ruby classes to CSV documents in order to
|
8
|
+
establish an almost zero-configuration persistence layer for
|
9
|
+
applications.
|
6
10
|
|
7
|
-
##Getting Started
|
11
|
+
## Getting Started
|
8
12
|
|
9
13
|
Add this line to your application's Gemfile:
|
10
14
|
|
@@ -24,7 +28,8 @@ Or install it yourself as:
|
|
24
28
|
$ gem install csv_record
|
25
29
|
```
|
26
30
|
|
27
|
-
And inside your Ruby models just require and include the CSVRecord
|
31
|
+
And inside your Ruby models just require and include the CSVRecord
|
32
|
+
lib and start using it in the same way as your are used to:
|
28
33
|
|
29
34
|
```ruby
|
30
35
|
require 'csv_record'
|
@@ -36,27 +41,28 @@ class Jedi
|
|
36
41
|
end
|
37
42
|
```
|
38
43
|
|
39
|
-
##
|
40
|
-
To persist the data objects created in your application
|
44
|
+
## Persistence
|
45
|
+
To persist the data objects created in your application you can
|
46
|
+
use the following methods:
|
41
47
|
|
42
48
|
```ruby
|
43
|
-
Jedi.create( # save the new record in
|
49
|
+
Jedi.create( # save the new record in its CSV file
|
44
50
|
name: 'Luke Skywalker',
|
45
51
|
age: 18,
|
46
52
|
midi_chlorians: '12k'
|
47
53
|
)
|
48
54
|
|
49
|
-
jedi.save # save the record in
|
55
|
+
jedi.save # save the record in its CSV file (either creating or changing)
|
50
56
|
|
51
57
|
jedi.update_attribute :age, 29 # update a single field of an object
|
52
58
|
jedi.update_attributes age: 29, midi_chlorians: '18k' # update multiple fields at the same time
|
53
59
|
|
54
|
-
jedi.destroy # removes the record from
|
60
|
+
jedi.destroy # removes the record from its CSV file
|
55
61
|
|
56
62
|
jedi.new_record? # checks if the record is new
|
57
63
|
```
|
58
64
|
|
59
|
-
##Querying
|
65
|
+
## Querying
|
60
66
|
Records can be queried through the following methods:
|
61
67
|
|
62
68
|
```ruby
|
@@ -70,10 +76,10 @@ Jedi.find_by_name_and_age 'Luke Skywalker', 18 # find dynamically with multiple
|
|
70
76
|
|
71
77
|
Jedi.where age: 18, name: 'Luke Skywalker', midi_chlorians: '12k' # find with a multiple parameters hash
|
72
78
|
|
73
|
-
Jedi.count # returns the amount of records in
|
79
|
+
Jedi.count # returns the amount of records in its CSV file
|
74
80
|
|
75
|
-
Jedi.first # retrieves the first record in
|
76
|
-
Jedi.last # retrieves the last record in
|
81
|
+
Jedi.first # retrieves the first record in its CSV file
|
82
|
+
Jedi.last # retrieves the last record in its CSV file
|
77
83
|
```
|
78
84
|
|
79
85
|
Lazy querying is the default behavior now Yey!!
|
@@ -85,8 +91,8 @@ query # #<CsvRecord::Query:0x007fdff3d31aa0>
|
|
85
91
|
query.first # #<Jedi:0x007f9df6cea478>
|
86
92
|
```
|
87
93
|
|
88
|
-
##Associations
|
89
|
-
###Belongs To
|
94
|
+
## Associations
|
95
|
+
### Belongs To
|
90
96
|
A Belongs To association can be declared through the following method:
|
91
97
|
|
92
98
|
```ruby
|
@@ -117,7 +123,7 @@ jedi.save
|
|
117
123
|
jedi.jedi_order # #<JediOrder:0x007f9b249b24d8>
|
118
124
|
```
|
119
125
|
|
120
|
-
###Has Many
|
126
|
+
### Has Many
|
121
127
|
Extending the previous example, you can use the `has_many` method to establish the inverse relationship:
|
122
128
|
|
123
129
|
```ruby
|
@@ -137,7 +143,7 @@ jedi.save
|
|
137
143
|
jedi_order.jedis # [#<Jedi:0x007f9b249b24d8>]
|
138
144
|
```
|
139
145
|
|
140
|
-
###Has One
|
146
|
+
### Has One
|
141
147
|
The same as has_many but limited to one associated record.
|
142
148
|
|
143
149
|
```ruby
|
@@ -164,11 +170,11 @@ jedi.padawan = padawan
|
|
164
170
|
jedi.padawan # #<Padawan:0x007f9b249b24d8>
|
165
171
|
```
|
166
172
|
|
167
|
-
##Callbacks
|
168
|
-
###Overview
|
173
|
+
## Callbacks
|
174
|
+
### Overview
|
169
175
|
Callbacks can be used to execute code on predetermined moments.
|
170
176
|
|
171
|
-
####Usage
|
177
|
+
#### Usage
|
172
178
|
```ruby
|
173
179
|
after_create do
|
174
180
|
# learn the way of the force
|
@@ -176,14 +182,14 @@ end
|
|
176
182
|
```
|
177
183
|
`self` refers to the instance you are in
|
178
184
|
|
179
|
-
###
|
185
|
+
### Available Callbacks
|
180
186
|
Here is a list with all the available callbacks, listed in the same order in which they will get called during the respective operations:
|
181
187
|
|
182
|
-
####Finding an Object
|
188
|
+
#### Finding an Object
|
183
189
|
* after_initialize
|
184
190
|
* after_find
|
185
191
|
|
186
|
-
####Creating an Object
|
192
|
+
#### Creating an Object
|
187
193
|
* after_initialize
|
188
194
|
* before_validation
|
189
195
|
* after_validation
|
@@ -192,7 +198,7 @@ Here is a list with all the available callbacks, listed in the same order in whi
|
|
192
198
|
* after_create
|
193
199
|
* after_save
|
194
200
|
|
195
|
-
####Updating an Object
|
201
|
+
#### Updating an Object
|
196
202
|
* before_validation
|
197
203
|
* after_validation
|
198
204
|
* before_save
|
@@ -200,16 +206,16 @@ Here is a list with all the available callbacks, listed in the same order in whi
|
|
200
206
|
* after_update
|
201
207
|
* after_save
|
202
208
|
|
203
|
-
####Destroying an Object
|
209
|
+
#### Destroying an Object
|
204
210
|
* before_destroy
|
205
211
|
* after_destroy
|
206
212
|
|
207
|
-
##Validations
|
208
|
-
###Helpers available:
|
213
|
+
## Validations
|
214
|
+
### Helpers available:
|
209
215
|
|
210
216
|
`validates_presence_of`: Ensures if the specified attribute(s) were filled
|
211
217
|
|
212
|
-
`validates_uniqueness_of`: Ensures that the specified attribute(s) are unique within
|
218
|
+
`validates_uniqueness_of`: Ensures that the specified attribute(s) are unique within its CSV file
|
213
219
|
|
214
220
|
`validate`: Uses custom method(s) to validate the model
|
215
221
|
|
@@ -240,30 +246,36 @@ jedi.invalid? # => true
|
|
240
246
|
jedi.save # => false
|
241
247
|
```
|
242
248
|
|
243
|
-
##Customizations
|
249
|
+
## Customizations
|
244
250
|
|
245
|
-
Someday you might want to go "out of the rail" that we propose.
|
251
|
+
Someday you might want to go "out of the rail" that we propose.
|
252
|
+
Here is what you can do now:
|
246
253
|
|
247
|
-
###Changing the table_name
|
254
|
+
### Changing the table_name
|
248
255
|
```ruby
|
249
256
|
store_as :wierd_table_name
|
250
257
|
```
|
251
|
-
###Changing the field column name
|
258
|
+
### Changing the field column name
|
252
259
|
```ruby
|
253
260
|
mapping :name => :wierd_field
|
254
261
|
```
|
255
262
|
|
256
|
-
##Bug reports
|
263
|
+
## Bug reports
|
257
264
|
|
258
|
-
If you discover a problem with CSV_Record, we would like to know
|
265
|
+
If you discover a problem with CSV_Record, we would like to know
|
266
|
+
about it. Please let us know on the project issues page.
|
259
267
|
|
260
|
-
##Contributing
|
268
|
+
## Contributing
|
261
269
|
|
262
|
-
We hope that you will consider contributing to CSV_Record. Please
|
270
|
+
We hope that you will consider contributing to CSV_Record. Please
|
271
|
+
read this short overview for some information about how to get started:
|
263
272
|
|
264
273
|
https://github.com/lukelex/csv_record/wiki/Contributing
|
265
274
|
|
266
|
-
You will usually want to write tests for your changes. To run the
|
275
|
+
You will usually want to write tests for your changes. To run the
|
276
|
+
test suite, go into CSV_Record's top-level directory and run
|
277
|
+
"bundle install" and "rake". For the tests to pass.
|
267
278
|
|
268
|
-
##Precautions
|
269
|
-
CsvRecord creates a `db` folder in the root of your application.
|
279
|
+
## Precautions
|
280
|
+
CsvRecord creates a `db` folder in the root of your application.
|
281
|
+
Be sure that it has permission to do so.
|
data/Rakefile
CHANGED
data/csv_record.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
require File.expand_path('../lib/csv_record/version', __FILE__)
|
3
2
|
|
4
3
|
Gem::Specification.new do |gem|
|
@@ -17,10 +16,13 @@ Gem::Specification.new do |gem|
|
|
17
16
|
gem.require_paths = ["lib"]
|
18
17
|
gem.version = CsvRecord::VERSION
|
19
18
|
|
20
|
-
gem.add_dependency 'activesupport', '~>
|
19
|
+
gem.add_dependency 'activesupport', '~> 0'
|
21
20
|
|
22
|
-
gem.add_development_dependency 'rake', '~> 0
|
23
|
-
gem.add_development_dependency 'timecop', '~> 0
|
24
|
-
gem.add_development_dependency 'turn', '~> 0
|
25
|
-
gem.add_development_dependency 'minitest', '~>
|
21
|
+
gem.add_development_dependency 'rake', '~> 0'
|
22
|
+
gem.add_development_dependency 'timecop', '~> 0'
|
23
|
+
gem.add_development_dependency 'turn', '~> 0'
|
24
|
+
gem.add_development_dependency 'minitest', '~> 0'
|
25
|
+
gem.add_development_dependency 'pry', '~> 0'
|
26
|
+
gem.add_development_dependency 'pry-nav', '~> 0'
|
27
|
+
gem.add_development_dependency 'm', '~> 0'
|
26
28
|
end
|
data/lib/csv_record.rb
CHANGED
@@ -1,26 +1,3 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2012 Lukas Alexandre
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
# a copy of this software and associated documentation files (the
|
6
|
-
# "Software"), to deal in the Software without restriction, including
|
7
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
# the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
#++
|
23
|
-
|
24
1
|
require 'csv'
|
25
2
|
|
26
3
|
require 'csv_record/version'
|
data/lib/csv_record/callback.rb
CHANGED
data/lib/csv_record/callbacks.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'callback'
|
2
4
|
|
3
5
|
module CsvRecord::Callbacks
|
4
6
|
CALLBACK_TYPES = [
|
@@ -22,7 +24,7 @@ module CsvRecord::Callbacks
|
|
22
24
|
const_variable = "#{callback_type}_callbacks".upcase
|
23
25
|
const_set(const_variable, []) unless const_defined? const_variable
|
24
26
|
if block
|
25
|
-
const_get(const_variable) <<
|
27
|
+
const_get(const_variable) << CsvRecord::Callback.new(callback_type, block)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -35,9 +37,9 @@ module CsvRecord::Callbacks
|
|
35
37
|
end
|
36
38
|
|
37
39
|
module InstanceMethods
|
38
|
-
CALLBACK_TYPES.each do |
|
39
|
-
define_method "run_#{
|
40
|
-
const_variable = "#{
|
40
|
+
CALLBACK_TYPES.each do |type|
|
41
|
+
define_method "run_#{type}_callbacks" do
|
42
|
+
const_variable = "#{type}_callbacks".upcase
|
41
43
|
if self.class.const_defined? const_variable
|
42
44
|
callbacks_collection = self.class.const_get const_variable
|
43
45
|
callbacks_collection.each do |callback|
|
@@ -49,45 +51,45 @@ module CsvRecord::Callbacks
|
|
49
51
|
|
50
52
|
[:build, :initialize].each do |initialize_method|
|
51
53
|
define_method initialize_method do |*args|
|
52
|
-
result = super
|
53
|
-
|
54
|
+
result = super(*args)
|
55
|
+
run_after_initialize_callbacks
|
54
56
|
result
|
55
57
|
end
|
56
58
|
end
|
57
59
|
|
58
60
|
def valid?
|
59
|
-
|
61
|
+
run_before_validation_callbacks
|
60
62
|
is_valid = super
|
61
|
-
|
63
|
+
run_after_validation_callbacks if is_valid
|
62
64
|
is_valid
|
63
65
|
end
|
64
66
|
|
65
67
|
def destroy
|
66
|
-
|
68
|
+
run_before_destroy_callbacks
|
67
69
|
is_destroyed = super
|
68
|
-
|
70
|
+
run_after_destroy_callbacks if is_destroyed
|
69
71
|
is_destroyed
|
70
72
|
end
|
71
73
|
|
72
74
|
def save(*args)
|
73
|
-
|
75
|
+
run_before_save_callbacks
|
74
76
|
is_saved = super
|
75
|
-
|
77
|
+
run_after_save_callbacks if is_saved
|
76
78
|
is_saved
|
77
79
|
end
|
78
80
|
|
79
81
|
def append_registry
|
80
|
-
|
82
|
+
run_before_create_callbacks
|
81
83
|
is_saved = super
|
82
|
-
|
84
|
+
run_after_create_callbacks if is_saved
|
83
85
|
is_saved
|
84
86
|
end
|
85
87
|
|
86
88
|
def update_registry
|
87
|
-
|
89
|
+
run_before_update_callbacks
|
88
90
|
saved = super
|
89
|
-
|
90
|
-
|
91
|
+
run_after_destroy_callbacks if saved
|
92
|
+
run_after_update_callbacks if saved
|
91
93
|
saved
|
92
94
|
end
|
93
95
|
end
|
@@ -96,4 +98,4 @@ module CsvRecord::Callbacks
|
|
96
98
|
receiver.extend ClassMethods
|
97
99
|
receiver.send :include, InstanceMethods
|
98
100
|
end
|
99
|
-
end
|
101
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class CsvRecord::Condition
|
2
4
|
attr_reader :field, :value
|
3
5
|
|
@@ -8,11 +10,11 @@ class CsvRecord::Condition
|
|
8
10
|
|
9
11
|
def self.create_from_hashes(hashes)
|
10
12
|
hashes.map do |hash|
|
11
|
-
new
|
13
|
+
new(*hash)
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
17
|
def to_code
|
16
18
|
"attributes['#{@field}'] == '#{@value}'"
|
17
19
|
end
|
18
|
-
end
|
20
|
+
end
|
data/lib/csv_record/connector.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module CsvRecord::Connector
|
2
4
|
DATABASE_FOLDER = 'db'.freeze
|
3
5
|
APPEND_MODE = 'a'.freeze
|
@@ -6,7 +8,7 @@ module CsvRecord::Connector
|
|
6
8
|
|
7
9
|
# Checks wheter the database directory exists
|
8
10
|
def __initialize_db_directory__
|
9
|
-
unless Dir.
|
11
|
+
unless Dir.exist?(DATABASE_FOLDER)
|
10
12
|
Dir.mkdir DATABASE_FOLDER
|
11
13
|
end
|
12
14
|
end
|
@@ -15,7 +17,7 @@ module CsvRecord::Connector
|
|
15
17
|
def __initialize_db__
|
16
18
|
__initialize_db_directory__
|
17
19
|
unless db_initialized?
|
18
|
-
open_database_file
|
20
|
+
open_database_file(WRITE_MODE) do |csv|
|
19
21
|
csv << doppelganger_fields
|
20
22
|
end
|
21
23
|
end
|
@@ -23,7 +25,7 @@ module CsvRecord::Connector
|
|
23
25
|
|
24
26
|
# Checks wheter the database file exists
|
25
27
|
def db_initialized?
|
26
|
-
File.exist? self.const_get
|
28
|
+
File.exist? self.const_get('DATABASE_LOCATION')
|
27
29
|
end
|
28
30
|
|
29
31
|
# Open the database file
|
@@ -43,7 +45,7 @@ module CsvRecord::Connector
|
|
43
45
|
CSV.open(self.const_get('DATABASE_LOCATION_TMP'), WRITE_MODE, headers: true) do |copy|
|
44
46
|
copy << fields
|
45
47
|
csv.entries.each do |entry|
|
46
|
-
new_row = yield
|
48
|
+
new_row = yield(entry)
|
47
49
|
copy << new_row if new_row
|
48
50
|
end
|
49
51
|
end
|
@@ -51,13 +53,13 @@ module CsvRecord::Connector
|
|
51
53
|
rename_database
|
52
54
|
end
|
53
55
|
|
54
|
-
|
56
|
+
private
|
55
57
|
|
56
58
|
# Rename the TMP database file to replace the original
|
57
59
|
def rename_database
|
58
60
|
old_file = self.const_get 'DATABASE_LOCATION'
|
59
61
|
tmp_file = self.const_get 'DATABASE_LOCATION_TMP'
|
60
|
-
while not File.
|
62
|
+
while not File.exist?(old_file) ; sleep(10) ; end
|
61
63
|
File.delete old_file
|
62
64
|
File.rename tmp_file, old_file
|
63
65
|
end
|
@@ -66,4 +68,4 @@ module CsvRecord::Connector
|
|
66
68
|
alias :initialize_db :__initialize_db__
|
67
69
|
alias :open_database_file :__open_database_file__
|
68
70
|
alias :parse_database_file :__parse_database_file__
|
69
|
-
end
|
71
|
+
end
|