movable_erb 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/LICENSE +22 -0
- data/Manifest +21 -0
- data/README.rdoc +75 -0
- data/Rakefile +17 -0
- data/bin/movable_erb +37 -0
- data/cucumber.yml +1 -0
- data/features/csv.feature +40 -0
- data/features/step_definitions/csv_steps.rb +14 -0
- data/features/step_definitions/tmp.csv +4 -0
- data/features/support/env.rb +20 -0
- data/lib/movable_erb.rb +129 -0
- data/lib/templates/mtimport.erb +22 -0
- data/movable_erb.gemspec +41 -0
- data/spec/csv_spec.rb +289 -0
- data/spec/fixtures/advanced.csv +3 -0
- data/spec/fixtures/example.csv +5 -0
- data/spec/fixtures/template.erb +4 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +7 -0
- data/tasks/rspec.rake +11 -0
- metadata +115 -0
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
== The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2009
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
LICENSE
|
3
|
+
Manifest
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
bin/movable_erb
|
7
|
+
cucumber.yml
|
8
|
+
features/csv.feature
|
9
|
+
features/step_definitions/csv_steps.rb
|
10
|
+
features/step_definitions/tmp.csv
|
11
|
+
features/support/env.rb
|
12
|
+
lib/movable_erb.rb
|
13
|
+
lib/templates/mtimport.erb
|
14
|
+
movable_erb.gemspec
|
15
|
+
spec/csv_spec.rb
|
16
|
+
spec/fixtures/advanced.csv
|
17
|
+
spec/fixtures/example.csv
|
18
|
+
spec/fixtures/template.erb
|
19
|
+
spec/spec.opts
|
20
|
+
spec/spec_helper.rb
|
21
|
+
tasks/rspec.rake
|
data/README.rdoc
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
= Movable Erb
|
2
|
+
|
3
|
+
by Joshua Davey
|
4
|
+
http://github.com/jgdavey/movable_erb
|
5
|
+
|
6
|
+
== Description
|
7
|
+
|
8
|
+
A simple CSV to MTImport conversion utility.
|
9
|
+
Useful for mapping contacts data into individual entries in Movable Type.
|
10
|
+
|
11
|
+
MTImport format is simple enough that most blogging platforms can import it, so this utility could ease the pain of moving some older data structure in CSV format into a blog platform.
|
12
|
+
|
13
|
+
== Requirements
|
14
|
+
|
15
|
+
* fastercsv gem
|
16
|
+
|
17
|
+
== Installation
|
18
|
+
|
19
|
+
[sudo] gem install jgdavey-movable_erb
|
20
|
+
|
21
|
+
== Usage
|
22
|
+
|
23
|
+
MovableErb uses the header names in the first row of
|
24
|
+
the CSV file to map to each of the mtimport’s values:
|
25
|
+
Title, Body, Extended, Category, and Tags.
|
26
|
+
|
27
|
+
So, a CSV file that looks like:
|
28
|
+
Title,Body,Extended
|
29
|
+
Title of a Post,Body content (can include html, etc),Extended content
|
30
|
+
|
31
|
+
will become:
|
32
|
+
TITLE: Title of a Post
|
33
|
+
-----
|
34
|
+
BODY:
|
35
|
+
|
36
|
+
Body content (can include html, etc)
|
37
|
+
|
38
|
+
-----
|
39
|
+
EXTENDED:
|
40
|
+
|
41
|
+
Extended content
|
42
|
+
|
43
|
+
You can even specify more than one header column as Title, Body, etc.,
|
44
|
+
and they will be combined into one entity, joined by:
|
45
|
+
* a comma for one-line attributes (title, author), or
|
46
|
+
* a newline for multi-line (Body, Extended)
|
47
|
+
|
48
|
+
=== Commandline usage
|
49
|
+
After installing the gem, just run
|
50
|
+
|
51
|
+
movable_erb [options] yourfile.csv
|
52
|
+
|
53
|
+
|
54
|
+
== The MIT License
|
55
|
+
|
56
|
+
Copyright (c) 2009
|
57
|
+
|
58
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
59
|
+
a copy of this software and associated documentation files (the
|
60
|
+
'Software'), to deal in the Software without restriction, including
|
61
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
62
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
63
|
+
permit persons to whom the Software is furnished to do so, subject to
|
64
|
+
the following conditions:
|
65
|
+
|
66
|
+
The above copyright notice and this permission notice shall be
|
67
|
+
included in all copies or substantial portions of the Software.
|
68
|
+
|
69
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
70
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
71
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
72
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
73
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
74
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
75
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('movable_erb') do |p|
|
6
|
+
p.description = "A General-purpose CSV to ERB template formatter"
|
7
|
+
p.url = "http://github.com/jgdavey/movable_erb"
|
8
|
+
p.author = "Joshua Davey"
|
9
|
+
p.email = "josh@joshuadavey.com"
|
10
|
+
p.ignore_pattern = ["tmp/*", "script/*", "coverage/*"]
|
11
|
+
p.development_dependencies = ['rspec']
|
12
|
+
p.executable_pattern = ["bin/*"]
|
13
|
+
p.runtime_dependencies = ["fastercsv", "trollop"]
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
17
|
+
|
data/bin/movable_erb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pp'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'trollop'
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib movable_erb]))
|
7
|
+
|
8
|
+
DEFAULT_TEMPLATE = File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib templates mtimport.erb]))
|
9
|
+
|
10
|
+
opts = Trollop::options do
|
11
|
+
|
12
|
+
version "MovableErb v#{MovableErb::VERSION} (c) 2009 Joshua Davey"
|
13
|
+
banner <<-EOS
|
14
|
+
Usage:
|
15
|
+
|
16
|
+
movable_erb [options] <filenames.csv>
|
17
|
+
|
18
|
+
Options:
|
19
|
+
|
20
|
+
EOS
|
21
|
+
|
22
|
+
# Options
|
23
|
+
opt :separator, "Separator between records", :default => "", :short => '-s'
|
24
|
+
opt :template, "path to ERB template", :default => DEFAULT_TEMPLATE, :short => '-t'
|
25
|
+
|
26
|
+
# Show the help screen when no file given
|
27
|
+
educate if ARGV.empty?
|
28
|
+
|
29
|
+
# Only continue if the CSV file is found
|
30
|
+
Trollop::die "That file could not be found" unless ARGV.first && File.exist?(ARGV.first)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Paths for CSV files are left in ARGV
|
34
|
+
ARGV.each do |csv|
|
35
|
+
opts.merge!(:csv => csv)
|
36
|
+
puts MovableErb.new(opts).convert
|
37
|
+
end
|
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: --tags ~wip features
|
@@ -0,0 +1,40 @@
|
|
1
|
+
Feature: CSV Conversion
|
2
|
+
In order to convert my list of contacts to blog format
|
3
|
+
As a Command-line user
|
4
|
+
I want to use commandline utility to convert CSV files to MTImport files
|
5
|
+
|
6
|
+
Scenario: A short CSV of contacts
|
7
|
+
Given I am on the commandline
|
8
|
+
When I invoke the utility with the following CSV file:
|
9
|
+
"""
|
10
|
+
Title,Body,Body
|
11
|
+
John,773-123-1234,john@example.com
|
12
|
+
Abigail,,abby@example.com
|
13
|
+
Bernard,903-294-3921,
|
14
|
+
"""
|
15
|
+
Then I should see the following output:
|
16
|
+
"""
|
17
|
+
TITLE: John
|
18
|
+
-----
|
19
|
+
BODY:
|
20
|
+
|
21
|
+
773-123-1234
|
22
|
+
john@example.com
|
23
|
+
|
24
|
+
--------
|
25
|
+
TITLE: Abigail
|
26
|
+
-----
|
27
|
+
BODY:
|
28
|
+
|
29
|
+
abby@example.com
|
30
|
+
|
31
|
+
--------
|
32
|
+
TITLE: Bernard
|
33
|
+
-----
|
34
|
+
BODY:
|
35
|
+
|
36
|
+
903-294-3921
|
37
|
+
|
38
|
+
--------
|
39
|
+
|
40
|
+
"""
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Given /^I am on the commandline$/ do
|
2
|
+
# dummy step
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I invoke the utility with the following CSV file:?$/ do |string|
|
6
|
+
File.open(File.dirname(__FILE__) + '/tmp.csv', 'w') {|f| f.write(string) }
|
7
|
+
puts FasterCSV.parse(string).inspect
|
8
|
+
@erb = MovableErb.new({:csv => File.dirname(__FILE__) + '/tmp.csv', :separator => ''})
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^I should see the following output:?$/ do |string|
|
12
|
+
puts @erb.csv.to_hashes.inspect
|
13
|
+
@erb.convert.should == string
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. lib movable_erb]))
|
5
|
+
|
6
|
+
require "mocha"
|
7
|
+
|
8
|
+
World(Mocha::API)
|
9
|
+
|
10
|
+
Before do
|
11
|
+
mocha_setup
|
12
|
+
end
|
13
|
+
|
14
|
+
After do
|
15
|
+
begin
|
16
|
+
mocha_verify
|
17
|
+
ensure
|
18
|
+
mocha_teardown
|
19
|
+
end
|
20
|
+
end
|
data/lib/movable_erb.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# @author Joshua Davey
|
2
|
+
# @version 0.2.4
|
3
|
+
class MovableErb
|
4
|
+
VERSION = "0.2.4"
|
5
|
+
attr_accessor :csv, :erb, :separator
|
6
|
+
|
7
|
+
DEFAULT_TEMPLATE = File.expand_path(File.dirname(__FILE__) + '/templates/mtimport.erb')
|
8
|
+
|
9
|
+
##
|
10
|
+
# @param [Hash] options
|
11
|
+
# @option options [String] :template ("mtimport.erb") Path to the ERB template file to use
|
12
|
+
# @option options [String] :csv <b>Required.</b> Path to the CSV file to convert
|
13
|
+
# @option options [String] :separator ("") Defaults to empty String, ""
|
14
|
+
def initialize(options = {})
|
15
|
+
@erb = MovableErb::Erb.setup do |erb|
|
16
|
+
erb.template = options[:template] || DEFAULT_TEMPLATE
|
17
|
+
end
|
18
|
+
if options[:csv]
|
19
|
+
@csv = MovableErb::CSV.setup do |csv|
|
20
|
+
csv.filename = options[:csv]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
@separator = options[:separator] || ""
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Converts each row of the CSV file and collects it into @results
|
28
|
+
# @return [String] parsed results joined by the separator
|
29
|
+
def convert
|
30
|
+
@results = []
|
31
|
+
csv.parse!
|
32
|
+
csv.hashes.each do |hash_data|
|
33
|
+
erb.data = hash_data
|
34
|
+
@results << erb.build!
|
35
|
+
end
|
36
|
+
@results.join(separator)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Loads a CSV document into an array of hashes
|
42
|
+
class MovableErb::CSV
|
43
|
+
require 'fastercsv'
|
44
|
+
|
45
|
+
attr_accessor :filename, :hashes
|
46
|
+
|
47
|
+
##
|
48
|
+
# Initializes and yields a new instance
|
49
|
+
# @yield [csv] a new instance of {MovableErb::CSV}
|
50
|
+
# @return [MovableErb::CSV]
|
51
|
+
def self.setup(&block)
|
52
|
+
csv = self.new
|
53
|
+
yield csv
|
54
|
+
csv.parse!
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Internally calls {#to_hashes}, but returns self
|
59
|
+
# @see to_hashes
|
60
|
+
# @return [MovableErb::CSV] self
|
61
|
+
def parse!
|
62
|
+
@hashes = self.to_hashes
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Reads the CSV file into an array of hashes
|
68
|
+
# @return [Array] an Array of Hashes
|
69
|
+
def to_hashes
|
70
|
+
array_of_arrays = FasterCSV.read(filename)
|
71
|
+
headers = array_of_arrays.shift
|
72
|
+
headers.each { |h| h.downcase! && h.gsub!(/\s/,"_") } if headers
|
73
|
+
hashes = Array.new(array_of_arrays.length) { Hash.new }
|
74
|
+
array_of_arrays.each_with_index do |row,i|
|
75
|
+
headers.each_with_index do |header, j|
|
76
|
+
unless row[j].nil?
|
77
|
+
hashes[i][header] = [] if hashes[i][header].nil?
|
78
|
+
hashes[i][header] << row[j]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
hashes
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Convenience class to setup and parse data with an ERB template.
|
88
|
+
class MovableErb::Erb
|
89
|
+
require 'erb'
|
90
|
+
|
91
|
+
attr_accessor :template, :parsed_string, :data
|
92
|
+
|
93
|
+
##
|
94
|
+
# Creates a new instance and allow manipulation of it via block.
|
95
|
+
#
|
96
|
+
# This can be used to initialize and parse quickly.
|
97
|
+
#
|
98
|
+
# @yield [erb] a new instance of {MovableErb::Erb}
|
99
|
+
#
|
100
|
+
# @example Create a new instance, setup and build the template
|
101
|
+
# @erb = MovableErb::Erb.setup do |erb|
|
102
|
+
# erb.data = {'hash' => 'of', 'meaningful' => 'values'}
|
103
|
+
# erb.template = "path/to/template.erb"
|
104
|
+
# erb.build!
|
105
|
+
# end
|
106
|
+
# @return [MovableErb::Erb]
|
107
|
+
def self.setup
|
108
|
+
erb = self.new
|
109
|
+
yield erb
|
110
|
+
erb
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Sets the template file to use and reads it into a string
|
115
|
+
#
|
116
|
+
# Note: this is required before {#build!} can be called.
|
117
|
+
# @return [String] the unparsed template
|
118
|
+
def template=(template_file)
|
119
|
+
@template = File.read template_file
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Using the specified template, this will parse the template
|
124
|
+
# @return [String] the parsed template
|
125
|
+
def build!
|
126
|
+
erb = ERB.new(template, nil, '<>')
|
127
|
+
@parsed_string = erb.result(binding) if erb
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
TITLE: <%= data['title'].join(', ') if data['title'] %>
|
2
|
+
<% if data['author'] %>
|
3
|
+
AUTHOR: <%= data['author'].join(', ') %>
|
4
|
+
<% end %>
|
5
|
+
<% data['category'] && data['category'].each do |cat| %>
|
6
|
+
CATEGORY: <%= cat %>
|
7
|
+
<% end %>
|
8
|
+
-----
|
9
|
+
BODY:
|
10
|
+
|
11
|
+
<%= data['body'].join("\n") if data['body'] %>
|
12
|
+
|
13
|
+
<% if data['extended_body'] %>
|
14
|
+
|
15
|
+
-----
|
16
|
+
EXTENDED BODY:
|
17
|
+
|
18
|
+
<%= data['extended_body'] %>
|
19
|
+
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
--------
|
data/movable_erb.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{movable_erb}
|
5
|
+
s.version = "0.2.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Joshua Davey"]
|
9
|
+
s.date = %q{2009-10-08}
|
10
|
+
s.default_executable = %q{movable_erb}
|
11
|
+
s.description = %q{A General-purpose CSV to ERB template formatter}
|
12
|
+
s.email = %q{josh@joshuadavey.com}
|
13
|
+
s.executables = ["movable_erb"]
|
14
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "bin/movable_erb", "lib/movable_erb.rb", "lib/templates/mtimport.erb", "tasks/rspec.rake"]
|
15
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.rdoc", "Rakefile", "bin/movable_erb", "cucumber.yml", "features/csv.feature", "features/step_definitions/csv_steps.rb", "features/step_definitions/tmp.csv", "features/support/env.rb", "lib/movable_erb.rb", "lib/templates/mtimport.erb", "movable_erb.gemspec", "spec/csv_spec.rb", "spec/fixtures/advanced.csv", "spec/fixtures/example.csv", "spec/fixtures/template.erb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/rspec.rake"]
|
16
|
+
s.homepage = %q{http://github.com/jgdavey/movable_erb}
|
17
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Movable_erb", "--main", "README.rdoc"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubyforge_project = %q{movable_erb}
|
20
|
+
s.rubygems_version = %q{1.3.5}
|
21
|
+
s.summary = %q{A General-purpose CSV to ERB template formatter}
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_runtime_dependency(%q<fastercsv>, [">= 0"])
|
29
|
+
s.add_runtime_dependency(%q<trollop>, [">= 0"])
|
30
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<fastercsv>, [">= 0"])
|
33
|
+
s.add_dependency(%q<trollop>, [">= 0"])
|
34
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
35
|
+
end
|
36
|
+
else
|
37
|
+
s.add_dependency(%q<fastercsv>, [">= 0"])
|
38
|
+
s.add_dependency(%q<trollop>, [">= 0"])
|
39
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
40
|
+
end
|
41
|
+
end
|
data/spec/csv_spec.rb
ADDED
@@ -0,0 +1,289 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
TEMPLATE_FIXTURE = File.expand_path(File.dirname(__FILE__) + '/fixtures/template.erb')
|
4
|
+
CSV_FIXTURE = File.expand_path(File.dirname(__FILE__) + '/fixtures/example.csv')
|
5
|
+
|
6
|
+
describe MovableErb do
|
7
|
+
it "should have a CSV instance" do
|
8
|
+
m = MovableErb.new
|
9
|
+
m.csv = MovableErb::CSV.setup do |csv|
|
10
|
+
csv.filename = CSV_FIXTURE
|
11
|
+
end.should be_a(MovableErb::CSV)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have an Erb instance" do
|
15
|
+
m = MovableErb.new
|
16
|
+
m.erb = MovableErb::Erb.setup do |erb|
|
17
|
+
true
|
18
|
+
end.should be_a(MovableErb::Erb)
|
19
|
+
end
|
20
|
+
|
21
|
+
context "#convert" do
|
22
|
+
before(:each) do
|
23
|
+
@m = MovableErb.new
|
24
|
+
end
|
25
|
+
it "should raise an error if it's missing a CSV and/or Erb instance" do
|
26
|
+
lambda { @m.convert }.should raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should raise an error if it's CSV instance can't parse!" do
|
30
|
+
@m.erb = MovableErb::Erb.setup { |erb| erb.template = TEMPLATE_FIXTURE }
|
31
|
+
@m.csv = "Random string"
|
32
|
+
lambda { @m.convert }.should raise_error(NoMethodError, "undefined method `parse!' for \"Random string\":String")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should raise an error if it's missing an Erb instance" do
|
36
|
+
String.any_instance.stubs(:data=).returns('')
|
37
|
+
@m.csv = MovableErb::CSV.setup { |csv| csv.filename = CSV_FIXTURE }
|
38
|
+
@m.erb = "Random string"
|
39
|
+
lambda { @m.convert }.should raise_error(NoMethodError, "undefined method `build!' for \"Random string\":String")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should convert the CSV to a string with the Erb template" do
|
43
|
+
@m.csv = MovableErb::CSV.setup { |csv| csv.filename = CSV_FIXTURE }
|
44
|
+
@m.erb = MovableErb::Erb.setup { |erb| erb.template = TEMPLATE_FIXTURE }
|
45
|
+
@m.separator = "\n"
|
46
|
+
@m.convert.should == <<-ERB.gsub(/^ +/, "")
|
47
|
+
Name: John
|
48
|
+
Email: john@example.com
|
49
|
+
|
50
|
+
Name: Abigail
|
51
|
+
Email: abby@example.com
|
52
|
+
|
53
|
+
Name: Bernard
|
54
|
+
|
55
|
+
Name: Casius
|
56
|
+
ERB
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "initilization" do
|
61
|
+
it "should take a hash of options" do
|
62
|
+
m = MovableErb.new({:hash => 'of options'})
|
63
|
+
m.should be_a(MovableErb)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should set the template file" do
|
67
|
+
m = MovableErb.new({ :template => TEMPLATE_FIXTURE })
|
68
|
+
m.erb.template.should == File.read(TEMPLATE_FIXTURE)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should set the csv file" do
|
72
|
+
m = MovableErb.new({ :csv => CSV_FIXTURE })
|
73
|
+
m.csv.filename.should == CSV_FIXTURE
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should set a separator if given" do
|
77
|
+
m = MovableErb.new({ :separator => ', ' })
|
78
|
+
m.separator.should == ', '
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "full-on run-through" do
|
83
|
+
it "should work!" do
|
84
|
+
movable_erb = MovableErb.new({
|
85
|
+
:csv => File.expand_path(File.dirname(__FILE__) + '/fixtures/advanced.csv'),
|
86
|
+
:separator => ''
|
87
|
+
})
|
88
|
+
movable_erb.convert.should == <<-ERB.gsub(/^ +/, "")
|
89
|
+
TITLE: Hambone
|
90
|
+
CATEGORY: Silly
|
91
|
+
CATEGORY: Blah
|
92
|
+
-----
|
93
|
+
BODY:
|
94
|
+
|
95
|
+
This is the content for hambone
|
96
|
+
|
97
|
+
--------
|
98
|
+
TITLE: WillyNilly
|
99
|
+
-----
|
100
|
+
BODY:
|
101
|
+
|
102
|
+
More body
|
103
|
+
|
104
|
+
--------
|
105
|
+
ERB
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe MovableErb::CSV do
|
111
|
+
it "should be an instance of itself" do
|
112
|
+
MovableErb::CSV.new.should be_a(MovableErb::CSV)
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "setup" do
|
116
|
+
before(:each) do
|
117
|
+
@csv = MovableErb::CSV.new
|
118
|
+
end
|
119
|
+
|
120
|
+
context "shortcut setup class method" do
|
121
|
+
before(:each) do
|
122
|
+
MovableErb::CSV.any_instance.stubs(:filename).returns("fake")
|
123
|
+
FasterCSV.stubs(:read).returns([])
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should create a new instance" do
|
127
|
+
MovableErb::CSV.setup do |csv|
|
128
|
+
csv.should be_a(MovableErb::CSV)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should return the new instance" do
|
133
|
+
MovableErb::CSV.setup { |csv| @instance = csv }.should == @instance
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should return the new instance (2)" do
|
137
|
+
MovableErb::CSV.setup do |csv|
|
138
|
+
@instance = csv
|
139
|
+
'fakey fake string'
|
140
|
+
end.should == @instance
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should raise an error if no block given" do
|
144
|
+
lambda { MovableErb::CSV.setup }.should raise_error('no block given')
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should call parse!" do
|
148
|
+
MovableErb::CSV.any_instance.expects(:parse!)
|
149
|
+
MovableErb::CSV.setup { |csv| true }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "parsing" do
|
155
|
+
before(:each) do
|
156
|
+
FasterCSV.stubs(:read).returns([["row1"], ["row2"]])
|
157
|
+
@csv = MovableErb::CSV.new
|
158
|
+
@csv.filename = "test.csv"
|
159
|
+
end
|
160
|
+
|
161
|
+
it "#parse! should return self" do
|
162
|
+
@csv.parse!.should == @csv
|
163
|
+
end
|
164
|
+
|
165
|
+
it "#parse! should modify attribute hashes (via to_hashes)" do
|
166
|
+
@csv.expects(:to_hashes)
|
167
|
+
@csv.parse!
|
168
|
+
end
|
169
|
+
|
170
|
+
context "#to_hashes" do
|
171
|
+
it "should read from file" do
|
172
|
+
FasterCSV.expects(:read).with("test.csv").returns([[]])
|
173
|
+
@csv.to_hashes
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should return an array of hashes (1 rows, 1 column)" do
|
177
|
+
@csv.to_hashes.should == [{'row1' => ['row2']}]
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should downcase the header row" do
|
181
|
+
FasterCSV.stubs(:read).returns([["Name"],["Billy Bob"]])
|
182
|
+
@csv.to_hashes.should == [{'name' => ['Billy Bob']}]
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should convert the header row to snake_case" do
|
186
|
+
FasterCSV.stubs(:read).returns([["Extended Body"],["Billy Bob"]])
|
187
|
+
@csv.to_hashes.should == [{'extended_body' => ['Billy Bob']}]
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should return an array of hashes (3 rows, 3 columns)" do
|
191
|
+
FasterCSV.stubs(:read).returns([["Name", "Phone", "Email"],
|
192
|
+
["John", "773-123-1234", "john@example.com"],
|
193
|
+
["Abigail", nil, "abby@example.com"],
|
194
|
+
["Casius", nil, nil]])
|
195
|
+
@csv.to_hashes.should == [
|
196
|
+
{'name' => ['John'], 'phone' => ['773-123-1234'], 'email' => ['john@example.com'] },
|
197
|
+
{'name' => ['Abigail'], 'email' => ['abby@example.com'] },
|
198
|
+
{'name' => ['Casius'],}
|
199
|
+
]
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should collect values with the same key" do
|
203
|
+
FasterCSV.stubs(:read).returns([["Name", "Name", "Email"], ["John", "James", "john@example.com"]])
|
204
|
+
@csv.to_hashes.should == [{'name' => ['John', 'James'],'email' => ['john@example.com']}]
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should collect values with the same key (more than 2)" do
|
208
|
+
FasterCSV.stubs(:read).returns([["Name", "Name", "Name"], ["John", "James", "Jill"]])
|
209
|
+
@csv.to_hashes.should == [{'name' => ['John', 'James', 'Jill']}]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe MovableErb::Erb do
|
216
|
+
context "initializing" do
|
217
|
+
it "should initialize with a template file" do
|
218
|
+
MovableErb::Erb.new.should be_a(MovableErb::Erb)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context "loading a template" do
|
223
|
+
it "template setter should load a file into @template" do
|
224
|
+
File.expects(:read).with("filename.erb").returns("This is a template")
|
225
|
+
@erb = MovableErb::Erb.new
|
226
|
+
@erb.template = 'filename.erb'
|
227
|
+
@erb.template.should == 'This is a template'
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "data hash" do
|
232
|
+
it "should accept a data hash" do
|
233
|
+
@erb = MovableErb::Erb.new
|
234
|
+
@erb.data = {'these' => 'params'}
|
235
|
+
@erb.data.should == {'these' => 'params'}
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context "shortcut setup class method" do
|
240
|
+
it "should create a new instance" do
|
241
|
+
MovableErb::Erb.setup do |erb|
|
242
|
+
erb.should be_a(MovableErb::Erb)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should return the new instance" do
|
247
|
+
MovableErb::Erb.setup { |erb| @instance = erb }.should == @instance
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should return the new instance (2)" do
|
251
|
+
MovableErb::Erb.setup do |erb|
|
252
|
+
@instance = erb
|
253
|
+
'fakey fake string'
|
254
|
+
end.should == @instance
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should raise an error if no block given" do
|
258
|
+
lambda { MovableErb::Erb.setup }.should raise_error('no block given')
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
context "#build!" do
|
263
|
+
before(:each) do
|
264
|
+
@erb = MovableErb::Erb.new
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should create a new ERB instance with @template" do
|
268
|
+
@erb.stubs(:template).returns("string")
|
269
|
+
ERB.expects(:new)
|
270
|
+
@erb.build!
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should set @parsed_string" do
|
274
|
+
@erb.stubs(:template).returns("string")
|
275
|
+
@erb.build!
|
276
|
+
@erb.parsed_string.should_not be_nil
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should parse a template with data given" do
|
280
|
+
@erb.template = TEMPLATE_FIXTURE
|
281
|
+
@erb.data = {'name' => 'Johnny', 'email' => 'john@example.com'}
|
282
|
+
@erb.build!
|
283
|
+
@erb.parsed_string.should == <<-ERB.gsub(/^\s+/,'')
|
284
|
+
Name: Johnny
|
285
|
+
Email: john@example.com
|
286
|
+
ERB
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
|
3
|
+
namespace :spec do
|
4
|
+
desc "Run all examples with RCov"
|
5
|
+
Spec::Rake::SpecTask.new('rcov') do |t|
|
6
|
+
t.spec_files = FileList['spec']
|
7
|
+
t.spec_opts << ["--color"]
|
8
|
+
t.rcov = true
|
9
|
+
t.rcov_opts = ['--exclude', 'spec/,tasks/,coverage/,features/,/System/,/Library/']
|
10
|
+
end
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: movable_erb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Davey
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-08 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: fastercsv
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: trollop
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: A General-purpose CSV to ERB template formatter
|
46
|
+
email: josh@joshuadavey.com
|
47
|
+
executables:
|
48
|
+
- movable_erb
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- CHANGELOG
|
53
|
+
- LICENSE
|
54
|
+
- README.rdoc
|
55
|
+
- bin/movable_erb
|
56
|
+
- lib/movable_erb.rb
|
57
|
+
- lib/templates/mtimport.erb
|
58
|
+
- tasks/rspec.rake
|
59
|
+
files:
|
60
|
+
- CHANGELOG
|
61
|
+
- LICENSE
|
62
|
+
- Manifest
|
63
|
+
- README.rdoc
|
64
|
+
- Rakefile
|
65
|
+
- bin/movable_erb
|
66
|
+
- cucumber.yml
|
67
|
+
- features/csv.feature
|
68
|
+
- features/step_definitions/csv_steps.rb
|
69
|
+
- features/step_definitions/tmp.csv
|
70
|
+
- features/support/env.rb
|
71
|
+
- lib/movable_erb.rb
|
72
|
+
- lib/templates/mtimport.erb
|
73
|
+
- movable_erb.gemspec
|
74
|
+
- spec/csv_spec.rb
|
75
|
+
- spec/fixtures/advanced.csv
|
76
|
+
- spec/fixtures/example.csv
|
77
|
+
- spec/fixtures/template.erb
|
78
|
+
- spec/spec.opts
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
- tasks/rspec.rake
|
81
|
+
has_rdoc: true
|
82
|
+
homepage: http://github.com/jgdavey/movable_erb
|
83
|
+
licenses: []
|
84
|
+
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options:
|
87
|
+
- --line-numbers
|
88
|
+
- --inline-source
|
89
|
+
- --title
|
90
|
+
- Movable_erb
|
91
|
+
- --main
|
92
|
+
- README.rdoc
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
version:
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: "1.2"
|
106
|
+
version:
|
107
|
+
requirements: []
|
108
|
+
|
109
|
+
rubyforge_project: movable_erb
|
110
|
+
rubygems_version: 1.3.5
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: A General-purpose CSV to ERB template formatter
|
114
|
+
test_files: []
|
115
|
+
|