redhead 0.0.1

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/lib/redhead.rb ADDED
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2010 Adam Prescott
2
+ # Licensed under the MIT license. See LICENSE.
3
+
4
+ module Redhead
5
+
6
+ # The character used to separate raw header names from their values.
7
+ HEADER_NAME_VALUE_SEPARATOR_CHARACTER = ":"
8
+
9
+ # The actual pattern to split header name from value. Uses the above character.
10
+ HEADER_NAME_VALUE_SEPARATOR_PATTERN = /\s*#{HEADER_NAME_VALUE_SEPARATOR_CHARACTER}\s*/
11
+
12
+ # The separator between header lines and regular body content.
13
+ HEADERS_SEPARATOR = "\n\n"
14
+
15
+ # The actual pattern used to split headers from content.
16
+ HEADERS_SEPARATOR_PATTERN = /#{HEADERS_SEPARATOR}/m
17
+
18
+ # The default code to convert a given key to a raw header name.
19
+ TO_RAW = lambda { |key| key.to_s.split(/_/).map(&:capitalize).join("-") }
20
+
21
+ # The default code to convert a given raw header name to a key.
22
+ TO_KEY = lambda { |raw| raw.split(/[^a-z_]+/i).join("_").downcase.to_sym }
23
+
24
+ # Method wrapping TO_RAW, to allow overriding for customisation.
25
+ def self.to_raw
26
+ TO_RAW
27
+ end
28
+
29
+ # Method wrapping TO_KEY, to allow overriding for customisation.
30
+ def self.to_key
31
+ TO_KEY
32
+ end
33
+ end
34
+
35
+ require "redhead/header"
36
+ require "redhead/header_set"
37
+ require "redhead/redhead_string"
@@ -0,0 +1,83 @@
1
+ module Redhead
2
+ class Header
3
+ attr_accessor :key, :raw, :value
4
+ attr_writer :to_key, :to_raw
5
+
6
+ def initialize(key, raw, value)
7
+ @key = key
8
+ @raw = raw
9
+ @value = value
10
+ end
11
+
12
+ # Parses a string representing a header. Uses HEADER_NAME_VALUE_SEPARATOR_PATTERN
13
+ # to determine the name and value parts of the string.
14
+ #
15
+ # With a given block, the parsed raw header name is passed to the block and the result is
16
+ # used as the key name. If no block is given, then the default is used to create the key
17
+ # name.
18
+ def self.parse(header_string, &block)
19
+ header_string =~ HEADER_NAME_VALUE_SEPARATOR_PATTERN
20
+ raw = $`
21
+ value = $'
22
+
23
+ to_key_block = block || Redhead.to_key
24
+ key = to_key_block[raw]
25
+
26
+ header = new(key, raw, value)
27
+
28
+ header
29
+ end
30
+
31
+ # Returns the header as a string. If raw_name is given, this value is used as the raw header
32
+ # name. If raw_name is not given, do one of two things:
33
+ #
34
+ # * If a block is given, pass #key to the block and use the result as the raw header name.
35
+ # * If a block is not given, use #raw as the raw header name.
36
+ def to_s(raw_name = nil)
37
+ r = raw_name || (block_given? ? yield(key) : raw)
38
+ "#{r}#{Redhead::HEADER_NAME_VALUE_SEPARATOR_CHARACTER} #{value}"
39
+ end
40
+
41
+ # Does the same thing as #to_s, but instead of calling #raw in the last case, it calls #raw!.
42
+ def to_s!(raw_name = nil)
43
+ r = raw_name || (block_given? ? yield(key) : raw!)
44
+ "#{r}#{Redhead::HEADER_NAME_VALUE_SEPARATOR_CHARACTER} #{value}"
45
+ end
46
+
47
+ # Calls #to_key with #raw as the argument.
48
+ def key!
49
+ to_key[raw]
50
+ end
51
+
52
+ # Calls #to_raw with #key as the argument. By-passes the stored raw header name and reproduces
53
+ # it with #to_raw dynamically.
54
+ def raw!
55
+ to_raw[key]
56
+ end
57
+
58
+ def inspect
59
+ "{ #{key.inspect} => #{value.inspect} }"
60
+ end
61
+
62
+ # Returns true if other_header has the same raw header name and value as self.
63
+ def ==(other_header)
64
+ raw == other_header.raw &&
65
+ value == other_header.value
66
+ end
67
+
68
+ # Returns the Proc object used to convert keys to raw header names. Defaults to Redhead.to_raw.
69
+ def to_raw
70
+ @to_raw || Redhead.to_raw
71
+ end
72
+
73
+ # Returns the Proc object used to convert keys to raw header names. Defaults to Redhead.to_raw.
74
+ def to_key
75
+ @to_key || Redhead.to_key
76
+ end
77
+
78
+ # Returns true if to_raw[to_key[raw]] == raw, otherwise, false.
79
+ def reversible?
80
+ to_raw[to_key[raw]] == raw
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,134 @@
1
+ module Redhead
2
+ class HeaderSet
3
+ include Enumerable
4
+
5
+ # Sets the headers of the set to _headers_. _headers_ is assumed to be ordered.
6
+ def initialize(headers)
7
+ @headers = headers
8
+ end
9
+
10
+ # Parses lines of header strings with Header.parse. Returns a new HeaderSet object
11
+ # for the parsed headers.
12
+ def self.parse(header_string, &block)
13
+ headers = []
14
+ header_string.split("\n").each do |str|
15
+ headers << Redhead::Header.parse(str, &block)
16
+ end
17
+
18
+ new(headers)
19
+ end
20
+
21
+ # Yields each header in the set.
22
+ def each
23
+ @headers.each { |h| yield h }
24
+ end
25
+
26
+ # Returns true if the set of headers is empty.
27
+ def empty?
28
+ @headers.empty?
29
+ end
30
+
31
+ # Returns the first header found which has Header#key matching _key_.
32
+ def [](key)
33
+ @headers.find { |header| header.key == key }
34
+ end
35
+
36
+ # If there is a header in the set with a key matching _key_, then set its value to _value_.
37
+ # If there is no header matching _key_, create a new header with the given key and value,
38
+ # with a raw header equal to to_raw[key]. Sets the new header's to_raw to self#to_raw.
39
+ def []=(key, value)
40
+ h = self[key]
41
+ if h
42
+ h.value = value
43
+ else
44
+ new_header = Redhead::Header.new(key, to_raw[key], value)
45
+ new_header.to_raw = to_raw
46
+ self << new_header
47
+ end
48
+ end
49
+
50
+ # Adds _header_ to the set of headers.
51
+ def <<(header)
52
+ @headers << header
53
+ end
54
+
55
+ # Similar to #[]= but allows manually setting the value of Header#raw to _raw_.
56
+ def add(key, value, raw = nil)
57
+ new_header = Redhead::Header.new(key, raw || to_raw[key], value)
58
+ new_header.to_raw = to_raw
59
+ self << new_header
60
+ new_header
61
+ end
62
+
63
+ # Removes any headers with key names matching _key_ from the set.
64
+ def delete(key)
65
+ header = self[key]
66
+ @headers.reject! { |header| header.key == key } ? header : nil
67
+ end
68
+
69
+ # Calls #to_s on each header in the set, joining the result with newlines.
70
+ #
71
+ # If _hash_ has a key matching a header in the set, passes the value for that key in the hash
72
+ # to Header#to_s. If _hash_ has no key for the header being iterated over, passes the given
73
+ # block to Header#to_s instead.
74
+ def to_s(hash = {}, &block)
75
+ return @headers.map { |header| header.to_s }.join("\n") if hash.empty? && !block_given?
76
+
77
+ @headers.map do |header|
78
+ if hash.has_key?(header.key)
79
+ header.to_s(hash[header.key])
80
+ else
81
+ header.to_s(&block)
82
+ end
83
+ end.join("\n")
84
+ end
85
+
86
+ # If a block is given, passes the block to Header#to_s! otherwise passes #to_raw instead. Joins
87
+ # the result with newlines.
88
+ def to_s!(&block)
89
+ blk = block || to_raw
90
+ @headers.map { |header| header.to_s!(&blk) }.join("\n")
91
+ end
92
+
93
+ # Returns true if Header#reversible? is true for each header in the set, otherwise false.
94
+ def reversible?
95
+ all? { |header| header.reversible? }
96
+ end
97
+
98
+ # Returns the Proc to be used to convert key names to raw header names. Defaults to Redhead.to_raw.
99
+ def to_raw
100
+ @to_raw || Redhead.to_raw
101
+ end
102
+
103
+ # Sets HeaderSet#to_raw to _new_to_raw_. Sets Header#to_raw for each header in the set to _new_to_raw_.
104
+ def to_raw=(new_to_raw)
105
+ @to_raw = new_to_raw
106
+ each { |header| header.to_raw = new_to_raw }
107
+ end
108
+
109
+ # Returns the Proc to be used to convert raw header names to key names. Defaults to Redhead.to_key.
110
+ def to_key
111
+ @to_key || Redhead.to_key
112
+ end
113
+
114
+ # Sets HeaderSet#to_raw to _new_to_raw_. Sets Header#to_raw for each header in the set to _new_to_raw_.
115
+ def to_key=(new_to_key)
116
+ @to_key = new_to_key
117
+ each { |header| header.to_key = new_to_key }
118
+ end
119
+
120
+ def inspect
121
+ "{ #{@headers.map { |header| header.inspect }.join(", ")} }"
122
+ end
123
+
124
+ # Returns true if, for each header in the set, there is a header in _other_ for which header#==(other_header)
125
+ # is true. Otherwise, returns false.
126
+ def ==(other)
127
+ @headers.all? do |header|
128
+ other.find do |other_header|
129
+ header == other_header
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,62 @@
1
+ require "delegate"
2
+
3
+ module Redhead
4
+ class String < SimpleDelegator
5
+ attr_reader :headers, :string
6
+
7
+ class << self
8
+ alias_method :[], :new
9
+ end
10
+
11
+ # Takes _string_, splits the headers from the content using HEADERS_SEPARATOR_PATTERN, then
12
+ # creates the headers by calling HeaderSet.parse, passing in _block_. Sets #to_key to _block_,
13
+ # and calls super with the main body content as an argument.
14
+ def initialize(string, &block)
15
+ string =~ HEADERS_SEPARATOR_PATTERN
16
+ @string = $'
17
+ super(@string)
18
+
19
+ @headers = Redhead::HeaderSet.parse($`, &block)
20
+ @headers.to_key = block
21
+ end
22
+
23
+ # Returns the main body content wrapped in the Redhead String object.
24
+ def to_s
25
+ __getobj__
26
+ end
27
+
28
+ def inspect
29
+ "+#{string.inspect}"
30
+ end
31
+
32
+ # Returns true if self.headers == other.headers and self.string == other.string.
33
+ def ==(other)
34
+ headers == other.headers && string == other.string
35
+ end
36
+
37
+ # Modifies the headers in the set, using the given _hash_, which has the form
38
+ #
39
+ # { :some_header => { :raw => a, :key => b }, :another_header => ..., ... }
40
+ #
41
+ # Change the header with key :some_header such that its new raw name is _a_ and its new key name
42
+ # is _b_. Returns a HeaderSet object containing the changed Header objects.
43
+ def headers!(hash)
44
+ changing = headers.select { |header| hash.has_key?(header.key) }
45
+
46
+ # modifies its elements!
47
+ changing.each do |header|
48
+ new_values = hash[header.key]
49
+ header.raw = new_values[:raw] if new_values[:raw]
50
+ header.key = new_values[:key] if new_values[:key]
51
+ end
52
+
53
+ Redhead::HeaderSet.new(changing)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def __getobj__
60
+ string
61
+ end
62
+ end
data/rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "rake"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:test) do |t|
5
+ t.rspec_opts = "-I test --color --format nested"
6
+ t.pattern = "test/**/*_spec.rb"
7
+ t.verbose = false
8
+ t.fail_on_error = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,344 @@
1
+ require "test_helper"
2
+
3
+ describe Redhead::HeaderSet do
4
+ before(:each) do
5
+ @headers = []
6
+ ("a".."c").map { |e| @headers << Redhead::Header.new(e.to_sym, "header_#{e}", "value_#{e}") }
7
+ @full_header_set_string = ("a".."c").map { |e| "header_#{e}: value_#{e}" }.join("\n")
8
+ @header = @headers.first
9
+ @first_header_key = :a
10
+ @header_set = Redhead::HeaderSet.new(@headers)
11
+ @default_to_raw = Redhead.to_raw
12
+ @default_to_key = Redhead.to_key
13
+
14
+ @reversible_headers = Redhead::HeaderSet.parse("A-Header: one\nA-Header-Two: two")
15
+ @irreversible_headers = Redhead::HeaderSet.parse("a_header: one\na_header_two: two")
16
+ end
17
+
18
+ context "as a class" do
19
+ describe ".parse" do
20
+ it "calls Header.parse on each header line, to create a set of headers" do
21
+ string = @full_header_set_string + Redhead::HEADERS_SEPARATOR + "some content goes here"
22
+ header_lines = @full_header_set_string.split("\n")
23
+ parsed_header_set = Redhead::HeaderSet.new(header_lines.map { |header_line| Redhead::Header.parse(header_line) })
24
+ Redhead::HeaderSet.parse(@full_header_set_string).should == parsed_header_set
25
+ end
26
+ end
27
+
28
+ context "with a block" do
29
+ it "uses the given block as to_key" do
30
+ Redhead::HeaderSet.parse(@full_header_set_string) { :foo }.each { |h| h.key.should == :foo }
31
+ end
32
+
33
+ it "does not set to_key on each parsed header object in the set" do
34
+ # note: Proc#== bug!
35
+ to_key = proc { :foo }
36
+ Redhead::HeaderSet.parse(@full_header_set_string, &to_key).each { |header| header.to_key.should_not == to_key }
37
+ end
38
+ end
39
+ end
40
+
41
+ it "is Enumerable and responds to #each" do
42
+ @header_set.is_a?(Enumerable).should be_true
43
+ @header_set.respond_to?(:each).should be_true
44
+ end
45
+
46
+ describe "#[]" do
47
+ context "for a key with a corresponding header" do
48
+ it "takes a symbolic header name key and returns a header" do
49
+ @header_set[:a].is_a?(Redhead::Header).should be_true
50
+ end
51
+ end
52
+
53
+ context "for a key with no corresponding header" do
54
+ it "returns nil" do
55
+ @header_set[:something_non_existent].should be_nil
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "#[]=" do
61
+ context "for a key with a corresponding header" do
62
+ it "sets a new header value" do
63
+ new_value = "new value"
64
+ @header_set[@first_header_key].should_not be_nil
65
+ @header_set[@first_header_key] = new_value
66
+ @header_set[@first_header_key].value.should == new_value
67
+ end
68
+ end
69
+
70
+ context "for a key with no corresponding header" do
71
+ it "creates a new header with this value" do
72
+ new_value = "some brand new value"
73
+ @header_set[:brand_new_key] = new_value
74
+ @header_set[:brand_new_key].should_not be_nil
75
+ @header_set[:brand_new_key].value.should == new_value
76
+ end
77
+
78
+ it "calls #to_raw to create the value of #raw" do
79
+ @header_set.to_raw = proc { "WHOA!" }
80
+ @header_set[:brand_new_key] = "some value"
81
+ @header_set[:brand_new_key].raw.should == "WHOA!"
82
+ end
83
+
84
+ it "sets new_header#to_raw to header_set#to_raw" do
85
+ @header_set.to_raw = proc { "Whoa!" }
86
+ @header_set[:brand_new_key] = "some value"
87
+ @header_set[:brand_new_key].to_raw.should == @header_set.to_raw
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "#add" do
93
+ context "being equivalent to #[]=" do
94
+ def new_header(header_string)
95
+ @header_set[:brand_new_key].should be_nil
96
+ @header_set.add(:brand_new_key, "some value")
97
+ @header_set[:brand_new_key].should_not be_nil
98
+ end
99
+
100
+ it "parses the given header string, adds the new header to self and returns that header" do
101
+ new_header(@header_set)
102
+ end
103
+
104
+ it "creates a new header with the given value" do
105
+ new_header(@header_set)
106
+ @header_set[:brand_new_key].value.should == "some value"
107
+ end
108
+
109
+ it "returns a Redhead::Header object" do
110
+ @header_set.add(:brand_new_key, "some value").class.should == Redhead::Header
111
+ end
112
+
113
+ it "calls #to_raw to create the value of #raw" do
114
+ @header_set.add(:brand_new_key, "some value")
115
+ @header_set[:brand_new_key].raw.should == "Brand-New-Key"
116
+
117
+ @header_set.to_raw = proc { "Nothing really" }
118
+ @header_set.add(:something_or_other, "something or other")
119
+ @header_set[:something_or_other].raw.should == "Nothing really"
120
+ end
121
+
122
+ it "sets new_header#to_raw to header_set#to_raw" do
123
+ @header_set.to_raw = proc { "Whoa!" }
124
+ @header_set.add(:brand_new_key, "some value")
125
+ @header_set[:brand_new_key].to_raw.should == @header_set.to_raw
126
+ end
127
+ end
128
+
129
+ it "takes an optional third argument which sets the value of the raw header" do
130
+ @header_set.add(:foo, "bar", "BAZ!")
131
+ @header_set[:foo].value.should == "bar"
132
+ @header_set[:foo].key.should == :foo
133
+ @header_set[:foo].raw.should == "BAZ!"
134
+ @header_set[:foo].raw!.should == "Foo"
135
+ end
136
+ end
137
+
138
+ describe "#delete" do
139
+ it "removes a header from the set" do
140
+ @header_set[:brand_new_key].should be_nil
141
+ @header_set[:brand_new_key] = "something random"
142
+ @header_set[:brand_new_key].should_not be_nil
143
+ new_header = @header_set[:brand_new_key]
144
+ @header_set.delete(:brand_new_key)
145
+ @header_set[:brand_new_key].should be_nil
146
+ end
147
+
148
+ it "returns the deleted header" do
149
+ @header_set[:brand_new_key] = "test"
150
+ h = @header_set[:brand_new_key]
151
+ @header_set.delete(:brand_new_key).should == h
152
+ end
153
+
154
+ it "returns nil if there is no header corresponding to the key" do
155
+ @header_set[:brand_new_key].should be_nil
156
+ @header_set.delete(:brand_new_key).should be_nil
157
+ end
158
+ end
159
+
160
+ describe "#to_s" do
161
+ it "equals the individual header to_s results, joined with newlines" do
162
+ @header_set.to_s.should == @headers.map { |header| header.to_s }.join("\n")
163
+ end
164
+
165
+ context %Q{with a hash argument :a => "something raw"} do
166
+ def modified_full_header_set_string
167
+ str = "something raw: value_a\n"
168
+ str += @headers[1..-1].map { |e| "header_#{e.key}: value_#{e.key}" }.join("\n")
169
+ str
170
+ end
171
+
172
+ it %Q{sets the header with key :a to have #raw == "one" and #value == 1} do
173
+ str = modified_full_header_set_string
174
+
175
+ @header_set.to_s(:a => "something raw").should == str
176
+ @header_set[:a].raw.should_not == "something raw"
177
+ @header_set[:a].raw.should == "header_a"
178
+ end
179
+
180
+ it "does not leave a side-effect" do
181
+ str = modified_full_header_set_string
182
+
183
+ @header_set.to_s(:a => "something raw").should == str
184
+ @header_set[:a].raw.should_not == "something raw"
185
+ @header_set[:a].raw.should == "header_a"
186
+ end
187
+ end
188
+
189
+ context "with a block argument" do
190
+ def modified_full_header_set_string
191
+ @headers.map { |e| "#{yield e.key}: value_#{e.key}" }.join("\n")
192
+ end
193
+
194
+ it "uses the given block to convert #key to a raw header, for each header in the set" do
195
+ @header_set.to_s { "testing" + "testing" }.should == modified_full_header_set_string { "testing" + "testing" }
196
+
197
+ new_to_raw = proc { |x| x.to_s.upcase.reverse }
198
+
199
+ @header_set.to_s(&new_to_raw).should == modified_full_header_set_string(&new_to_raw)
200
+ end
201
+
202
+ it "does not leave the given block as #to_raw" do
203
+ @header_set.to_s { "test" + "test" }
204
+ @header_set.to_raw.should_not == proc { "test" + "test" }
205
+ end
206
+
207
+ it "follows the hash argument first, falling back to the given block" do
208
+ @header_set.to_s(:a => "something raw") { "NOT RAW AT ALL" }.split("\n").first.should == "something raw: value_a"
209
+ end
210
+ end
211
+ end
212
+
213
+ describe "#to_s!" do
214
+ context "without a block" do
215
+ it "calls to_s! on each header in the set, passing #to_raw as a block joining the results with newlines" do
216
+ @header_set.to_raw = proc { "Total foo bar" }
217
+ @header_set.to_s!.should == @headers.map { |header| "Total foo bar: #{header.value}" }.join("\n")
218
+ end
219
+ end
220
+
221
+ context "with a block" do
222
+ it "calls to_s! on each header in the set, passing the given block, joining the results with newlines" do
223
+ @header_set.to_s! { "Total foo bar" }.should == @headers.map { |header| "Total foo bar: #{header.value}" }.join("\n")
224
+ end
225
+
226
+ it "does not leave the given block as #to_raw on existing headers" do
227
+ temp_to_raw = proc { "Total foo bar" }
228
+ @header_set.to_s!(&temp_to_raw)
229
+ @header_set.all? { |header| header.raw!.should_not == "Total foo bar" }
230
+ end
231
+
232
+ it "does not leave the given block as #to_raw on the header set" do
233
+ temp_to_raw = proc { "Total foo bar" }
234
+ @header_set.to_s!(&temp_to_raw)
235
+ @header_set.to_raw.should_not == temp_to_raw
236
+ @header_set[:temp_foo_foo] = "what"
237
+ @header_set[:temp_foo_foo].raw!.should_not == "Total foo bar"
238
+ end
239
+ end
240
+ end
241
+
242
+ describe "#==(other_header)" do
243
+ it "is sane." do
244
+ @header_set.should == @header_set
245
+
246
+ Redhead::HeaderSet.parse("Test: test").should == Redhead::HeaderSet.parse("Test: test")
247
+ end
248
+
249
+ it "returns true if, for every header in self, there is a corresponding header in other_header equal to it, using Header#==" do
250
+ one, two = @header_set.partition { |header| header.key.to_s < @header_set.to_a[1].key.to_s }.map { |part| Redhead::HeaderSet.new(part) }
251
+
252
+ one.all? { |a| two.find { |b| a == b } }.should be_false
253
+ # sanity check with any?
254
+ one.any? { |a| two.find { |b| a == b } }.should be_false
255
+
256
+ one << two.first # create an overlap
257
+
258
+ one.all? { |a| two.find { |b| a == b } }.should be_false
259
+ # sanity check with any?
260
+ one.any? { |a| two.find { |b| a == b } }.should be_true
261
+ end
262
+ end
263
+
264
+ describe "#reversible?" do
265
+ it "returns true if each header in the set is reversible, otherwise false" do
266
+ @reversible_headers.reversible?.should == @reversible_headers.all? { |header| header.reversible? }
267
+ @irreversible_headers.reversible?.should == @irreversible_headers.all? { |header| header.reversible? }
268
+
269
+ @reversible_headers.reversible?.should be_true
270
+ @irreversible_headers.reversible?.should be_false
271
+
272
+ @reversible_headers.to_raw = proc { "" }
273
+ @reversible_headers.reversible?.should_not be_true # contained headers get caught up in the change
274
+
275
+ # example from the readme:
276
+
277
+ string = "A-Header-Name: a header value\n\nContent."
278
+
279
+ str = Redhead::String.new(string) do |name|
280
+ name.gsub(/-/, "").upcase.to_sym
281
+ end
282
+
283
+ str.headers.reversible?.should be_false
284
+
285
+ str = Redhead::String.new(string) do |name|
286
+ name.split(/-/).map { |e| e.upcase }.join("zzz").to_sym
287
+ end
288
+
289
+ str.headers.reversible?.should be_false
290
+
291
+ str.headers.to_raw = lambda do |name|
292
+ name.to_s.split(/zzz/).map { |e| e.capitalize }.join("-")
293
+ end
294
+
295
+ str.headers.reversible?.should be_true
296
+ end
297
+ end
298
+
299
+ describe "#to_raw" do
300
+ it "defaults to Redhead.to_raw" do
301
+ # note: Proc#== bug!
302
+ @header_set.to_raw.should == @default_to_raw
303
+ end
304
+ end
305
+
306
+ describe "#to_raw=" do
307
+ it "sets a new block to be used as to_raw" do
308
+ # note: Proc#== bug!
309
+ new_to_raw = proc { "" + "" }
310
+ @header_set.to_raw = new_to_raw
311
+ @header_set.to_raw.should_not == @default_to_raw
312
+ @header_set.to_raw.should == new_to_raw
313
+ end
314
+
315
+ it "sets to_raw, for each header in the set" do
316
+ new_to_raw = proc { "" + "" }
317
+ @header_set.to_raw = new_to_raw
318
+ @header_set.each { |header| header.to_raw.should == new_to_raw }
319
+ end
320
+ end
321
+
322
+ describe "#to_key" do
323
+ it "defaults to Redhead.to_key" do
324
+ # note: Proc#== bug!
325
+ @header_set.to_key.should == @default_to_key
326
+ end
327
+ end
328
+
329
+ describe "#to_key=" do
330
+ it "sets a new block to be used as to_key" do
331
+ # note: Proc#== bug!
332
+ new_to_key = proc { "" + "" }
333
+ @header_set.to_key = new_to_key
334
+ @header_set.to_key.should_not == @default_to_key
335
+ @header_set.to_key.should == new_to_key
336
+ end
337
+
338
+ it "sets to_key, for each header in the set" do
339
+ new_to_key = proc { "" + "" }
340
+ @header_set.to_key = new_to_key
341
+ @header_set.each { |header| header.to_key.should == new_to_key }
342
+ end
343
+ end
344
+ end