roxml 2.3.2 → 2.4.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/History.txt +145 -0
- data/Manifest.txt +81 -0
- data/Rakefile +85 -95
- data/TODO +42 -0
- data/html/index.html +278 -0
- data/html/style.css +79 -0
- data/lib/roxml.rb +112 -49
- data/lib/roxml/extensions/active_support.rb +37 -12
- data/lib/roxml/extensions/array/conversions.rb +12 -2
- data/lib/roxml/extensions/deprecation.rb +4 -4
- data/lib/roxml/options.rb +39 -30
- data/lib/roxml/xml.rb +119 -54
- data/lib/roxml/xml/rexml.rb +2 -2
- data/roxml.gemspec +40 -101
- data/tasks/test.rake +42 -0
- data/test/bugs/rexml_bugs.rb +15 -0
- data/test/fixtures/book_with_octal_pages.xml +4 -0
- data/test/mocks/mocks.rb +0 -4
- data/test/test_helper.rb +1 -1
- data/test/unit/array_test.rb +16 -0
- data/test/unit/freeze_test.rb +71 -0
- data/test/unit/inheritance_test.rb +26 -3
- data/test/unit/options_test.rb +20 -19
- data/test/unit/overriden_output_test.rb +33 -0
- data/test/unit/roxml_test.rb +7 -0
- data/test/unit/xml_bool_test.rb +16 -11
- data/test/unit/xml_convention_test.rb +150 -0
- data/test/unit/xml_hash_test.rb +41 -0
- data/test/unit/xml_name_test.rb +29 -6
- data/test/unit/xml_object_test.rb +30 -0
- data/vendor/override_rake_task/README +30 -0
- data/vendor/override_rake_task/init.rb +1 -0
- data/vendor/override_rake_task/install.rb +46 -0
- data/vendor/override_rake_task/lib/override_rake_task.rb +16 -0
- metadata +77 -34
@@ -0,0 +1,33 @@
|
|
1
|
+
class OctalInteger
|
2
|
+
def self.from_xml(val)
|
3
|
+
new(Integer(val.content))
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(value)
|
7
|
+
@val = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
@val == other
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_xml
|
15
|
+
sprintf("%#o", @val)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class BookWithOctalPages
|
20
|
+
include ROXML
|
21
|
+
|
22
|
+
xml_accessor :pages_with_to_xml_proc, :as => Integer, :to_xml => proc {|val| sprintf("%#o", val) }, :required => true
|
23
|
+
xml_accessor :pages_with_type, OctalInteger, :required => true
|
24
|
+
end
|
25
|
+
|
26
|
+
class TestToXmlWithOverriddenOutput < Test::Unit::TestCase
|
27
|
+
to_xml_test :book_with_octal_pages
|
28
|
+
def test_padded_numbers_read_properly
|
29
|
+
b = BookWithOctalPages.from_xml(fixture(:book_with_octal_pages))
|
30
|
+
assert_equal 239, b.pages_with_type
|
31
|
+
assert_equal 239, b.pages_with_to_xml_proc
|
32
|
+
end
|
33
|
+
end
|
data/test/unit/roxml_test.rb
CHANGED
data/test/unit/xml_bool_test.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
|
+
PROC_TRUE = proc {|val| val ? 'TRUE' : 'FALSE'}
|
4
|
+
PROC_True = proc {|val| val ? 'True' : 'False'}
|
5
|
+
PROC_true = proc {|val| val.to_s}
|
6
|
+
PROC_1 = proc {|val| val ? 1 : 0}
|
7
|
+
|
3
8
|
class XmlBool
|
4
9
|
include ROXML
|
5
10
|
|
6
|
-
|
7
|
-
xml_reader :
|
8
|
-
xml_reader :
|
9
|
-
xml_reader :
|
10
|
-
xml_reader :
|
11
|
-
xml_reader :
|
12
|
-
xml_reader :
|
13
|
-
xml_reader :
|
11
|
+
xml_name 'xml_bool'
|
12
|
+
xml_reader :true_from_TRUE?, :to_xml => PROC_TRUE
|
13
|
+
xml_reader :false_from_FALSE?, :text => 'text_for_FALSE', :to_xml => PROC_TRUE
|
14
|
+
xml_reader :true_from_one?, :attr => 'attr_for_one', :to_xml => PROC_1
|
15
|
+
xml_reader :false_from_zero?, :text => 'text_for_zero', :in => 'container', :to_xml => PROC_1
|
16
|
+
xml_reader :true_from_True?, :attr => 'attr_for_True', :in => 'container', :to_xml => PROC_True
|
17
|
+
xml_reader :false_from_False?, :text => 'false_from_cdata_False', :as => :cdata, :to_xml => PROC_True
|
18
|
+
xml_reader :true_from_true?, :to_xml => PROC_true
|
19
|
+
xml_reader :false_from_false?, :to_xml => PROC_true
|
14
20
|
xml_reader :missing?
|
15
21
|
end
|
16
22
|
|
@@ -44,7 +50,6 @@ BOOL_XML = %{
|
|
44
50
|
<false_from_cdata_False><![CDATA[False]]></false_from_cdata_False>
|
45
51
|
<true_from_true>true</true_from_true>
|
46
52
|
<false_from_false>false</false_from_false>
|
47
|
-
<present_and_required>true</present_and_required>
|
48
53
|
</xml_bool>
|
49
54
|
}
|
50
55
|
PRESENT = %{
|
@@ -96,10 +101,10 @@ class TestXMLBool < Test::Unit::TestCase
|
|
96
101
|
XmlBoolRequired.from_xml(PRESENT)
|
97
102
|
end
|
98
103
|
|
99
|
-
|
104
|
+
assert_raise ROXML::RequiredElementMissing do
|
100
105
|
XmlBoolRequired.from_xml(ABSENT)
|
101
106
|
end
|
102
107
|
end
|
103
108
|
|
104
|
-
|
109
|
+
to_xml_test XmlBool => BOOL_XML
|
105
110
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
XML_CAMELLOWER = %{
|
4
|
+
<bookCase name="Jonas' Books">
|
5
|
+
<bookCount>12</bookCount>
|
6
|
+
<bigBooks>
|
7
|
+
<bigBook>GED</bigBook>
|
8
|
+
<bigBook>House of Leaves</bigBook>
|
9
|
+
</bigBooks>
|
10
|
+
</bookCase>
|
11
|
+
}
|
12
|
+
|
13
|
+
XML_CAMELCASE = %{
|
14
|
+
<BookCase Name="Jonas' Books">
|
15
|
+
<BookCount>12</BookCount>
|
16
|
+
<BigBooks>
|
17
|
+
<BigBook>GED</BigBook>
|
18
|
+
<BigBook>House of Leaves</BigBook>
|
19
|
+
</BigBooks>
|
20
|
+
</BookCase>
|
21
|
+
}
|
22
|
+
|
23
|
+
XML_UNDERSCORE = %{
|
24
|
+
<book_case name="Jonas' Books">
|
25
|
+
<book_count>12</book_count>
|
26
|
+
<big_books>
|
27
|
+
<big_book>GED</big_book>
|
28
|
+
<big_book>House of Leaves</big_book>
|
29
|
+
</big_books>
|
30
|
+
</book_case>
|
31
|
+
}
|
32
|
+
|
33
|
+
XML_DASHES = %{
|
34
|
+
<book-case name="Jonas' Books">
|
35
|
+
<book-count>12</book-count>
|
36
|
+
<big-books>
|
37
|
+
<big-book>GED</big-book>
|
38
|
+
<big-book>House of Leaves</big-book>
|
39
|
+
</big-books>
|
40
|
+
</book-case>
|
41
|
+
}
|
42
|
+
|
43
|
+
XML_UPCASE = %{
|
44
|
+
<BOOKCASE NAME="Jonas' Books">
|
45
|
+
<BOOKCOUNT>12</BOOKCOUNT>
|
46
|
+
<BIGBOOKS>
|
47
|
+
<BIGBOOK>GED</BIGBOOK>
|
48
|
+
<BIGBOOK>House of Leaves</BIGBOOK>
|
49
|
+
</BIGBOOKS>
|
50
|
+
</BOOKCASE>
|
51
|
+
}
|
52
|
+
|
53
|
+
class BookCase
|
54
|
+
include ROXML
|
55
|
+
|
56
|
+
xml_reader :book_count, :as => Integer, :required => true
|
57
|
+
xml_reader :big_books, [:text], :required => true
|
58
|
+
end
|
59
|
+
|
60
|
+
class BookCaseCamelCase < BookCase
|
61
|
+
xml_convention :camelcase
|
62
|
+
end
|
63
|
+
|
64
|
+
class BookCaseUnderScore < BookCase
|
65
|
+
xml_convention :underscore
|
66
|
+
end
|
67
|
+
|
68
|
+
class BookCaseDashes < BookCase
|
69
|
+
xml_convention &:dasherize
|
70
|
+
end
|
71
|
+
|
72
|
+
class BookCaseCamelLower < BookCase
|
73
|
+
xml_convention {|val| val.camelcase(:lower) }
|
74
|
+
end
|
75
|
+
|
76
|
+
class BookCaseUpCase < BookCase
|
77
|
+
xml_convention {|val| val.gsub('_', '').upcase }
|
78
|
+
end
|
79
|
+
|
80
|
+
class InheritedBookCaseCamelCase < BookCaseCamelCase
|
81
|
+
end
|
82
|
+
|
83
|
+
class InheritedBookCaseUpCase < BookCaseUpCase
|
84
|
+
end
|
85
|
+
|
86
|
+
# Same as BookCase. Needed to keep BookCase clean for other tests
|
87
|
+
class ParentBookCaseDefault
|
88
|
+
include ROXML
|
89
|
+
|
90
|
+
xml_reader :book_count, :as => Integer, :required => true
|
91
|
+
xml_reader :big_books, [:text], :required => true
|
92
|
+
end
|
93
|
+
|
94
|
+
class InheritedBookCaseDefault < ParentBookCaseDefault
|
95
|
+
end
|
96
|
+
|
97
|
+
class TestXMLConstruct < Test::Unit::TestCase
|
98
|
+
# TODO: Test convention applies to xml_name as well...
|
99
|
+
|
100
|
+
def test_default_convention_is_underscore
|
101
|
+
bc = BookCase.from_xml(XML_UNDERSCORE)
|
102
|
+
assert_has_book_case_info(bc)
|
103
|
+
end
|
104
|
+
|
105
|
+
[BookCaseUpCase, BookCaseCamelLower, BookCaseDashes, BookCaseUnderScore, BookCaseCamelCase].each do |klass|
|
106
|
+
define_method(:"test_xml_convention_#{klass.to_s.underscore}") do
|
107
|
+
data = :"XML_#{klass.to_s.sub('BookCase', '').upcase}"
|
108
|
+
assert_equal Proc, klass.roxml_naming_convention.class
|
109
|
+
|
110
|
+
bc = klass.from_xml(Object.const_get(data))
|
111
|
+
assert_has_book_case_info(bc)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_child_should_inherit_convention_if_it_doesnt_declare_one
|
116
|
+
[InheritedBookCaseUpCase, InheritedBookCaseCamelCase].each do |klass|
|
117
|
+
data = :"XML_#{klass.to_s.sub('InheritedBookCase', '').upcase}"
|
118
|
+
assert_equal Proc, klass.roxml_naming_convention.class
|
119
|
+
|
120
|
+
bc = klass.from_xml(Object.const_get(data))
|
121
|
+
assert_has_book_case_info(bc)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_child_should_inherit_convention_even_if_it_is_added_after_child_declaration
|
126
|
+
bc = InheritedBookCaseDefault.from_xml(XML_UNDERSCORE)
|
127
|
+
assert_has_book_case_info(bc)
|
128
|
+
|
129
|
+
ParentBookCaseDefault.class_eval do
|
130
|
+
xml_convention :dasherize
|
131
|
+
end
|
132
|
+
|
133
|
+
bc = InheritedBookCaseDefault.from_xml(XML_DASHES)
|
134
|
+
assert_has_book_case_info(bc)
|
135
|
+
assert_raise ROXML::RequiredElementMissing do
|
136
|
+
InheritedBookCaseDefault.from_xml(XML_UNDERSCORE)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_tag_name_should_get_convention_treatment_as_well
|
141
|
+
assert_equal "book-case-dashes", BookCaseDashes.tag_name
|
142
|
+
assert_equal "INHERITEDBOOKCASEUPCASE", InheritedBookCaseUpCase.tag_name
|
143
|
+
assert_equal "InheritedBookCaseCamelCase", InheritedBookCaseCamelCase.tag_name
|
144
|
+
end
|
145
|
+
|
146
|
+
def assert_has_book_case_info(bc)
|
147
|
+
assert_equal 12, bc.book_count
|
148
|
+
assert_equal ['GED', 'House of Leaves'], bc.big_books
|
149
|
+
end
|
150
|
+
end
|
data/test/unit/xml_hash_test.rb
CHANGED
@@ -1,11 +1,52 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
|
+
class BookWithContributorHash
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_reader :contributors, {:key => {:attr => 'role'},
|
7
|
+
:value => 'name'}
|
8
|
+
end
|
9
|
+
|
3
10
|
class TestXMLHash < Test::Unit::TestCase
|
4
11
|
def setup
|
5
12
|
@contents = {'quaquaversally' => 'adjective: (of a geological formation) sloping downward from the center in all directions.',
|
6
13
|
'tergiversate' => 'To use evasions or ambiguities; equivocate.'}
|
7
14
|
end
|
8
15
|
|
16
|
+
def test_hash_preserves_data
|
17
|
+
b = BookWithContributorHash.from_xml(%{
|
18
|
+
<book isbn="0974514055">
|
19
|
+
<contributor role="author"><name>David Thomas</name></contributor>
|
20
|
+
<contributor role="supporting author"><name>Andrew Hunt</name></contributor>
|
21
|
+
<contributor role="supporting author"><name>Chad Fowler</name></contributor>
|
22
|
+
</book>
|
23
|
+
})
|
24
|
+
assert_equal({'author' => 'David Thomas', 'supporting author' => ['Andrew Hunt', 'Chad Fowler']},
|
25
|
+
b.contributors)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_hash_with_object_key_fails
|
29
|
+
assert_raise ArgumentError do
|
30
|
+
Class.new do
|
31
|
+
include ROXML
|
32
|
+
|
33
|
+
xml_reader :object_key_to_text, {:key => BookWithContributorHash,
|
34
|
+
:value => 'text_node'}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_hash_with_object_value_fails
|
40
|
+
assert_raise ArgumentError do
|
41
|
+
Class.new do
|
42
|
+
include ROXML
|
43
|
+
|
44
|
+
xml_reader :key_to_object_value, {:key => {:attr => 'text_node'},
|
45
|
+
:value => BookWithContributorHash}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
9
50
|
def test_attrs_hash
|
10
51
|
dict = DictionaryOfAttrs.from_xml(fixture(:dictionary_of_attrs))
|
11
52
|
assert_equal Hash, dict.definitions.class
|
data/test/unit/xml_name_test.rb
CHANGED
@@ -75,6 +75,16 @@ class TestXMLName < Test::Unit::TestCase
|
|
75
75
|
assert_equal "<parent><child_accessor_name/></parent>", parent.to_xml.to_s.gsub(/[\n ]/, '')
|
76
76
|
end
|
77
77
|
|
78
|
+
def test_it_should_be_inherited
|
79
|
+
class_with_inherited_name = Class.new(ParentOfNamedChild)
|
80
|
+
assert_equal :parent, class_with_inherited_name.tag_name
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_it_should_be_inherited_over_multiple_levels
|
84
|
+
class_with_inherited_name = Class.new(Class.new(ParentOfNamedChild))
|
85
|
+
assert_equal :parent, class_with_inherited_name.tag_name
|
86
|
+
end
|
87
|
+
|
78
88
|
def test_named_books_picked_up
|
79
89
|
named = Library.from_xml(fixture(:library))
|
80
90
|
assert named.books
|
@@ -95,14 +105,27 @@ class TestXMLName < Test::Unit::TestCase
|
|
95
105
|
end
|
96
106
|
|
97
107
|
def test_tag_refs
|
98
|
-
assert_equal 'definition', DictionaryOfTexts.
|
99
|
-
assert_equal 'word', DictionaryOfTexts.
|
100
|
-
assert_equal 'meaning', DictionaryOfTexts.
|
108
|
+
assert_equal 'definition', DictionaryOfTexts.tag_refs_without_deprecation.only.name
|
109
|
+
assert_equal 'word', DictionaryOfTexts.tag_refs_without_deprecation.only.hash.key.name
|
110
|
+
assert_equal 'meaning', DictionaryOfTexts.tag_refs_without_deprecation.only.hash.value.name
|
101
111
|
|
102
112
|
dict = DictionaryOfTexts.from_xml(fixture(:dictionary_of_texts))
|
103
113
|
|
104
|
-
assert_equal 'definition', dict.
|
105
|
-
assert_equal 'word', dict.
|
106
|
-
assert_equal 'meaning', dict.
|
114
|
+
assert_equal 'definition', dict.tag_refs_without_deprecation.only.name
|
115
|
+
assert_equal 'word', dict.tag_refs_without_deprecation.only.hash.key.name
|
116
|
+
assert_equal 'meaning', dict.tag_refs_without_deprecation.only.hash.value.name
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_roxml_attrs
|
120
|
+
assert_equal 'definition', DictionaryOfTexts.roxml_attrs.only.name
|
121
|
+
assert_equal 'word', DictionaryOfTexts.roxml_attrs.only.hash.key.name
|
122
|
+
assert_equal 'meaning', DictionaryOfTexts.roxml_attrs.only.hash.value.name
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_xml_name_query_is_deprecated
|
126
|
+
# This query should go when the XML_NAME_WARNING stuff goes
|
127
|
+
assert_deprecated do
|
128
|
+
NamedChild.xml_name?
|
129
|
+
end
|
107
130
|
end
|
108
131
|
end
|
@@ -1,5 +1,21 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
|
+
class EmptyCart
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_reader :id
|
7
|
+
|
8
|
+
def empty?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class CartHolder
|
14
|
+
include ROXML
|
15
|
+
|
16
|
+
xml_reader :cart, EmptyCart, :required => true
|
17
|
+
end
|
18
|
+
|
3
19
|
class TestXMLObject < Test::Unit::TestCase
|
4
20
|
# Test book with text and attribute
|
5
21
|
def test_book_author_text_attribute
|
@@ -113,4 +129,18 @@ class TestXMLObject < Test::Unit::TestCase
|
|
113
129
|
assert_equal 'Unknown', p.mother.mother.mother.name
|
114
130
|
assert_equal Person, p.mother.mother.mother.class
|
115
131
|
end
|
132
|
+
|
133
|
+
def test_defining_empty_on_object_doesnt_cause_it_to_be_seen_as_absent
|
134
|
+
# absent means defaulting, failing required
|
135
|
+
|
136
|
+
holder = CartHolder.from_xml(%{
|
137
|
+
<cartholder>
|
138
|
+
<cart>
|
139
|
+
<id>111111</id>
|
140
|
+
</cart>
|
141
|
+
</cartholder>
|
142
|
+
})
|
143
|
+
|
144
|
+
assert_equal "111111", holder.cart.id
|
145
|
+
end
|
116
146
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
OverrideRakeTask plugin by Eugene Bolshakov, eugene.bolshakov@gmail.com, http://www.taknado.com
|
2
|
+
|
3
|
+
This plugin is based on the Matthew Bass's idea described here:
|
4
|
+
http://matthewbass.com/2007/03/07/overriding-existing-rake-tasks/
|
5
|
+
|
6
|
+
The installation script is based on the one found in the app_config plugin
|
7
|
+
by Daniel Owsianski, http://jarmark.org/projects/app-config/
|
8
|
+
|
9
|
+
When using rake with rails it loads the task in the following order:
|
10
|
+
|
11
|
+
1. Default rails tasks (like db:migrate)
|
12
|
+
2. The tasks in your app's lib/tasks directory
|
13
|
+
3. The tasks in your vendor/plugins directory
|
14
|
+
|
15
|
+
This plugin will allow to override rake tasks that were defined earlier. It means that
|
16
|
+
you'll be able to override default rails tasks with lib/tasks & plugins tasks and
|
17
|
+
override the taksks in lib/tasks with the tasks defined in plugins.
|
18
|
+
|
19
|
+
In order to override a task you need to define it as usual, but using "override_task"
|
20
|
+
method instead of "task":
|
21
|
+
|
22
|
+
namespace :db do
|
23
|
+
override_task :migrate do
|
24
|
+
...
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
In order to make this work the plugin should be loaded before the tasks and the install script
|
29
|
+
supplied with the plugin adds a line to load itself to the Rakefile. If it won't be able to
|
30
|
+
modify your Rakefile, it will let you know and you'll have to modify it manually.
|
@@ -0,0 +1 @@
|
|
1
|
+
# Include hook code here
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Insert line: [require "#{RAILS_ROOT}/vendor/plugins/override_rake_task/lib/override_rake_task.rb"]
|
2
|
+
# before "require 'rake'" in Rakefile
|
3
|
+
# stolen from app_confing plugin :) http://jarmark.org/projects/app-config/
|
4
|
+
|
5
|
+
file = File.join(File.dirname(__FILE__), '../../../Rakefile')
|
6
|
+
unless File.exists?(file)
|
7
|
+
STDERR.puts("ERROR: Could not locate Rakefile")
|
8
|
+
exit(1)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Tip from http://pleac.sourceforge.net/pleac_ruby/fileaccess.html
|
12
|
+
# 'Modifying a File in Place Without a Temporary File'
|
13
|
+
output= ""
|
14
|
+
inserted = false
|
15
|
+
line_to_insert = %q{require "#{RAILS_ROOT}/vendor/plugins/override_rake_task/lib/override_rake_task.rb"}
|
16
|
+
line_to_find = "require 'rake'"
|
17
|
+
|
18
|
+
File.open(file, 'r+') do |f| # open file for update
|
19
|
+
# read into array of lines and iterate through lines
|
20
|
+
f.readlines.each do |line|
|
21
|
+
unless inserted
|
22
|
+
if line.gsub(/#.*/, '').include?(line_to_insert)
|
23
|
+
inserted = true
|
24
|
+
elsif line.gsub(/#.*/, '').include?(line_to_find)
|
25
|
+
output << line_to_insert
|
26
|
+
output << "\n\n"
|
27
|
+
inserted = true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
output << line
|
31
|
+
end
|
32
|
+
f.pos = 0 # back to start
|
33
|
+
f.print output # write out modified lines
|
34
|
+
f.truncate(f.pos) # truncate to new length
|
35
|
+
end
|
36
|
+
|
37
|
+
unless inserted
|
38
|
+
STDERR.puts <<END
|
39
|
+
ERROR: Could not update Rakefile
|
40
|
+
To finish installation please add the following line to
|
41
|
+
Rakefile manually:
|
42
|
+
\t#{line_to_insert}
|
43
|
+
NOTE: line must be inserted before #{line_to_find}
|
44
|
+
END
|
45
|
+
exit(1)
|
46
|
+
end
|