active_export 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -5,6 +5,6 @@
5
5
  _yardoc
6
6
  doc/
7
7
  coverage
8
- tmp
8
+ tmp/*
9
9
  log/*
10
10
  Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ - ruby-head
5
+ - rbx-19mode
6
+ gemfile:
7
+ - spec/gemfiles/Gemfile.rails.3.0
8
+ - spec/gemfiles/Gemfile.rails.3.1
9
+ - spec/gemfiles/Gemfile.rails.3.2
10
+ branches:
11
+ only:
12
+ - master
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ gemspec
5
5
 
6
6
  group :development, :test do
7
7
  gem 'rake', '~> 0.9.2.2', :require => false
8
- gem 'rails', ">= #{ENV['RAILS'] || '3.0.0'}"
8
+ gem 'rails', ">= 3.0.0"
9
9
 
10
10
  gem 'yard'
11
11
  gem 'rdiscount'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ActiveExport
1
+ # ActiveExport [![Build Status](https://secure.travis-ci.org/kengos/active_export.png?branch=master)](http://travis-ci.org/kengos/active_export)[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/kengos/active_export)
2
2
 
3
3
  ActiveExport generate from ActiveRecord or others to CSV String or CSV file.
4
4
 
@@ -18,6 +18,30 @@ module ActiveExport
18
18
  end
19
19
 
20
20
  class << self
21
+ # Generate Csv String
22
+ # @param [Array, ActiveRecord::Relation] data
23
+ # @param [Symbol, String] source
24
+ # @param [Symobl, String] namespace
25
+ # @param [Hash] options ({})
26
+ # @option options [Array] :eval_methods
27
+ # @option options [Array] :label_keys
28
+ # @option options [String] :label_prefix
29
+ # @option options [Hash] :csv_options (see http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html)
30
+ # @return [String] Csv String
31
+ def export(data, source, namespace, options = {})
32
+ new(source, namespace, options).export(data)
33
+ end
34
+
35
+ # Generate Csv File
36
+ # @param [Array, ActiveRecord::Relation] data
37
+ # @param [Symbol, String] source YAML File alias name (see ActiveExport::Configuration#sources)
38
+ # @param [Symbol, String] namespace YAML File namespace
39
+ # @param [String, Filepath] filename Csv File name
40
+ # @param [Hash] options ({}) (see .export)
41
+ def export_file(data, source, namespace, filename, options = {})
42
+ new(source, namespace, options).export_file(data, filename)
43
+ end
44
+
21
45
  def translate(key, scope = [])
22
46
  defaults = [
23
47
  :"active_export.#{scope.join('.')}.#{key.to_s.gsub('.', '_')}",
@@ -46,6 +70,19 @@ module ActiveExport
46
70
  end
47
71
  end
48
72
 
73
+ # Export data to exporter
74
+ # @param [Array, ActiveRecord::Relation] data Export target data
75
+ # @param [Object] Object needs to support '<<' accessor
76
+ def export_data(data, exporter)
77
+ if data.respond_to?(:find_in_batches) && data.respond_to?(:orders) && data.orders.blank? && data.respond_to?(:taken) && data.taken.blank?
78
+ data.find_in_batches(find_in_batches_options) do |group|
79
+ group.each{|f| exporter << generate_value(f) }
80
+ end
81
+ else
82
+ data.each{|f| exporter << generate_value(f) }
83
+ end
84
+ end
85
+
49
86
  # Convert value for export string
50
87
  # @todo refactor me
51
88
  def convert(value)
@@ -98,5 +135,24 @@ module ActiveExport
98
135
  def translate(key, scope = nil)
99
136
  self.class.translate(key, scope || default_scope)
100
137
  end
138
+
139
+ protected
140
+
141
+ def generate_header
142
+ self.label_keys.inject([]) {|result, key|
143
+ result << translate(key_name(key))
144
+ }
145
+ end
146
+
147
+ def generate_value(row)
148
+ self.eval_methods.inject([]){|result, f|
149
+ v = row.send(:eval, f) rescue nil
150
+ result << convert(v)
151
+ }
152
+ end
153
+
154
+ def find_in_batches_options
155
+ self.config.default_find_in_batches_options.merge( self.options[:find_in_batches_options] || {} )
156
+ end
101
157
  end
102
158
  end
@@ -4,32 +4,6 @@ require 'csv'
4
4
 
5
5
  module ActiveExport
6
6
  class Csv < ::ActiveExport::Base
7
- # Generate Csv String
8
- # @param [Array, ActiveRecord::Relation] data
9
- # @param [Symbol, String] source
10
- # @param [Symobl, String] namespace
11
- # @param [Hash] options ({})
12
- # @option options [Array] :eval_methods
13
- # @option options [Array] :label_keys
14
- # @option options [String] :label_prefix
15
- # @option options [Hash] :csv_options (see http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html)
16
- # @return [String] Csv String
17
- # @exmaple
18
- # AcriveExport::Csv.export(data, :source, :namespace)
19
- def self.export(data, source, namespace, options = {})
20
- new(source, namespace, options).export(data)
21
- end
22
-
23
- # Generate Csv File
24
- # @param [Array, ActiveRecord::Relation] data
25
- # @param [Symbol, String] source YAML File alias name (see ActiveExport::Configuration#sources)
26
- # @param [Symbol, String] namespace YAML File namespace
27
- # @param [String, Filepath] filename Csv File name
28
- # @param [Hash] options ({}) (see .export)
29
- def self.export_file(data, source, namespace, filename, options = {})
30
- new(source, namespace, options).export_file(data, filename)
31
- end
32
-
33
7
  def export(data)
34
8
  CSV.generate(csv_options) do |csv|
35
9
  csv << generate_header if header?
@@ -38,7 +12,7 @@ module ActiveExport
38
12
  end
39
13
 
40
14
  def export_file(data, filename)
41
- File.atomic_write(filename) do |file|
15
+ File.atomic_write(filename.to_s) do |file|
42
16
  CSV.open(file, "wb", csv_options) do |csv|
43
17
  csv << generate_header if header?
44
18
  export_data(data, csv)
@@ -47,36 +21,7 @@ module ActiveExport
47
21
  filename
48
22
  end
49
23
 
50
- # Export data to exporter
51
- # @param [Array, ActiveRecord::Relation] data Export target data
52
- # @param [CSV, Array, String] exporter CSV class or Array class, or String class (should support '<<' accessor)
53
- def export_data(data, exporter)
54
- if data.respond_to?(:find_in_batches) && data.respond_to?(:orders) && data.orders.blank? && data.respond_to?(:taken) && data.taken.blank?
55
- data.find_in_batches(find_in_batches_options) do |group|
56
- group.each{|f| exporter << generate_value(f) }
57
- end
58
- else
59
- data.each{|f| exporter << generate_value(f) }
60
- end
61
- end
62
-
63
24
  protected
64
- def generate_header
65
- self.label_keys.inject([]) {|result, key|
66
- result << translate(key_name(key))
67
- }
68
- end
69
-
70
- def generate_value(row)
71
- self.eval_methods.inject([]){|result, f|
72
- v = row.send(:eval, f) rescue nil
73
- result << convert(v)
74
- }
75
- end
76
-
77
- def find_in_batches_options
78
- self.config.default_find_in_batches_options.merge( self.options[:find_in_batches_options] || {} )
79
- end
80
25
 
81
26
  def csv_options
82
27
  self.config.default_csv_options.merge( self.options[:csv_options] || {} )
@@ -1,3 +1,3 @@
1
1
  module ActiveExport
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+
3
+ module ActiveExport
4
+ class Xml < ::ActiveExport::Base
5
+ # @return [String] XML style string
6
+ def export(data)
7
+ str = ''
8
+ str << source[:xml_format][:header]
9
+ [].tap {|o| export_data(data, o)}.inject([]) do |result, f|
10
+ result << {}.tap{|o|
11
+ self.label_keys.each_with_index {|k, i| o[k] = f[i] }
12
+ }
13
+ end.each do |f|
14
+ str << binding(f)
15
+ end
16
+ str << source[:xml_format][:footer]
17
+ str
18
+ end
19
+
20
+ def export_file(data, filename)
21
+ File.atomic_write(filename.to_s) do |file|
22
+ file.write export(data)
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ # @params [Hash] values Format: { label_1: value_1, ... }
29
+ def binding(values)
30
+ result_string = binding_source.dup
31
+ values.each_pair do |k,v|
32
+ result_string.gsub!("%%#{k}%%", v)
33
+ end
34
+ result_string
35
+ end
36
+
37
+ def binding_source
38
+ @xml_body ||= source[:xml_format][:body]
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+
3
+ require 'yaml'
4
+
5
+ module ActiveExport
6
+ class Yaml < ::ActiveExport::Base
7
+ # @return [String] YAML style string
8
+ # @memo output format(i want)
9
+ # -
10
+ # - label: value
11
+ # - label: value
12
+ def export(data)
13
+ [].tap {|o|
14
+ export_data(data, o)
15
+ }.to_yaml
16
+ end
17
+
18
+ def export_file(data, filename)
19
+ File.atomic_write(filename.to_s) do |file|
20
+ file.write export(data)
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/active_export.rb CHANGED
@@ -6,6 +6,8 @@ require 'erb'
6
6
  module ActiveExport
7
7
  autoload :Base, 'active_export/base'
8
8
  autoload :Csv, 'active_export/csv'
9
+ autoload :Yaml, 'active_export/yaml'
10
+ autoload :Xml, 'active_export/xml'
9
11
 
10
12
  class << self
11
13
  # @example
@@ -74,6 +74,43 @@ describe ActiveExport::Base do
74
74
  end
75
75
  end
76
76
 
77
+ describe "#export_data" do
78
+ let(:csv_exporter) { ActiveExport::Base.new(:default, :book_1) }
79
+ let!(:book_1) { Book.create!(name: 'book_1', author: nil, price: 58) }
80
+ let!(:book_2) { Book.create!(name: 'book_2', author: nil, price: 58) }
81
+ let!(:book_3) { Book.create!(name: 'book_2', author: nil, price: 58) }
82
+
83
+ it "should not call find_in_batches when has order" do
84
+ obj = Book.order('id ASC')
85
+ obj.should_not_receive(:find_in_batches)
86
+ obj.should_receive(:each)
87
+ csv_exporter.send(:export_data, obj, [])
88
+ end
89
+
90
+
91
+ it "should not call find_in_batches when has limit" do
92
+ obj = Book.limit(1)
93
+ obj.should_not_receive(:find_in_batches)
94
+ obj.should_receive(:each)
95
+ csv_exporter.send(:export_data, obj, [])
96
+ end
97
+
98
+ it "should not call find_in_batches when specified obj is not ActiveRecord::Relation" do
99
+ obj = [Book.first]
100
+ obj.should_not_receive(:find_in_batches)
101
+ obj.should_receive(:each)
102
+ csv_exporter.send(:export_data, obj, [])
103
+ end
104
+
105
+ it "should call find_in_batches" do
106
+ obj = Book.scoped
107
+ obj.should_receive(:find_in_batches).with({batch_size: 1})
108
+ obj.should_not_receive(:each)
109
+ csv_exporter.stub(:find_in_batches_options).and_return({batch_size: 1})
110
+ csv_exporter.send(:export_data, obj, [])
111
+ end
112
+ end
113
+
77
114
  describe ".translate" do
78
115
  let(:i18n_key) { 'author.name' }
79
116
  subject { ActiveExport::Base.translate('author.name', [:default, :book]) }
@@ -71,43 +71,6 @@ book_2:author_2:38
71
71
  it { File.read(filename).split("\n").first.should eql %Q("Book name","Author name","Book price") }
72
72
  end
73
73
 
74
- describe "#export_data" do
75
- let(:csv_exporter) { ActiveExport::Csv.new(:default, :book_1) }
76
- let!(:book_1) { Book.create!(name: 'book_1', author: nil, price: 58) }
77
- let!(:book_2) { Book.create!(name: 'book_2', author: nil, price: 58) }
78
- let!(:book_3) { Book.create!(name: 'book_2', author: nil, price: 58) }
79
-
80
- it "should not call find_in_batches when has order" do
81
- obj = Book.order('id ASC')
82
- obj.should_not_receive(:find_in_batches)
83
- obj.should_receive(:each)
84
- csv_exporter.send(:export_data, obj, [])
85
- end
86
-
87
-
88
- it "should not call find_in_batches when has limit" do
89
- obj = Book.limit(1)
90
- obj.should_not_receive(:find_in_batches)
91
- obj.should_receive(:each)
92
- csv_exporter.send(:export_data, obj, [])
93
- end
94
-
95
- it "should not call find_in_batches when specified obj is not ActiveRecord::Relation" do
96
- obj = [Book.first]
97
- obj.should_not_receive(:find_in_batches)
98
- obj.should_receive(:each)
99
- csv_exporter.send(:export_data, obj, [])
100
- end
101
-
102
- it "should call find_in_batches" do
103
- obj = Book.scoped
104
- obj.should_receive(:find_in_batches).with({batch_size: 1})
105
- obj.should_not_receive(:each)
106
- csv_exporter.stub(:find_in_batches_options).and_return({batch_size: 1})
107
- csv_exporter.send(:export_data, obj, [])
108
- end
109
- end
110
-
111
74
  describe ".generate_value" do
112
75
  let(:author_1) { Author.create!(name: 'author_1') }
113
76
  let!(:book_1) { Book.create!(name: 'book_1', author: author_1, price: 1000) }
@@ -0,0 +1,50 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ActiveExport::Xml do
6
+ before {
7
+ ActiveExport.configure do |config|
8
+ config.sources = { xml: fixture_file('xml.yml') }
9
+ end
10
+ }
11
+
12
+ let(:author_1) { Author.create!(name: 'author_1') }
13
+ let(:author_2) { Author.create!(name: 'author_2') }
14
+ let!(:book_1) { Book.create!(name: 'book_1', author: author_1, price: 58) }
15
+ let!(:book_2) { Book.create!(name: 'book_2', author: author_2, price: 38) }
16
+
17
+ let(:expect_string) {
18
+ <<-EOS
19
+ <?xml version="1.0" encoding="UTF-8"?>
20
+ <records>
21
+ <book>
22
+ <name>book_1</name>
23
+ <author_name>author_1</author_name>
24
+ <price>63.51</price>
25
+ </book>
26
+ <book>
27
+ <name>book_2</name>
28
+ <author_name>author_2</author_name>
29
+ <price>41.61</price>
30
+ </book>
31
+ </records>
32
+ EOS
33
+ }
34
+ describe ".export" do
35
+ subject { ActiveExport::Xml.export(Book.scoped, :xml, :book_1) }
36
+ it { should == expect_string }
37
+ end
38
+
39
+ describe ".export_file" do
40
+ let(:xml_file) { Rails.root.join('tmp', 'test.xml') }
41
+ before {
42
+ FileUtils.rm yaml_file if FileTest.exist?(xml_file)
43
+ ActiveExport::Xml.export_file(Book.scoped, :xml, :book_1, xml_file)
44
+ }
45
+ after {
46
+ FileUtils.rm xml_file if FileTest.exist?(xml_file)
47
+ }
48
+ it { File.read(xml_file).should == expect_string }
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ActiveExport::Yaml do
6
+ before {
7
+ ActiveExport.configure do |config|
8
+ config.sources = { default: fixture_file('csv_1.yml') }
9
+ end
10
+ }
11
+
12
+ describe ".export" do
13
+ let(:author_1) { Author.create!(name: 'author_1') }
14
+ let(:author_2) { Author.create!(name: 'author_2') }
15
+ let!(:book_1) { Book.create!(name: 'book_1', author: author_1, price: 58) }
16
+ let!(:book_2) { Book.create!(name: 'book_2', author: author_2, price: 38) }
17
+
18
+ let(:yaml_string) { ActiveExport::Yaml.export(Book.order('id DESC').all, :default, :book_2) }
19
+ subject { YAML.load(yaml_string) }
20
+ its([0]) { should == ["book_2", "author_2", "42"] }
21
+ its([1]) { should == ["book_1", "author_1", "64"] }
22
+ end
23
+
24
+ describe ".export_file" do
25
+ let(:author_1) { Author.create!(name: 'author_1') }
26
+ let(:author_2) { Author.create!(name: 'author_2') }
27
+ let!(:book_1) { Book.create!(name: 'book_1', author: author_1, price: 58) }
28
+ let!(:book_2) { Book.create!(name: 'book_2', author: author_2, price: 38) }
29
+ let(:yaml_file) { Rails.root.join('tmp', 'test.yml') }
30
+ before {
31
+ FileUtils.rm yaml_file if FileTest.exist?(yaml_file)
32
+ ActiveExport::Yaml.export_file(Book.scoped, :default, :book_2, yaml_file)
33
+ }
34
+ after {
35
+ FileUtils.rm yaml_file if FileTest.exist?(yaml_file)
36
+ }
37
+ subject { YAML.load(File.read(yaml_file)) }
38
+ its([0]) { should == ["book_1", "author_1", "64"] }
39
+ its([1]) { should == ["book_2", "author_2", "42"] }
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ book_1:
2
+ label_prefix: 'book'
3
+ methods:
4
+ - name
5
+ - author.name
6
+ - price: 'price * 1.095'
7
+ xml_format:
8
+ encoding: 'UTF-8'
9
+ header: |
10
+ <?xml version="1.0" encoding="UTF-8"?>
11
+ <records>
12
+ footer: |
13
+ </records>
14
+ body: |
15
+ <book>
16
+ <name>%%name%%</name>
17
+ <author_name>%%author.name%%</author_name>
18
+ <price>%%price%%</price>
19
+ </book>
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'rails', "3.0.16"
5
+
6
+ gem 'sqlite3'
7
+ gem 'rspec-rails'
8
+ gem 'factory_girl_rails'
9
+ gem 'database_cleaner'
10
+ end
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'rails', "3.1.7"
5
+
6
+ gem 'sqlite3'
7
+ gem 'rspec-rails'
8
+ gem 'factory_girl_rails'
9
+ gem 'database_cleaner'
10
+ end
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'rails', "3.2.8"
5
+
6
+ gem 'sqlite3'
7
+ gem 'rspec-rails'
8
+ gem 'factory_girl_rails'
9
+ gem 'database_cleaner'
10
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,8 @@
1
- require 'tapp'
1
+ begin
2
+ require 'tapp'
3
+ rescue Exception
4
+ end
5
+
2
6
  require 'rails/rails_support'
3
7
  require 'rspec'
4
8
  require 'rspec/rails'
data/tasks/yard.rake CHANGED
@@ -1,6 +1,11 @@
1
- require 'yard'
2
- require 'yard/rake/yardoc_task'
1
+ begin
3
2
 
4
- YARD::Rake::YardocTask.new do |t|
5
- t.files = ['lib/**/*.rb']
3
+ require 'yard'
4
+ require 'yard/rake/yardoc_task'
5
+
6
+ YARD::Rake::YardocTask.new do |t|
7
+ t.files = ['lib/**/*.rb']
8
+ end
9
+
10
+ rescue Exception
6
11
  end
data/tmp/.gitkeep ADDED
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_export
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-19 00:00:00.000000000 Z
12
+ date: 2012-08-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -35,6 +35,7 @@ extensions: []
35
35
  extra_rdoc_files: []
36
36
  files:
37
37
  - .gitignore
38
+ - .travis.yml
38
39
  - .yardopts
39
40
  - Gemfile
40
41
  - Guardfile
@@ -47,12 +48,20 @@ files:
47
48
  - lib/active_export/configuration.rb
48
49
  - lib/active_export/csv.rb
49
50
  - lib/active_export/version.rb
51
+ - lib/active_export/xml.rb
52
+ - lib/active_export/yaml.rb
50
53
  - spec/active_export/base_spec.rb
51
54
  - spec/active_export/csv_spec.rb
52
55
  - spec/active_export/rails_support_spec.rb
56
+ - spec/active_export/xml_spec.rb
57
+ - spec/active_export/yaml_spec.rb
53
58
  - spec/active_export_spec.rb
54
59
  - spec/factories/book.rb
55
60
  - spec/fixtures/csv_1.yml
61
+ - spec/fixtures/xml.yml
62
+ - spec/gemfiles/Gemfile.rails.3.0
63
+ - spec/gemfiles/Gemfile.rails.3.1
64
+ - spec/gemfiles/Gemfile.rails.3.2
56
65
  - spec/rails/model/author.rb
57
66
  - spec/rails/model/book.rb
58
67
  - spec/rails/model/book_category.rb
@@ -61,6 +70,7 @@ files:
61
70
  - spec/rails/schema.rb
62
71
  - spec/spec_helper.rb
63
72
  - tasks/yard.rake
73
+ - tmp/.gitkeep
64
74
  homepage: https://github.com/kengos/active_export
65
75
  licenses: []
66
76
  post_install_message:
@@ -89,9 +99,15 @@ test_files:
89
99
  - spec/active_export/base_spec.rb
90
100
  - spec/active_export/csv_spec.rb
91
101
  - spec/active_export/rails_support_spec.rb
102
+ - spec/active_export/xml_spec.rb
103
+ - spec/active_export/yaml_spec.rb
92
104
  - spec/active_export_spec.rb
93
105
  - spec/factories/book.rb
94
106
  - spec/fixtures/csv_1.yml
107
+ - spec/fixtures/xml.yml
108
+ - spec/gemfiles/Gemfile.rails.3.0
109
+ - spec/gemfiles/Gemfile.rails.3.1
110
+ - spec/gemfiles/Gemfile.rails.3.2
95
111
  - spec/rails/model/author.rb
96
112
  - spec/rails/model/book.rb
97
113
  - spec/rails/model/book_category.rb