xing-backend 0.0.19 → 0.0.20
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 +4 -4
- data/app/models/role.rb +24 -0
- data/config/locales/json.yml +29 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20140828011806_initial.rb +45 -0
- data/db/migrate/20140914030703_devise_token_auth_add_token_info_to_users.rb +20 -0
- data/db/migrate/20140929192921_remove_login_from_users.rb +5 -0
- data/lib/xing-backend.rb +1 -0
- data/lib/xing/engine.rb +4 -0
- data/lib/xing/nominal/database_config_validator.rb +31 -0
- data/lib/xing/nominal/dependency_utils.rb +26 -0
- data/lib/xing/nominal/secrets_validator.rb +50 -0
- data/lib/xing/nominal/yaml_config_validator.rb +44 -0
- data/lib/xing/services.rb +0 -2
- data/lib/xing/services/class_registry.rb +31 -0
- data/lib/xing/services/{page_wrapper.rb → paged_wrapper.rb} +2 -2
- data/lib/xing/snapshot.rb +4 -0
- data/lib/xing/snapshot/domain_helpers.rb +24 -0
- data/lib/xing/snapshot/fetcher.rb +35 -0
- data/lib/xing/snapshot/local_site_snapshot.rb +37 -0
- data/lib/xing/snapshot/remote_site_snapshot.rb +16 -0
- data/lib/xing/snapshot/site_page_set.rb +29 -0
- data/lib/xing/snapshot/site_snapshot.rb +41 -0
- data/lib/xing/snapshot/sitemap.rb +68 -0
- data/lib/xing/snapshot/writer.rb +15 -0
- data/lib/xing/spec_helpers.rb +7 -0
- data/lib/xing/spec_helpers/api_response_matchers.rb +26 -0
- data/lib/xing/spec_helpers/ci_support.rb +6 -0
- data/lib/xing/spec_helpers/dom_equiv.rb +26 -0
- data/lib/xing/spec_helpers/json_requests.rb +58 -0
- data/lib/xing/spec_helpers/routing_spec_patch.rb +28 -0
- data/lib/xing/spec_helpers/split_servers.rb +15 -0
- data/lib/xing/spec_helpers/test_url_helpers.rb +5 -0
- data/lib/xing/static.rb +1 -0
- data/lib/xing/static/backend_url_cookie.rb +16 -0
- data/lib/xing/static/goto_param.rb +30 -0
- data/lib/xing/static/logger.rb +11 -0
- data/lib/xing/static/rack_app.rb +40 -0
- data/lib/xing/tasks/all.rake +4 -0
- data/lib/xing/tasks/db_recycle.rake +4 -0
- data/lib/xing/tasks/dependencies_common.rake +49 -0
- data/lib/xing/tasks/sample_data.rake +49 -0
- data/lib/xing/tasks/take_snapshot.rake +4 -0
- data/spec/xing/builders/list_builder_spec.rb +0 -2
- data/spec/xing/builders/ordered_list_builder_spec.rb +0 -2
- data/spec/xing/nominal/database_config_validator_spec.rb +98 -0
- data/spec/xing/nominal/secrets_validator_spec.rb +78 -0
- data/spec/xing/serializers/list_spec.rb +116 -0
- data/spec/xing/serializers/paged_index_spec.rb +2 -2
- data/spec/xing/serializers/paged_list_spec.rb +1 -1
- data/spec/xing/services/error_converter_spec.rb +1 -3
- data/spec/xing/services/paged_wrapper_spec.rb +30 -0
- data/spec/xing/snapshot/remote_snapshot_fetcher_spec.rb +81 -0
- data/spec/xing/{services → snapshot}/snapshot_fetcher_spec.rb +6 -4
- data/spec_help/dummy/db/test.sqlite3 +0 -0
- data/spec_help/dummy/log/test.log +143 -0
- data/spec_help/file-sandbox.rb +164 -0
- data/spec_help/spec_helper.rb +0 -2
- metadata +152 -12
- data/lib/xing/services/snapshot_fetcher.rb +0 -33
- data/lib/xing/services/snapshot_writer.rb +0 -19
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'xing/serializers/paged_index'
|
2
|
-
require 'xing/services/
|
2
|
+
require 'xing/services/paged_wrapper'
|
3
3
|
|
4
4
|
describe Xing::Serializers::PagedIndex do
|
5
5
|
class PageIndexSerializer < Xing::Serializers::PagedIndex
|
@@ -39,7 +39,7 @@ describe Xing::Serializers::PagedIndex do
|
|
39
39
|
|
40
40
|
describe 'as_json' do
|
41
41
|
let :serializer do
|
42
|
-
PageIndexSerializer.new(Xing::Services::
|
42
|
+
PageIndexSerializer.new(Xing::Services::PagedWrapper.new(list, page_num, total_items, per_page))
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should generate a JSON with the proper links and self" do
|
@@ -42,7 +42,7 @@ describe Xing::Serializers::PagedList do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
let :serializer do
|
45
|
-
PageSerializer.new(Xing::Services::
|
45
|
+
PageSerializer.new(Xing::Services::PagedWrapper.new(list, page_num, total_items, per_page))
|
46
46
|
end
|
47
47
|
|
48
48
|
let :json do
|
@@ -10,9 +10,7 @@ describe Xing::Services::ErrorConverter do
|
|
10
10
|
before do
|
11
11
|
# ensure that I18n can find the translation file needed for error
|
12
12
|
# conversions
|
13
|
-
I18n.load_path += Dir[File.join(File.dirname(__FILE__),'../../..', 'config', 'locales', '*.{rb,yml}')
|
14
|
-
puts dirn
|
15
|
-
end]
|
13
|
+
I18n.load_path += Dir[File.join(File.dirname(__FILE__),'../../..', 'config', 'locales', '*.{rb,yml}')]
|
16
14
|
end
|
17
15
|
|
18
16
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'xing/services/paged_wrapper'
|
2
|
+
|
3
|
+
describe Xing::Services::PagedWrapper do
|
4
|
+
let :list do
|
5
|
+
[ :a, :b, :c ]
|
6
|
+
end
|
7
|
+
|
8
|
+
let :per_page do
|
9
|
+
3
|
10
|
+
end
|
11
|
+
|
12
|
+
let :total_items do
|
13
|
+
14
|
14
|
+
end
|
15
|
+
|
16
|
+
let :page_num do
|
17
|
+
2
|
18
|
+
end
|
19
|
+
|
20
|
+
subject :wrapper do
|
21
|
+
Xing::Services::PagedWrapper.new(list, page_num, total_items, per_page)
|
22
|
+
end
|
23
|
+
|
24
|
+
it{ expect(subject.current_page).to eq(page_num) }
|
25
|
+
it{ expect(subject.total_count).to eq(total_items) }
|
26
|
+
it{ expect(subject.limit_value).to eq(per_page) }
|
27
|
+
|
28
|
+
it{ expect(subject.total_pages).to eq(5) }
|
29
|
+
it{ expect(subject.map(&:to_s)).to eq(%w[a b c])}
|
30
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'xing/snapshot/fetcher'
|
2
|
+
require 'file-sandbox'
|
3
|
+
|
4
|
+
describe Xing::Snapshot::Fetcher do
|
5
|
+
include FileSandbox
|
6
|
+
|
7
|
+
let :server_secrets do
|
8
|
+
{ 'url' => 'http://snapshot-server.com',
|
9
|
+
'user' => 'foobar',
|
10
|
+
'password' => 'my_password'
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(Rails).to receive_message_chain(:application, :secrets, :snapshot_server).and_return(server_secrets)
|
16
|
+
allow(Rails).to receive(:root).and_return(@sandbox.root)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "if remote succeeds" do
|
20
|
+
before do
|
21
|
+
begin
|
22
|
+
#FileUtils.mkdir_p("#{ Rails.root }/spec/fixtures/sitemap_scratch")
|
23
|
+
#File.delete("#{ Rails.root }/spec/fixtures/sitemap_scratch/test.html")
|
24
|
+
rescue
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# This feels like way too much mocking, but dont know how to test without
|
29
|
+
# completely
|
30
|
+
# turning off selenium
|
31
|
+
before do
|
32
|
+
response = Typhoeus::Response.new(code: 200, body: "some html content")
|
33
|
+
Typhoeus.stub(server_secrets['url']).and_return(response)
|
34
|
+
expect(Typhoeus::Request).to receive(:new).with(
|
35
|
+
server_secrets['url'],
|
36
|
+
:userpwd => "#{server_secrets['user']}:#{server_secrets['password']}",
|
37
|
+
:params => { :url => "http://www.awesome.com/test" }
|
38
|
+
).and_call_original
|
39
|
+
end
|
40
|
+
|
41
|
+
subject :remote_snapshot_fetcher do
|
42
|
+
Xing::Snapshot::Fetcher.new
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should read html contents from remote server and output to the file" do
|
46
|
+
remote_snapshot_fetcher.perform("http://www.awesome.com", "test")
|
47
|
+
content = File.read("public/frontend_snapshots/test.html")
|
48
|
+
expect(content).to eq("some html content")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "if remote fails" do
|
53
|
+
before do
|
54
|
+
response = Typhoeus::Response.new(code: 500, status_message: "failed", body: "a backtrace")
|
55
|
+
Typhoeus.stub(server_secrets['url']).and_return(response)
|
56
|
+
expect(Typhoeus::Request).to receive(:new).with(
|
57
|
+
server_secrets['url'],
|
58
|
+
:userpwd => "#{server_secrets['user']}:#{server_secrets['password']}",
|
59
|
+
:params => { :url => "http://www.awesome.com/test" }
|
60
|
+
).and_call_original
|
61
|
+
end
|
62
|
+
|
63
|
+
let :logger do
|
64
|
+
double("Logger")
|
65
|
+
end
|
66
|
+
|
67
|
+
subject :remote_snapshot_fetcher do
|
68
|
+
Xing::Snapshot::Fetcher.new.tap do |fetcher|
|
69
|
+
allow(fetcher).to receive(:logger).and_return(logger)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should read html contents from remote server and output to the file" do
|
74
|
+
expect(logger).to receive(:warn).with(/failed/)
|
75
|
+
expect(logger).to receive(:warn).with(/a backtrace/)
|
76
|
+
expect do
|
77
|
+
remote_snapshot_fetcher.perform("http://www.awesome.com", "test")
|
78
|
+
end.to raise_error(/Query.*failed/)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -1,8 +1,10 @@
|
|
1
|
-
require 'xing/
|
2
|
-
require '
|
1
|
+
require 'xing/snapshot/fetcher'
|
2
|
+
require 'file-sandbox'
|
3
3
|
|
4
4
|
|
5
|
-
describe Xing::
|
5
|
+
describe Xing::Snapshot::Fetcher do
|
6
|
+
include FileSandbox
|
7
|
+
|
6
8
|
let :server_secrets do
|
7
9
|
{ 'url' => 'http://snapshot-server.com',
|
8
10
|
'user' => 'foobar',
|
@@ -13,7 +15,7 @@ describe Xing::Services::SnapshotFetcher do
|
|
13
15
|
let :mock_request do double('request') end
|
14
16
|
let :mock_response do double('a response') end
|
15
17
|
let :fetcher do
|
16
|
-
Xing::
|
18
|
+
Xing::Snapshot::Fetcher.new
|
17
19
|
end
|
18
20
|
|
19
21
|
before do
|
File without changes
|
@@ -0,0 +1,143 @@
|
|
1
|
+
ETHON: Libcurl initialized
|
2
|
+
ETHON: started MULTI
|
3
|
+
ETHON: performed MULTI
|
4
|
+
ETHON: Libcurl initialized
|
5
|
+
ETHON: started MULTI
|
6
|
+
ETHON: performed MULTI
|
7
|
+
ETHON: started MULTI
|
8
|
+
ETHON: performed MULTI
|
9
|
+
ETHON: Libcurl initialized
|
10
|
+
ETHON: started MULTI
|
11
|
+
ETHON: performed MULTI
|
12
|
+
ETHON: started MULTI
|
13
|
+
ETHON: performed MULTI
|
14
|
+
ETHON: Libcurl initialized
|
15
|
+
ETHON: started MULTI
|
16
|
+
ETHON: performed MULTI
|
17
|
+
ETHON: started MULTI
|
18
|
+
ETHON: performed MULTI
|
19
|
+
ETHON: Libcurl initialized
|
20
|
+
ETHON: started MULTI
|
21
|
+
ETHON: performed MULTI
|
22
|
+
ETHON: started MULTI
|
23
|
+
ETHON: performed MULTI
|
24
|
+
ETHON: Libcurl initialized
|
25
|
+
ETHON: started MULTI
|
26
|
+
ETHON: performed MULTI
|
27
|
+
ETHON: started MULTI
|
28
|
+
ETHON: performed MULTI
|
29
|
+
ETHON: Libcurl initialized
|
30
|
+
ETHON: started MULTI
|
31
|
+
ETHON: performed MULTI
|
32
|
+
ETHON: started MULTI
|
33
|
+
ETHON: performed MULTI
|
34
|
+
ETHON: Libcurl initialized
|
35
|
+
ETHON: started MULTI
|
36
|
+
ETHON: performed MULTI
|
37
|
+
ETHON: started MULTI
|
38
|
+
ETHON: performed MULTI
|
39
|
+
ETHON: Libcurl initialized
|
40
|
+
ETHON: started MULTI
|
41
|
+
ETHON: performed MULTI
|
42
|
+
ETHON: started MULTI
|
43
|
+
ETHON: performed MULTI
|
44
|
+
ETHON: Libcurl initialized
|
45
|
+
ETHON: started MULTI
|
46
|
+
ETHON: performed MULTI
|
47
|
+
ETHON: started MULTI
|
48
|
+
ETHON: performed MULTI
|
49
|
+
ETHON: Libcurl initialized
|
50
|
+
ETHON: started MULTI
|
51
|
+
ETHON: performed MULTI
|
52
|
+
ETHON: started MULTI
|
53
|
+
ETHON: performed MULTI
|
54
|
+
ETHON: Libcurl initialized
|
55
|
+
ETHON: started MULTI
|
56
|
+
ETHON: performed MULTI
|
57
|
+
ETHON: started MULTI
|
58
|
+
ETHON: performed MULTI
|
59
|
+
ETHON: Libcurl initialized
|
60
|
+
ETHON: started MULTI
|
61
|
+
ETHON: performed MULTI
|
62
|
+
ETHON: started MULTI
|
63
|
+
ETHON: performed MULTI
|
64
|
+
ETHON: Libcurl initialized
|
65
|
+
ETHON: started MULTI
|
66
|
+
ETHON: performed MULTI
|
67
|
+
ETHON: started MULTI
|
68
|
+
ETHON: performed MULTI
|
69
|
+
ETHON: Libcurl initialized
|
70
|
+
ETHON: started MULTI
|
71
|
+
ETHON: performed MULTI
|
72
|
+
ETHON: started MULTI
|
73
|
+
ETHON: performed MULTI
|
74
|
+
ETHON: Libcurl initialized
|
75
|
+
ETHON: started MULTI
|
76
|
+
ETHON: performed MULTI
|
77
|
+
ETHON: started MULTI
|
78
|
+
ETHON: performed MULTI
|
79
|
+
ETHON: Libcurl initialized
|
80
|
+
ETHON: started MULTI
|
81
|
+
ETHON: performed MULTI
|
82
|
+
ETHON: started MULTI
|
83
|
+
ETHON: performed MULTI
|
84
|
+
ETHON: Libcurl initialized
|
85
|
+
ETHON: started MULTI
|
86
|
+
ETHON: performed MULTI
|
87
|
+
ETHON: started MULTI
|
88
|
+
ETHON: performed MULTI
|
89
|
+
ETHON: Libcurl initialized
|
90
|
+
ETHON: started MULTI
|
91
|
+
ETHON: performed MULTI
|
92
|
+
ETHON: started MULTI
|
93
|
+
ETHON: performed MULTI
|
94
|
+
ETHON: Libcurl initialized
|
95
|
+
ETHON: started MULTI
|
96
|
+
ETHON: performed MULTI
|
97
|
+
ETHON: started MULTI
|
98
|
+
ETHON: performed MULTI
|
99
|
+
ETHON: Libcurl initialized
|
100
|
+
ETHON: started MULTI
|
101
|
+
ETHON: performed MULTI
|
102
|
+
ETHON: started MULTI
|
103
|
+
ETHON: performed MULTI
|
104
|
+
ETHON: Libcurl initialized
|
105
|
+
ETHON: started MULTI
|
106
|
+
ETHON: performed MULTI
|
107
|
+
ETHON: started MULTI
|
108
|
+
ETHON: performed MULTI
|
109
|
+
ETHON: Libcurl initialized
|
110
|
+
ETHON: started MULTI
|
111
|
+
ETHON: performed MULTI
|
112
|
+
ETHON: started MULTI
|
113
|
+
ETHON: performed MULTI
|
114
|
+
ETHON: Libcurl initialized
|
115
|
+
ETHON: started MULTI
|
116
|
+
ETHON: performed MULTI
|
117
|
+
ETHON: started MULTI
|
118
|
+
ETHON: performed MULTI
|
119
|
+
ETHON: Libcurl initialized
|
120
|
+
ETHON: started MULTI
|
121
|
+
ETHON: performed MULTI
|
122
|
+
ETHON: started MULTI
|
123
|
+
ETHON: performed MULTI
|
124
|
+
ETHON: Libcurl initialized
|
125
|
+
ETHON: started MULTI
|
126
|
+
ETHON: performed MULTI
|
127
|
+
ETHON: started MULTI
|
128
|
+
ETHON: performed MULTI
|
129
|
+
ETHON: Libcurl initialized
|
130
|
+
ETHON: started MULTI
|
131
|
+
ETHON: performed MULTI
|
132
|
+
ETHON: started MULTI
|
133
|
+
ETHON: performed MULTI
|
134
|
+
ETHON: Libcurl initialized
|
135
|
+
ETHON: started MULTI
|
136
|
+
ETHON: performed MULTI
|
137
|
+
ETHON: started MULTI
|
138
|
+
ETHON: performed MULTI
|
139
|
+
ETHON: Libcurl initialized
|
140
|
+
ETHON: started MULTI
|
141
|
+
ETHON: performed MULTI
|
142
|
+
ETHON: started MULTI
|
143
|
+
ETHON: performed MULTI
|
@@ -0,0 +1,164 @@
|
|
1
|
+
#require 'ftools'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module FileSandbox
|
5
|
+
def self.included(spec)
|
6
|
+
return unless spec.respond_to? :before
|
7
|
+
|
8
|
+
spec.before do
|
9
|
+
setup_sandbox
|
10
|
+
end
|
11
|
+
|
12
|
+
spec.after do
|
13
|
+
teardown_sandbox
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class HaveContents
|
18
|
+
def initialize(contents)
|
19
|
+
@contents = contents
|
20
|
+
end
|
21
|
+
|
22
|
+
def matches?(target)
|
23
|
+
case @contents
|
24
|
+
when Regexp
|
25
|
+
@contents =~ target.contents
|
26
|
+
when String
|
27
|
+
@contents == target.contents
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def have_contents(expected)
|
33
|
+
HaveContents.new(expected)
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :sandbox
|
37
|
+
|
38
|
+
def in_sandbox(&block)
|
39
|
+
raise "I expected to create a sandbox as you passed in a block to me" if !block_given?
|
40
|
+
|
41
|
+
setup_sandbox
|
42
|
+
original_error = nil
|
43
|
+
|
44
|
+
begin
|
45
|
+
yield @sandbox
|
46
|
+
rescue => e
|
47
|
+
original_error = e
|
48
|
+
raise
|
49
|
+
ensure
|
50
|
+
begin
|
51
|
+
teardown_sandbox
|
52
|
+
rescue
|
53
|
+
if original_error
|
54
|
+
STDERR.puts "ALERT: a test raised an error and failed to release some lock(s) in the sandbox directory"
|
55
|
+
raise(original_error)
|
56
|
+
else
|
57
|
+
raise
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup_sandbox(path = '__sandbox')
|
64
|
+
unless @sandbox
|
65
|
+
@sandbox = Sandbox.new(path)
|
66
|
+
@__old_path_for_sandbox = Dir.pwd
|
67
|
+
Dir.chdir(@sandbox.root)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def teardown_sandbox
|
72
|
+
if @sandbox
|
73
|
+
Dir.chdir(@__old_path_for_sandbox)
|
74
|
+
@sandbox.clean_up
|
75
|
+
@sandbox = nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Sandbox
|
80
|
+
attr_reader :root
|
81
|
+
|
82
|
+
def initialize(path = '__sandbox')
|
83
|
+
@root = File.expand_path(path)
|
84
|
+
clean_up
|
85
|
+
FileUtils.mkdir_p @root
|
86
|
+
end
|
87
|
+
|
88
|
+
def [](name)
|
89
|
+
SandboxFile.new(File.join(@root, name), name)
|
90
|
+
end
|
91
|
+
|
92
|
+
# usage new :file=>'my file.rb', :with_contents=>'some stuff'
|
93
|
+
def new(options)
|
94
|
+
if options.has_key? :directory
|
95
|
+
dir = self[options.delete(:directory)]
|
96
|
+
FileUtils.mkdir_p dir.path
|
97
|
+
else
|
98
|
+
file = self[options.delete(:file)]
|
99
|
+
if (binary_content = options.delete(:with_binary_content) || options.delete(:with_binary_contents))
|
100
|
+
file.binary_content = binary_content
|
101
|
+
else
|
102
|
+
file.content = (options.delete(:with_content) || options.delete(:with_contents) || '')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
raise "unexpected keys '#{options.keys.join(', ')}'" unless options.empty?
|
107
|
+
|
108
|
+
dir || file
|
109
|
+
end
|
110
|
+
|
111
|
+
def remove(options)
|
112
|
+
name = File.join(@root, options[:file])
|
113
|
+
FileUtils.remove_file name
|
114
|
+
end
|
115
|
+
|
116
|
+
def clean_up
|
117
|
+
FileUtils.rm_rf @root
|
118
|
+
if File.exists? @root
|
119
|
+
raise "Could not remove directory #{@root.inspect}, something is probably still holding a lock on it"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
class SandboxFile
|
126
|
+
attr_reader :path
|
127
|
+
|
128
|
+
def initialize(path, sandbox_path)
|
129
|
+
@path = path
|
130
|
+
@sandbox_path = sandbox_path
|
131
|
+
end
|
132
|
+
|
133
|
+
def inspect
|
134
|
+
"SandboxFile: #@sandbox_path"
|
135
|
+
end
|
136
|
+
|
137
|
+
def exist?
|
138
|
+
File.exist? path
|
139
|
+
end
|
140
|
+
|
141
|
+
def content
|
142
|
+
File.read path
|
143
|
+
end
|
144
|
+
|
145
|
+
def content=(content)
|
146
|
+
FileUtils.mkdir_p File.dirname(@path)
|
147
|
+
File.open(@path, "w") {|f| f << content}
|
148
|
+
end
|
149
|
+
|
150
|
+
def binary_content=(content)
|
151
|
+
FileUtils.mkdir_p File.dirname(@path)
|
152
|
+
File.open(@path, "wb") {|f| f << content}
|
153
|
+
end
|
154
|
+
|
155
|
+
def create
|
156
|
+
self.content = ''
|
157
|
+
end
|
158
|
+
|
159
|
+
alias exists? exist?
|
160
|
+
alias contents content
|
161
|
+
alias contents= content=
|
162
|
+
alias binary_contents= binary_content=
|
163
|
+
end
|
164
|
+
end
|