redhead 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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