csverizer 0.0.3
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 +7 -0
- data/.gitignore +24 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +44 -0
- data/Rakefile +6 -0
- data/csverizer.gemspec +30 -0
- data/lib/active_model/csv_array_serializer.rb +30 -0
- data/lib/active_model/csverizer.rb +92 -0
- data/lib/active_model/csverizer/railtie.rb +29 -0
- data/lib/active_model/csverizer/version.rb +5 -0
- data/lib/active_model/csverizer_factory.rb +11 -0
- data/lib/csverizer.rb +6 -0
- data/spec/active_model/array_serializer_spec.rb +34 -0
- data/spec/active_model/attributes_spec.rb +31 -0
- data/spec/active_model/csverizer_factory_spec.rb +23 -0
- data/spec/active_model/has_many_spec.rb +27 -0
- data/spec/active_model/has_one_spec.rb +45 -0
- data/spec/active_model/header_spec.rb +96 -0
- data/spec/renderer_spec.rb +33 -0
- data/spec/spec_helper.rb +95 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f0b54134cdafa0cceebcfb66e35364e0b2b8b9562c181b8690c7c1ee71b8b16f
|
4
|
+
data.tar.gz: 8e59f9151a1159895ba85f7395c7b9de12b1a7263bbb116aec7d9b55ddf35247
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a9baa3fea4c27b1f084ab5b3da09137fe9ffda0b3437ee1f838502e6ac17f3d72833dedee08b4afc415eef5efe8a182f5ac4d6fa08c646a344477dc968b3ed55
|
7
|
+
data.tar.gz: 9b02b2d9dbbd4631af2f205cd2dfe8786be53cd90fd368d0d08c16ed38df70094a3f553e739191fb4800afcc4cf7642b0c0f2af937c1e6b5d4aa8abd09152aad
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
tmp
|
24
|
+
log
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.8
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2015 William Cunningham
|
2
|
+
Copyright (c) 2020 Peter Hankiewicz
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# CSVerizer
|
2
|
+
|
3
|
+
`ActiveModel::Serializers` style CSV serialization.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'csverizer'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install csverizer
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
class Post
|
23
|
+
include ActiveModel::Serialization
|
24
|
+
attr_accessor :title, :body
|
25
|
+
def attributes; end # not necessary for ActiveModel::CSVerizer
|
26
|
+
end
|
27
|
+
|
28
|
+
class PostSerializer < ActiveModel::CSVerizer
|
29
|
+
attributes :title, :body
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
post = Post.new(title: 'Welcome', body: 'Why hello there!')
|
35
|
+
PostSerializer.new(post).to_csv # => "title,body\nWelcome,Why hello there!"
|
36
|
+
```
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
1. Fork it ( https://github.com/[my-github-username]/active_model_csv_serializers/fork )
|
41
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
42
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
43
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
44
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/csverizer.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_model/csverizer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'csverizer'
|
8
|
+
spec.version = ActiveModel::CSVerizer::VERSION
|
9
|
+
spec.authors = ['William Cunningham', 'Peter Hankiewicz']
|
10
|
+
spec.email = ['w.a.cunningham.ii@gmail.com', 'peter.hankiewicz@gmail.com']
|
11
|
+
spec.summary = 'Serialize models as CSV.'
|
12
|
+
spec.description = 'ActiveModel::Serializers style CSV serialization.'
|
13
|
+
spec.homepage = 'https://github.com/peter-hank/csverizer'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 2.2.2'
|
22
|
+
|
23
|
+
spec.add_dependency 'activemodel', '>= 5.1'
|
24
|
+
spec.add_development_dependency 'rails', '>= 5.1'
|
25
|
+
spec.add_development_dependency 'bundler', '>= 1.3'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.7'
|
28
|
+
spec.add_development_dependency 'rspec-rails', '~> 3.7'
|
29
|
+
spec.add_development_dependency 'pry'
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'active_support/inflections'
|
3
|
+
|
4
|
+
module ActiveModel
|
5
|
+
class CsvArraySerializer
|
6
|
+
def initialize(objects, options = {})
|
7
|
+
@each_serializer = options[:each_serializer]
|
8
|
+
@objects = objects
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_a
|
13
|
+
return ActiveModel::CSVerizer.new(nil).to_a if @objects.nil?
|
14
|
+
@objects.collect do |object|
|
15
|
+
serializer = @each_serializer || ActiveModel::CSVerizerFactory
|
16
|
+
serializer.new(object, @options).to_a
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_csv
|
21
|
+
to_a.to_csv
|
22
|
+
end
|
23
|
+
|
24
|
+
def attribute_names
|
25
|
+
return [] unless @objects
|
26
|
+
serializer = @each_serializer || ActiveModel::CSVerizerFactory
|
27
|
+
serializer.new(@objects.first, @options).attribute_names
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
class CSVerizer
|
5
|
+
@_attributes = []
|
6
|
+
@associations = []
|
7
|
+
@root = true
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :_attributes, :associations, :root
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.inherited(base)
|
14
|
+
base._attributes = []
|
15
|
+
base.associations = []
|
16
|
+
base.root = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.attributes(*attributes)
|
20
|
+
@_attributes = @_attributes.concat(attributes)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.has_one(associated)
|
24
|
+
@associations << {
|
25
|
+
associated: associated,
|
26
|
+
serializer: ActiveModel::CSVerizerFactory
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.has_many(associated)
|
31
|
+
@associations << {
|
32
|
+
associated: associated,
|
33
|
+
serializer: ActiveModel::CsvArraySerializer
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_reader :object
|
38
|
+
|
39
|
+
def initialize(object, options = {})
|
40
|
+
@object = object
|
41
|
+
@root = options.fetch(:root, self.class.root)
|
42
|
+
@prefix = options.fetch(:prefix, '')
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_a
|
46
|
+
return [[]] unless @object
|
47
|
+
|
48
|
+
values = []
|
49
|
+
values << self.class._attributes.collect { |name| read_attribute(name) }
|
50
|
+
|
51
|
+
associated_serializers.each do |serializer|
|
52
|
+
values = values.product(serializer.to_a).collect(&:flatten)
|
53
|
+
end
|
54
|
+
|
55
|
+
values
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_csv
|
59
|
+
CSV.generate do |csv|
|
60
|
+
csv << attribute_names if @root
|
61
|
+
to_a.each { |record| csv << record }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def attribute_names
|
66
|
+
names = self.class._attributes.collect do |attribute|
|
67
|
+
@prefix + attribute.to_s
|
68
|
+
end
|
69
|
+
associated_serializers.reduce(names) do |names, serializer|
|
70
|
+
names.concat serializer.attribute_names
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def read_attribute(name)
|
77
|
+
return send(name) if respond_to?(name)
|
78
|
+
object.read_attribute_for_serialization(name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def read_association(name)
|
82
|
+
respond_to?(name) ? send(name) : object.send(name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def associated_serializers
|
86
|
+
@associated_serializers ||= self.class.associations.collect do |hash|
|
87
|
+
object = read_attribute(hash[:associated])
|
88
|
+
hash[:serializer].new(object, prefix: hash[:associated].to_s + '_')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ActiveModel::CSVerizer::Railtie < Rails::Railtie
|
2
|
+
initializer 'csverizer' do
|
3
|
+
ActiveSupport.on_load(:action_controller) do
|
4
|
+
ActionController::Renderers.add :csv do |object, options|
|
5
|
+
filename = options.fetch(:filename, 'data')
|
6
|
+
begin
|
7
|
+
serializer =
|
8
|
+
if object.respond_to?(:each)
|
9
|
+
hash = options.slice(:each_serializer)
|
10
|
+
ActiveModel::CsvArraySerializer.new(object, hash)
|
11
|
+
else
|
12
|
+
hash = options.slice(:serializer)
|
13
|
+
ActiveModel::CSVerizerFactory.new(object, hash)
|
14
|
+
end
|
15
|
+
data = serializer.to_csv
|
16
|
+
# TODO: probably should implement a specialized exception for this
|
17
|
+
# this btw is when a serializer is not found for provided object
|
18
|
+
rescue NameError
|
19
|
+
data = object.respond_to?(:to_csv) ? object.to_csv : object.to_s
|
20
|
+
end
|
21
|
+
send_data(
|
22
|
+
data,
|
23
|
+
type: Mime[:csv],
|
24
|
+
disposition: "attachment; filename=#{filename}.csv"
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'active_support/inflections'
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
module CSVerizerFactory
|
5
|
+
def self.new(object, options = {})
|
6
|
+
return ActiveModel::CSVerizer.new(nil) if object.nil?
|
7
|
+
klass = object.model_name.name + 'CSVerizer'
|
8
|
+
klass.constantize.new(object, options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/csverizer.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'ArraySerializer' do
|
4
|
+
let(:comments) { [comment_1, comment_2] }
|
5
|
+
let(:comment_1) { Comment.new(text: 'a') }
|
6
|
+
let(:comment_2) { Comment.new(text: 'b') }
|
7
|
+
let(:post) { Post.new(name: 'c', body: 'd') }
|
8
|
+
|
9
|
+
it 'renders csv using specified serializer' do
|
10
|
+
array_serializer = ActiveModel::CsvArraySerializer.new(
|
11
|
+
comments,
|
12
|
+
each_serializer: CommentCSVerizer
|
13
|
+
)
|
14
|
+
csv = array_serializer.to_csv
|
15
|
+
|
16
|
+
expect(csv).to include(comment_1.text)
|
17
|
+
expect(csv).to include(comment_2.text)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'renders csv without specified serializer' do
|
21
|
+
array_serializer = ActiveModel::CsvArraySerializer.new(comments)
|
22
|
+
csv = array_serializer.to_csv
|
23
|
+
|
24
|
+
expect(csv).to include(comment_1.text)
|
25
|
+
expect(csv).to include(comment_2.text)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'raises an exception when expected serializer not found' do
|
29
|
+
comments << Object.new
|
30
|
+
array_serializer = ActiveModel::CsvArraySerializer.new(comments)
|
31
|
+
|
32
|
+
expect{ array_serializer.to_csv }.to raise_error(NameError)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'attributes' do
|
4
|
+
it 'pulls attributes off associated model' do
|
5
|
+
post = Post.new(name: 'Samwise', body: 'Hobbit extraordinaire.')
|
6
|
+
serializer = PostCSVerizer.new(post)
|
7
|
+
csv = serializer.to_csv
|
8
|
+
|
9
|
+
expect(csv).to include(post.name)
|
10
|
+
expect(csv).to include(post.body)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'favors methods defined on serializer' do
|
14
|
+
post = Post.new(name: 'Samwise', body: 'Hobbit extraordinaire.')
|
15
|
+
serializer = Post2CSVerizer.new(post)
|
16
|
+
csv = serializer.to_csv
|
17
|
+
|
18
|
+
expect(csv).to include('pie')
|
19
|
+
expect(csv).to_not include(post.name)
|
20
|
+
expect(csv).to include(post.body)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'allows attributes declaration to be split up' do
|
24
|
+
post = Post.new(name: 'Samwise', body: 'Hobbit extraordinaire.')
|
25
|
+
serializer = Post3CSVerizer.new(post)
|
26
|
+
csv = serializer.to_csv
|
27
|
+
|
28
|
+
expect(csv).to include(post.name)
|
29
|
+
expect(csv).to include(post.body)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveModel::CSVerizerFactory do
|
4
|
+
let(:post) { Post.new(name: 'a', body: 'b') }
|
5
|
+
|
6
|
+
describe '#new' do
|
7
|
+
it 'builds a serializer with type based on singular association' do
|
8
|
+
serializer = ActiveModel::CSVerizerFactory.new(post)
|
9
|
+
expect(serializer).to be_a(PostCSVerizer)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'builds a serializer with type based on plural association' do
|
13
|
+
serializer = ActiveModel::CSVerizerFactory.new(post)
|
14
|
+
expect(serializer).to be_a(PostCSVerizer)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'raises name error when expected serializer not found' do
|
18
|
+
expect do
|
19
|
+
ActiveModel::CSVerizerFactory.new(Photo.new)
|
20
|
+
end.to raise_error(NameError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'has_many' do
|
4
|
+
let(:post) { Post.new(name: 'a', body: 'b', comments: comments) }
|
5
|
+
let(:comments) do
|
6
|
+
[
|
7
|
+
Comment.new(text: 'c'),
|
8
|
+
Comment.new(text: 'd'),
|
9
|
+
Comment.new(text: 'e')
|
10
|
+
]
|
11
|
+
end
|
12
|
+
let(:serializer) { PostCSVerizer.new(post, root: false) }
|
13
|
+
|
14
|
+
it 'appends associated objects csv to multiple copies of this' do
|
15
|
+
csv = serializer.to_csv
|
16
|
+
records = csv.split("\n")
|
17
|
+
expect(records.length).to eq(comments.length)
|
18
|
+
records.each.with_index do |record, i|
|
19
|
+
next if i == 0
|
20
|
+
expect(record).to include(post.name)
|
21
|
+
expect(record).to include(post.body)
|
22
|
+
|
23
|
+
comment = comments[i]
|
24
|
+
expect(record).to include(comment.text)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'has_one' do
|
4
|
+
let(:post) { Post.new(name: 'a', body: 'b', author: author) }
|
5
|
+
let(:author) { Author.new(name: 'd') }
|
6
|
+
let(:category) { Category.new(name: 'e') }
|
7
|
+
let(:post_serializer) { PostCSVerizer.new(post) }
|
8
|
+
let(:author_serializer) { AuthorCSVerizer.new(author) }
|
9
|
+
|
10
|
+
it 'appends the associated objects csv data to this' do
|
11
|
+
csv = post_serializer.to_csv
|
12
|
+
|
13
|
+
expect(csv).to include(post.name)
|
14
|
+
expect(csv).to include(post.body)
|
15
|
+
expect(csv).to include(author.name)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'appends all associated objects csv data to this' do
|
19
|
+
post.category = category
|
20
|
+
csv = post_serializer.to_csv
|
21
|
+
|
22
|
+
expect(csv).to include(post.name)
|
23
|
+
expect(csv).to include(post.body)
|
24
|
+
expect(csv).to include(author.name)
|
25
|
+
expect(csv).to include(category.name)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'appends associated objects associations' do
|
29
|
+
author.category = category
|
30
|
+
csv = post_serializer.to_csv
|
31
|
+
|
32
|
+
expect(csv).to include(post.name)
|
33
|
+
expect(csv).to include(post.body)
|
34
|
+
expect(csv).to include(author.name)
|
35
|
+
expect(csv).to include(category.name)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns this csv data if no associated object' do
|
39
|
+
author = nil
|
40
|
+
csv = post_serializer.to_csv
|
41
|
+
|
42
|
+
expect(csv).to include(post.name)
|
43
|
+
expect(csv).to include(post.body)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'headers' do
|
4
|
+
it 'includes headers based on attribute names by default' do
|
5
|
+
post = Post.new(name: 'Samwise', body: 'Hobbit extraordinaire.')
|
6
|
+
serializer = PostCSVerizer.new(post)
|
7
|
+
csv = serializer.to_csv
|
8
|
+
|
9
|
+
expect(csv).to include('name')
|
10
|
+
expect(csv).to include('body')
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when root option set to false during serializer instantiation' do
|
14
|
+
it 'does not include headers' do
|
15
|
+
post = Post.new(name: 'Samwise', body: 'Hobbit extraordinaire.')
|
16
|
+
serializer = PostCSVerizer.new(post, root: false)
|
17
|
+
csv = serializer.to_csv
|
18
|
+
|
19
|
+
expect(csv).to_not include('name')
|
20
|
+
expect(csv).to_not include('body')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when root set to false during class definition' do
|
25
|
+
before { PostCSVerizer.root = false }
|
26
|
+
after { PostCSVerizer.root = true }
|
27
|
+
|
28
|
+
it 'does not include headers' do
|
29
|
+
post = Post.new(name: 'Samwise', body: 'Hobbit extraordinaire.')
|
30
|
+
serializer = PostCSVerizer.new(post, root: false)
|
31
|
+
csv = serializer.to_csv
|
32
|
+
|
33
|
+
expect(csv).to_not include('name')
|
34
|
+
expect(csv).to_not include('body')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when parent serializer root set to false' do
|
39
|
+
before { ActiveModel::CSVerizer.root = false }
|
40
|
+
after { ActiveModel::CSVerizer.root = true }
|
41
|
+
|
42
|
+
it 'does not include headers' do
|
43
|
+
post = Post.new(name: 'Samwise', body: 'Hobbit extraordinaire.')
|
44
|
+
serializer = PostCSVerizer.new(post, root: false)
|
45
|
+
csv = serializer.to_csv
|
46
|
+
|
47
|
+
expect(csv).to_not include('name')
|
48
|
+
expect(csv).to_not include('body')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when serialized object has one associated object' do
|
53
|
+
it 'renders associated attributes prepended with its name' do
|
54
|
+
category = Category.new(name: 'a')
|
55
|
+
author = Author.new(name: 'b', category: category)
|
56
|
+
serializer = AuthorCSVerizer.new(author)
|
57
|
+
csv = serializer.to_csv
|
58
|
+
|
59
|
+
expect(csv).to include('name')
|
60
|
+
expect(csv).to include('category_name')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when serialized object has nested associated objects' do
|
65
|
+
it 'renders associated attributes prepended with its objects name' do
|
66
|
+
category = Category.new(name: 'a')
|
67
|
+
author = Author.new(name: 'b', category: category)
|
68
|
+
post = Post.new(name: 'a', body: 'b', author: author)
|
69
|
+
serializer = PostCSVerizer.new(post)
|
70
|
+
csv = serializer.to_csv
|
71
|
+
|
72
|
+
expect(csv).to include('name')
|
73
|
+
expect(csv).to include('body')
|
74
|
+
expect(csv).to include('author_name')
|
75
|
+
expect(csv).to include('category_name')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when serialized object has many associated objects' do
|
80
|
+
it 'renders associated attributes prepended with its name' do
|
81
|
+
comments = [
|
82
|
+
Comment.new(text: 'c'),
|
83
|
+
Comment.new(text: 'd'),
|
84
|
+
Comment.new(text: 'e')
|
85
|
+
]
|
86
|
+
post = Post.new(name: 'a', body: 'b', comments: comments)
|
87
|
+
serializer = PostCSVerizer.new(post)
|
88
|
+
csv = serializer.to_csv
|
89
|
+
|
90
|
+
expect(csv).to include('name')
|
91
|
+
expect(csv).to include('body')
|
92
|
+
expect(csv).to include('comments_text') # TODO: singular prefix
|
93
|
+
expect(csv.split("\n").length).to eq(4)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'csv renderer', type: :controller do
|
4
|
+
controller do
|
5
|
+
def object
|
6
|
+
render csv: Post.new(name: 'a')
|
7
|
+
end
|
8
|
+
|
9
|
+
def array
|
10
|
+
render csv: [Post.new(name: 'b'), Category.new(name: 'c')]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
routes.draw { get ':controller/:action' }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'renders an object' do
|
19
|
+
get :object
|
20
|
+
expect(response.body).to include('a')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'renders an array' do
|
24
|
+
get :array
|
25
|
+
|
26
|
+
expect(response.body).to include('b')
|
27
|
+
expect(response.body).to include('c')
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'filename option'
|
31
|
+
describe 'serializer option'
|
32
|
+
describe 'each_serializer option'
|
33
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'action_controller'
|
3
|
+
require 'action_controller/railtie'
|
4
|
+
require 'rspec/rails'
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
require 'active_model'
|
8
|
+
require 'csverizer'
|
9
|
+
|
10
|
+
class DummyApp < Rails::Application
|
11
|
+
config.eager_load = false
|
12
|
+
config.secret_key_base = 'abc123'
|
13
|
+
end
|
14
|
+
DummyApp.initialize!
|
15
|
+
|
16
|
+
Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each {|f| require f}
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.order = :random
|
20
|
+
end
|
21
|
+
|
22
|
+
class Post
|
23
|
+
include ActiveModel::Model
|
24
|
+
include ActiveModel::Serialization
|
25
|
+
|
26
|
+
attr_accessor :name, :body, :comments, :author, :category
|
27
|
+
end
|
28
|
+
|
29
|
+
class PostCSVerizer < ActiveModel::CSVerizer
|
30
|
+
attributes :name, :body
|
31
|
+
has_many :comments
|
32
|
+
has_one :author
|
33
|
+
has_one :category
|
34
|
+
end
|
35
|
+
|
36
|
+
class Post2CSVerizer < PostCSVerizer
|
37
|
+
attributes :name, :body
|
38
|
+
|
39
|
+
def name
|
40
|
+
'pie'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Post3CSVerizer < ActiveModel::CSVerizer
|
45
|
+
attributes :name
|
46
|
+
attributes :body
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
|
51
|
+
class Comment
|
52
|
+
include ActiveModel::Model
|
53
|
+
include ActiveModel::Serialization
|
54
|
+
|
55
|
+
attr_accessor :text
|
56
|
+
end
|
57
|
+
|
58
|
+
class CommentCSVerizer < ActiveModel::CSVerizer
|
59
|
+
attributes :text
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
|
64
|
+
class Photo
|
65
|
+
include ActiveModel::Model
|
66
|
+
include ActiveModel::Serialization
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
|
71
|
+
class Author
|
72
|
+
include ActiveModel::Model
|
73
|
+
include ActiveModel::Serialization
|
74
|
+
|
75
|
+
attr_accessor :name, :category
|
76
|
+
end
|
77
|
+
|
78
|
+
class AuthorCSVerizer < ActiveModel::CSVerizer
|
79
|
+
attributes :name
|
80
|
+
|
81
|
+
has_one :category
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
|
86
|
+
class Category
|
87
|
+
include ActiveModel::Model
|
88
|
+
include ActiveModel::Serialization
|
89
|
+
|
90
|
+
attr_accessor :name
|
91
|
+
end
|
92
|
+
|
93
|
+
class CategoryCSVerizer < ActiveModel::CSVerizer
|
94
|
+
attributes :name
|
95
|
+
end
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: csverizer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- William Cunningham
|
8
|
+
- Peter Hankiewicz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2020-02-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activemodel
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '5.1'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '5.1'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rails
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5.1'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '5.1'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: bundler
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.3'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.3'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rake
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '3.7'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '3.7'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec-rails
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '3.7'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '3.7'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: pry
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
description: ActiveModel::Serializers style CSV serialization.
|
113
|
+
email:
|
114
|
+
- w.a.cunningham.ii@gmail.com
|
115
|
+
- peter.hankiewicz@gmail.com
|
116
|
+
executables: []
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".gitignore"
|
121
|
+
- ".ruby-version"
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- csverizer.gemspec
|
127
|
+
- lib/active_model/csv_array_serializer.rb
|
128
|
+
- lib/active_model/csverizer.rb
|
129
|
+
- lib/active_model/csverizer/railtie.rb
|
130
|
+
- lib/active_model/csverizer/version.rb
|
131
|
+
- lib/active_model/csverizer_factory.rb
|
132
|
+
- lib/csverizer.rb
|
133
|
+
- spec/active_model/array_serializer_spec.rb
|
134
|
+
- spec/active_model/attributes_spec.rb
|
135
|
+
- spec/active_model/csverizer_factory_spec.rb
|
136
|
+
- spec/active_model/has_many_spec.rb
|
137
|
+
- spec/active_model/has_one_spec.rb
|
138
|
+
- spec/active_model/header_spec.rb
|
139
|
+
- spec/renderer_spec.rb
|
140
|
+
- spec/spec_helper.rb
|
141
|
+
homepage: https://github.com/peter-hank/csverizer
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata: {}
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
147
|
+
require_paths:
|
148
|
+
- lib
|
149
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 2.2.2
|
154
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubygems_version: 3.1.2
|
161
|
+
signing_key:
|
162
|
+
specification_version: 4
|
163
|
+
summary: Serialize models as CSV.
|
164
|
+
test_files:
|
165
|
+
- spec/active_model/array_serializer_spec.rb
|
166
|
+
- spec/active_model/attributes_spec.rb
|
167
|
+
- spec/active_model/csverizer_factory_spec.rb
|
168
|
+
- spec/active_model/has_many_spec.rb
|
169
|
+
- spec/active_model/has_one_spec.rb
|
170
|
+
- spec/active_model/header_spec.rb
|
171
|
+
- spec/renderer_spec.rb
|
172
|
+
- spec/spec_helper.rb
|