movable_erb 0.2.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/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
|
+
|