data-writer 0.9.2 → 1.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 +4 -2
- data/data-writer.gemspec +11 -11
- data/lib/data-writer.rb +60 -51
- metadata +2 -2
data/README.md
CHANGED
@@ -49,14 +49,16 @@ require 'data-writer'
|
|
49
49
|
|
50
50
|
appender = DATAWriter.file("a")
|
51
51
|
appender.write " my dear Watson"
|
52
|
-
appender.close
|
52
|
+
appender.close
|
53
|
+
|
54
|
+
DATA.read # => "Elementary my dear Watson"
|
53
55
|
|
54
56
|
__END__
|
55
57
|
Elementary
|
56
58
|
```
|
57
59
|
|
58
60
|
If this method is called and DATA is not defined then it will raise a DATANotFoundError exception.
|
59
|
-
The file objects returned by this method have their #
|
61
|
+
The file objects returned by this method have their __#rewind__ method changed so that it seeks back to
|
60
62
|
the start of DATA, and not back to the start of the file.
|
61
63
|
|
62
64
|
|
data/data-writer.gemspec
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name
|
3
|
-
s.version
|
4
|
-
s.date
|
5
|
-
s.summary
|
6
|
-
s.description
|
7
|
-
s.authors
|
8
|
-
s.email
|
9
|
-
s.homepage
|
10
|
-
s.files
|
2
|
+
s.name = 'data-writer'
|
3
|
+
s.version = '1.0'
|
4
|
+
s.date = '2012-08-01'
|
5
|
+
s.summary = "Allows you to write to DATA"
|
6
|
+
s.description = "Normally you can only read from DATA but with data-writer you can also write to it. This allows you to easily persist data in a source file."
|
7
|
+
s.authors = ["Kalle Lindstrom"]
|
8
|
+
s.email = ["lindstrom.kalle@gmail.com"]
|
9
|
+
s.homepage = "https://github.com/kl/data-writer"
|
10
|
+
s.files = %w[lib/data-writer.rb README.md data-writer.gemspec Gemfile]
|
11
11
|
s.require_paths = ['lib']
|
12
|
-
s.has_rdoc
|
12
|
+
s.has_rdoc = false
|
13
13
|
|
14
14
|
s.add_development_dependency('rake')
|
15
15
|
s.add_development_dependency('minitest')
|
16
|
-
end
|
16
|
+
end
|
data/lib/data-writer.rb
CHANGED
@@ -4,20 +4,12 @@ class DATAWriter
|
|
4
4
|
|
5
5
|
class DATANotFoundError < StandardError; end
|
6
6
|
|
7
|
-
#
|
8
|
-
# The position in the file where DATA starts (line after __END__)
|
9
|
-
#
|
10
|
-
def self.data_start_pos
|
11
|
-
@data_start_pos
|
12
|
-
end
|
13
|
-
|
14
7
|
#
|
15
8
|
# Factory method for DATA writers. Works simliar to File.new.
|
16
9
|
# mode can be both a string like "w" or a number like File::WRONLY
|
17
10
|
#
|
18
11
|
def self.file(mode, opt={})
|
19
|
-
|
20
|
-
data_path = File.expand_path(DATA.path)
|
12
|
+
raise_data_not_found unless Object.const_defined?(:DATA)
|
21
13
|
|
22
14
|
if mode.is_a?(String)
|
23
15
|
valid_mode = get_valid_string_mode(mode)
|
@@ -25,11 +17,9 @@ class DATAWriter
|
|
25
17
|
valid_mode = get_valid_int_mode(mode)
|
26
18
|
end
|
27
19
|
|
28
|
-
file = create_file(
|
29
|
-
|
30
|
-
|
31
|
-
file.pos = @data_start_pos # sets the file pos to the line after __END__.
|
32
|
-
enhanced = enhance_file(file) # adds specialized methods for this object.
|
20
|
+
file = create_file(get_source_path, valid_mode, opt)
|
21
|
+
file.pos = get_data_pos # sets the file pos to the line after __END__.
|
22
|
+
enhanced = enhance_file(file) # adds specialized methods for this object.
|
33
23
|
|
34
24
|
if block_given?
|
35
25
|
yield(enhanced)
|
@@ -39,18 +29,34 @@ class DATAWriter
|
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
32
|
+
#
|
33
|
+
# Get the path of the source file.
|
34
|
+
#
|
35
|
+
def self.get_source_path
|
36
|
+
File.expand_path($0)
|
37
|
+
end
|
38
|
+
private_class_method :get_source_path
|
39
|
+
|
40
|
+
#
|
41
|
+
# Returns the position of __END__ in the source file.
|
42
|
+
#
|
43
|
+
def self.get_data_pos
|
44
|
+
if RUBY_PLATFORM =~ /java/i
|
45
|
+
scan_data_pos
|
46
|
+
else
|
47
|
+
DATA.pos
|
48
|
+
end
|
49
|
+
end
|
50
|
+
private_class_method :get_data_pos
|
51
|
+
|
42
52
|
#
|
43
53
|
# If "w" was specifed as a mode we need to remove that (because it will truncate the whole file)
|
44
54
|
#
|
45
55
|
def self.get_valid_string_mode(mode)
|
46
56
|
if mode =~ /w/
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
else
|
51
|
-
mode.sub!("w", "r+")
|
52
|
-
end
|
53
|
-
mode
|
57
|
+
trunc_end # truncate after __END__.
|
58
|
+
sub_with = mode.include?("+") ? "r" : "r+" # the actual mode will be "r+"
|
59
|
+
mode.sub("w", sub_with)
|
54
60
|
else
|
55
61
|
mode
|
56
62
|
end
|
@@ -62,7 +68,7 @@ class DATAWriter
|
|
62
68
|
#
|
63
69
|
def self.get_valid_int_mode(mode)
|
64
70
|
if (mode & File::TRUNC) == File::TRUNC # mode includes TRUNC
|
65
|
-
|
71
|
+
trunc_end # truncate after __END__.
|
66
72
|
valid_mode = 0
|
67
73
|
File::Constants.constants.each do |const| # build new mode excluding TRUNC
|
68
74
|
value = File::const_get(const)
|
@@ -78,6 +84,17 @@ class DATAWriter
|
|
78
84
|
end
|
79
85
|
private_class_method :get_valid_int_mode
|
80
86
|
|
87
|
+
#
|
88
|
+
# Deletes everything after __END__. This is used to simulate the "w" permission mode.
|
89
|
+
#
|
90
|
+
def self.trunc_end
|
91
|
+
file_content = File.read(get_source_path)
|
92
|
+
new_content = file_content[/.+?^__END__$/m] + "\n" # everything up to and including __END__.
|
93
|
+
|
94
|
+
File.open(get_source_path, "w") { |f| f.write(new_content) }
|
95
|
+
end
|
96
|
+
private_class_method :trunc_end
|
97
|
+
|
81
98
|
#
|
82
99
|
# Helper method to create a file that works in both 1.8 and 1.9 and different implementations.
|
83
100
|
#
|
@@ -86,16 +103,14 @@ class DATAWriter
|
|
86
103
|
|
87
104
|
if RUBY_PLATFORM =~ /java/i
|
88
105
|
if ruby >= "1.9.3"
|
89
|
-
|
90
|
-
File.new(path, mode_string, opt) # Only JRuby 1.7 seem to implement this method the 1.9 way.
|
106
|
+
File.new(path, mode_string, opt_with_encoding(opt)) # Only JRuby 1.7 seem to implement this method the 1.9 way.
|
91
107
|
else
|
92
108
|
File.new(path, mode_string)
|
93
109
|
end
|
94
110
|
|
95
111
|
else
|
96
112
|
if ruby >= "1.9.0"
|
97
|
-
|
98
|
-
File.new(path, mode_string, opt)
|
113
|
+
File.new(path, mode_string, opt_with_encoding(opt))
|
99
114
|
else
|
100
115
|
File.new(path, mode_string)
|
101
116
|
end
|
@@ -104,59 +119,53 @@ class DATAWriter
|
|
104
119
|
private_class_method :create_file
|
105
120
|
|
106
121
|
#
|
107
|
-
#
|
122
|
+
# Returns a new options hash that has it's :encoding key set to the source file encoding.
|
108
123
|
#
|
109
|
-
def self.
|
110
|
-
|
111
|
-
file_content = File.read(file_path)
|
112
|
-
new_content = file_content[/.+?^__END__$/m] + "\n" # everything up to an including __END__.
|
113
|
-
|
114
|
-
File.open(file_path, "w") { |f| f.write(new_content) }
|
124
|
+
def self.opt_with_encoding(opt)
|
125
|
+
{:encoding => __ENCODING__}.merge(opt)
|
115
126
|
end
|
116
|
-
private_class_method :
|
127
|
+
private_class_method :opt_with_encoding
|
117
128
|
|
118
129
|
#
|
119
|
-
# Finds the position in the file after __END__
|
120
|
-
#
|
130
|
+
# Finds the position in the file after __END__ (same as DATA.pos)
|
131
|
+
# This method is only used by JRuby since DATA.pos does not work in JRuby.
|
121
132
|
#
|
122
133
|
def self.scan_data_pos
|
123
|
-
source_file = File.new(
|
134
|
+
source_file = File.new(get_source_path)
|
124
135
|
|
125
136
|
until source_file.eof?
|
126
137
|
line = source_file.gets
|
127
|
-
if line =~
|
138
|
+
if line =~ /^__END__$/
|
128
139
|
pos = source_file.pos
|
129
140
|
source_file.close
|
130
141
|
return pos
|
131
142
|
end
|
132
143
|
end
|
133
144
|
source_file.close
|
134
|
-
|
145
|
+
raise_data_not_found
|
135
146
|
end
|
136
147
|
private_class_method :scan_data_pos
|
137
148
|
|
138
149
|
#
|
139
150
|
# Adds specialized methods to the DATA writer object.
|
140
151
|
#
|
141
|
-
def self.enhance_file(
|
152
|
+
def self.enhance_file(file)
|
142
153
|
|
143
|
-
|
144
|
-
|
154
|
+
file.instance_variable_set(:@DATA_pos, file.pos)
|
155
|
+
|
156
|
+
def file.rewind # so that #rewind will go back to __END__ and not the beginning of the file.
|
157
|
+
self.pos = @DATA_pos
|
145
158
|
end
|
146
159
|
|
147
|
-
|
160
|
+
file
|
148
161
|
end
|
149
162
|
private_class_method :enhance_file
|
150
163
|
|
151
164
|
#
|
152
|
-
# Raises a DATANotFoundError exception
|
165
|
+
# Raises a DATANotFoundError exception.
|
153
166
|
#
|
154
|
-
def self.
|
155
|
-
|
156
|
-
DATA
|
157
|
-
rescue NameError
|
158
|
-
raise DATANotFoundError, "DATA object does not exist. Ensure that the file has __END__"
|
159
|
-
end
|
167
|
+
def self.raise_data_not_found
|
168
|
+
raise DATANotFoundError, "DATA object does not exist. Ensure that the file has __END__"
|
160
169
|
end
|
161
|
-
private_class_method :
|
170
|
+
private_class_method :raise_data_not_found
|
162
171
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data-writer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0
|
4
|
+
version: '1.0'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|