active_admin_import 1.0.1 → 2.0.0

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/README.md CHANGED
@@ -14,14 +14,20 @@ https://github.com/zdennis/activerecord-import
14
14
 
15
15
  # +back+:: resource action to redirect after processing
16
16
  # +col_sep+:: column separator used for CSV parsing
17
- # +validate+:: rue|false, means perfoem validations or not
17
+ # +validate+:: true|false, means perfoem validations or not
18
18
  # +batch_size+:: integer value of max record count inserted by 1 query/transaction
19
- # +before_import+:: proc for before import action, called with resource, file, options arguments
20
- # +before_batch_import+:: proc for before each batch action, called with imported data and headers arguments
21
- # +after_batch_import+:: proc for after each batch action, called with imported data and headers arguments
19
+ # +before_import+:: proc for before import action, hook called with importer object
20
+ # +after_import+:: proc for after import action, hook called with importer object
21
+ # +before_batch_import+:: proc for before each batch action, called with importer object
22
+ # +after_batch_import+:: proc for after each batch action, called with importer object
22
23
  # +on_duplicate_key_update+:: an Array or Hash, tells activerecord-import to use MySQL's ON DUPLICATE KEY UPDATE ability.
23
24
  # +timestamps+:: true|false, tells activerecord-import to not add timestamps (if false) even if record timestamps is disabled in ActiveRecord::Base
24
25
  # +ignore+:: true|false, tells activerecord-import toto use MySQL's INSERT IGNORE ability
26
+ # +params_keys+:: params values available in callbacks
27
+ # +template+:: custom template rendering
28
+ # +locals+:: local variables for template
29
+ # +resource_class+:: resource class name
30
+ # +resource_label+:: resource label value
25
31
 
26
32
 
27
33
  #Example
@@ -30,7 +36,7 @@ https://github.com/zdennis/activerecord-import
30
36
  active_admin_import :validate => false,
31
37
  :col_sep => ',',
32
38
  :back => :index ,
33
- :before_import => proc{|data| Post.delete_all},
39
+ :before_import => proc{|importer| resource.delete_all},
34
40
  :batch_size => 1000
35
41
 
36
42
 
@@ -4,7 +4,7 @@ require File.expand_path('../lib/active_admin_import/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Igor Fedoronchuk"]
6
6
  gem.email = ["fedoronchuk@gmail.com"]
7
- gem.description = "CSV import for Active Admin"
7
+ gem.description = "The most efficient way to import for Active Admin"
8
8
  gem.summary = "ActiveAdmin import based on activerecord-import gem."
9
9
  gem.homepage = "http://github.com/Fivell/active_admin_import"
10
10
 
@@ -15,6 +15,5 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = ActiveAdminImport::VERSION
17
17
 
18
- gem.add_runtime_dependency('chronic')
19
18
  gem.add_runtime_dependency('activerecord-import','0.3.0')
20
19
  end
@@ -1,7 +1,11 @@
1
- <%= form_for :import, :url => {:action => :do_import}, :html => {:multipart => true} do |f| %>
2
- <%= label_tag "import_file", "File for import:" %><br>
3
- <%= f.file_field :file %>
4
- <hr />
5
- <%= submit_tag 'Import' %>
6
- <% end %>
7
-
1
+ <p>
2
+ <small> <%= raw(@active_admin_import_model.hint) %> </small>
3
+ </p>
4
+ <%= semantic_form_for @active_admin_import_model , :url => {:action => :do_import}, :html => {:multipart => true} do |f| %>
5
+ <%= f.inputs do %>
6
+ <%= f.input :file, :as=>:file %>
7
+ <% end %>
8
+ <%= f.actions do %>
9
+ <%= f.action :submit , :label =>t("active_admin_import.import_btn") ,:button_html => { :disable_with => t("active_admin_import.import_btn_disabled") }%>
10
+ <% end %>
11
+ <% end %>
@@ -3,5 +3,14 @@ require 'active_admin_import/version'
3
3
  require 'active_admin_import/engine'
4
4
  require 'active_admin_import/dsl'
5
5
  require 'active_admin_import/importer'
6
-
6
+ require 'active_admin_import/model'
7
7
  ::ActiveAdmin::DSL.send(:include, ActiveAdminImport::DSL)
8
+
9
+ module ActiveAdminImport
10
+ class Railtie < ::Rails::Railtie
11
+ config.after_initialize do
12
+ require 'active_support/i18n'
13
+ I18n.load_path.unshift *Dir[File.expand_path('../active_admin_import/locales/*.yml', __FILE__)]
14
+ end
15
+ end
16
+ end
@@ -7,45 +7,89 @@ module ActiveAdminImport
7
7
  # Options
8
8
  # +back+:: resource action to redirect after processing
9
9
  # +col_sep+:: column separator used for CSV parsing
10
- # +validate+:: rue|false, means perfoem validations or not
10
+ # +validate+:: true|false, means perfoem validations or not
11
11
  # +batch_size+:: integer value of max record count inserted by 1 query/transaction
12
- # +before_import+:: proc for before import action, called with resource, file, options arguments
13
- # +before_batch_import+:: proc for before each batch action, called with imported data and headers arguments
14
- # +after_batch_import+:: proc for after each batch action, called with imported data and headers arguments
12
+ # +before_import+:: proc for before import action, hook called with importer object
13
+ # +after_import+:: proc for after import action, hook called with importer object
14
+ # +before_batch_import+:: proc for before each batch action, called with importer object
15
+ # +after_batch_import+:: proc for after each batch action, called with importer object
15
16
  # +on_duplicate_key_update+:: an Array or Hash, tells activerecord-import to use MySQL's ON DUPLICATE KEY UPDATE ability.
16
17
  # +timestamps+:: true|false, tells activerecord-import to not add timestamps (if false) even if record timestamps is disabled in ActiveRecord::Base
17
18
  # +ignore+:: true|false, tells activerecord-import toto use MySQL's INSERT IGNORE ability
19
+ # +fetch_extra_options_from_params+:: params values available in callbacks in importer.extra_options hash
20
+ # +template+:: custom template rendering
21
+ # +locals+:: local variables for template
22
+ # +resource_class+:: resource class name
23
+ # +resource_label+:: resource label value
24
+ #
18
25
  def active_admin_import options = {}
19
26
  default_options = {
20
- :back => :import,
21
- :col_sep => ','
27
+ :back => :import,
28
+ :col_sep => ',',
29
+ :template => "admin/import",
30
+ :template_object => ActiveAdminImport::Model.new,
31
+ :fetch_extra_options_from_params => [],
32
+ :resource_class => nil,
33
+ :resource_label => nil,
34
+ :headers_rewrites => {}
35
+
36
+
22
37
  }
23
38
  options = default_options.merge(options)
24
- action_item :only => :index do
25
- link_to "Import #{active_admin_config.resource_name.pluralize}", :action => 'import'
26
- end
39
+ params_key = ActiveModel::Naming.param_key(options[:template_object])
40
+
27
41
 
28
42
  collection_action :import, :method => :get do
29
- render "admin/import"
43
+ @active_admin_import_model = options[:template_object]
44
+ render :template => options[:template]
45
+ end
46
+
47
+
48
+ action_item :only => :index do
49
+ link_to(I18n.t('active_admin_import.import_model',
50
+ :model => (options[:resource_label] || active_admin_config.resource_name)),
51
+ :action => 'import')
30
52
  end
31
53
 
54
+
32
55
  collection_action :do_import, :method => :post do
33
- if params[:import].blank?
34
- flash[:alert] = "Please, select file to import"
35
- return redirect_to :action => options[:back]
56
+ if params[params_key].blank?
57
+ flash[:alert] = I18n.t('active_admin_import.no_file_error')
58
+ return redirect_to :back
36
59
  end
37
- unless params[:import]['file'].try(:content_type) && params[:import]['file'].content_type.in?(["text/csv"])
38
- flash[:alert] = "You can import file only with extension csv"
39
- return redirect_to :action => options[:back]
60
+ content_types_allow = [
61
+ 'text/csv',
62
+ 'text/x-csv',
63
+ 'text/comma-separated-values',
64
+ 'application/csv',
65
+ 'application/vnd.ms-excel',
66
+ 'application/vnd.msexcel'
67
+ ]
68
+ unless params[params_key]['file'].try(:content_type) && params[params_key]['file'].content_type.in?(content_types_allow)
69
+ flash[:alert] = I18n.t('active_admin_import.file_format_error')
70
+ return redirect_to :back
40
71
  end
41
- importer = Importer.new( active_admin_config.resource_class, params[:import][:file], options)
42
72
 
73
+ importer = Importer.new((options[:resource_class] || active_admin_config.resource_class),
74
+ params[params_key][:file],
75
+ options,
76
+ params[params_key].to_hash.slice(*options[:fetch_extra_options_from_params])
77
+ )
78
+ result = importer.import
79
+
80
+ flash[:notice] = I18n.t('active_admin_import.imported',
81
+ :count=> result[:imported].to_i,
82
+ :model => (options[:resource_label] || active_admin_config.resource_label).downcase,
83
+ :plural_model => (options[:resource_label].present? ? options[:resource_label].to_s.pluralize : active_admin_config.plural_resource_label).downcase
84
+
85
+ ) if result[:imported].to_i > 0
86
+
87
+ flash[:error] = I18n.t('active_admin_import.failed',
88
+ :count=> result[:failed].count,
89
+ :model => (options[:resource_label] || active_admin_config.resource_label).downcase,
90
+ :plural_model => (options[:resource_label].present? ? options[:resource_label].to_s.pluralize : active_admin_config.plural_resource_label).downcase
43
91
 
44
- result = importer.import
45
- flash[:notice] = "#{view_context.pluralize(result[:imported].to_i,active_admin_config.resource_name)} was imported"
46
- unless result[:failed].count == 0
47
- flash[:error] = "#{view_context.pluralize(result[:failed].count,active_admin_config.resource_name)} was failed to imported"
48
- end
92
+ ) if result[:failed].count > 0
49
93
 
50
94
  redirect_to :action => options[:back]
51
95
  end
@@ -2,28 +2,33 @@ require 'csv'
2
2
  module ActiveAdminImport
3
3
  class Importer
4
4
 
5
- attr_reader :resource, :file, :options , :result
5
+ attr_reader :resource, :file, :options , :extra_options , :result ,
6
+ :cycle_data, :headers , :csv_lines
6
7
 
7
- def store data, headers
8
+ def store
8
9
  result = @resource.transaction do
9
- options[:before_batch_import].call(data, headers) if options[:before_batch_import].is_a?(Proc)
10
- result = resource.import headers, data, {
10
+ options[:before_batch_import].call(self) if options[:before_batch_import].is_a?(Proc)
11
+
12
+
13
+ result = resource.import headers.values, csv_lines, {
11
14
  :validate => options[:validate],
12
15
  :on_duplicate_key_update => options[:on_duplicate_key_update],
13
16
  :ignore => options[:ignore],
14
17
  :timestamps => options[:timestamps]
15
18
  }
16
- options[:after_batch_import].call(data, headers) if options[:after_batch_import].is_a?(Proc)
19
+ options[:after_batch_import].call(self) if options[:after_batch_import].is_a?(Proc)
17
20
  result
18
21
  end
19
- {:imported => data.count - result.failed_instances.count , :failed => result.failed_instances}
22
+ {:imported => csv_lines.count - result.failed_instances.count , :failed => result.failed_instances}
20
23
  end
21
24
 
22
25
  def prepare_headers(headers)
23
- Hash[headers.zip(headers.map { |el| el.underscore.gsub(/\s+/, '_') })]
26
+ @headers = Hash[headers.zip(headers.map { |el| el.underscore.gsub(/\s+/, '_') })]
27
+ @headers.merge!(options[:headers_rewrites])
28
+ @headers
24
29
  end
25
30
 
26
- def initialize resource, file, options
31
+ def initialize resource, file, options , extra_options = nil
27
32
  @resource = resource
28
33
  @file = file
29
34
  @options = {
@@ -36,20 +41,22 @@ module ActiveAdminImport
36
41
  :failed => [],
37
42
  :imported => 0
38
43
  }
44
+ @extra_options = extra_options
45
+ @csv_options = @options.slice(:col_sep, :row_sep)
39
46
  end
40
47
 
41
48
  def cycle(lines)
42
- lines = CSV.parse(lines.join)
43
- @result.merge!(self.store(lines, @headers.values)){|key,val1,val2| val1+val2}
49
+ @csv_lines = CSV.parse(lines.join, @csv_options)
50
+ @result.merge!(self.store){|key,val1,val2| val1+val2}
44
51
  end
45
52
 
46
53
  def import
47
- options[:before_import].call(@resource, @file, @options) if options[:before_import].is_a?(Proc)
54
+ options[:before_import].call(self) if options[:before_import].is_a?(Proc)
48
55
  lines = []
49
- batch_size = @options[:batch_size].to_i
56
+ batch_size = options[:batch_size].to_i
50
57
  IO.foreach(file.path) do |line|
51
- if @headers.empty?
52
- @headers = prepare_headers(CSV.parse(line).first)
58
+ if headers.empty?
59
+ prepare_headers(CSV.parse(line, @csv_options).first)
53
60
  else
54
61
  lines << line
55
62
  if lines.size >= batch_size
@@ -59,7 +66,7 @@ module ActiveAdminImport
59
66
  end
60
67
  end
61
68
  cycle(lines) unless lines.blank?
62
- options[:after_import].call(@result) if options[:after_import].is_a?(Proc)
69
+ options[:after_import].call(self) if options[:after_import].is_a?(Proc)
63
70
  result
64
71
  end
65
72
  end
@@ -0,0 +1,15 @@
1
+ en:
2
+ active_admin:
3
+ import: "Import"
4
+ active_admin_import:
5
+ file_format_error: "You can import only valid csv file"
6
+ no_file_error: "Please, select file to import"
7
+ imported:
8
+ one: "Successfully imported 1 %{model}"
9
+ other: "Successfully imported %{count} %{plural_model}"
10
+ failed:
11
+ one: "Failed to import 1 %{model}"
12
+ other: "Failed to import %{count} %{plural_model}"
13
+ import_model: "Import %{model}"
14
+ import_btn: "Import"
15
+ import_btn_disabled: "Wait..."
@@ -0,0 +1,15 @@
1
+ it:
2
+ active_admin:
3
+ import: "Importa"
4
+ active_admin_import:
5
+ file_format_error: "Puoi importare solo CSV conformi"
6
+ no_file_error: "Per favore, seleziona un file da importare"
7
+ imported:
8
+ one: "Importato 1 %{model} con successo"
9
+ other: "Importati %{count} %{plural_model} con successo"
10
+ failed:
11
+ one: "Importazione di 1 %{model} fallita"
12
+ other: "Importazione di %{count} %{plural_model} fallita"
13
+ import_model: "Importa %{model}"
14
+ import_btn: "Importa"
15
+ import_btn_disabled: "In attesa..."
@@ -0,0 +1,27 @@
1
+ module ActiveAdminImport
2
+ class Model
3
+ extend ActiveModel::Naming
4
+ include ActiveModel::Conversion
5
+
6
+ attr_accessor :file
7
+ attr_accessor :hint
8
+ attr_reader :attributes
9
+
10
+ def initialize(attributes={})
11
+ self.hint= attributes.delete(:hint)
12
+ @attributes = attributes
13
+ @attributes.each do |key,value|
14
+ #generate methods for instance object by attributes
15
+ singleton_class.class_eval do
16
+ define_method(key) { self.attributes[key] } unless method_defined? key
17
+ define_method("#{key}=") { |new_value| @attributes[key] = new_value } unless method_defined? "#{key}="
18
+ end
19
+ end
20
+ end
21
+
22
+ def persisted?
23
+ false
24
+ end
25
+
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveAdminImport
2
- VERSION = "1.0.1"
2
+ VERSION = "2.0.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_admin_import
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-11 00:00:00.000000000 Z
12
+ date: 2013-05-20 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: chronic
16
- requirement: &70313477456520 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: *70313477456520
25
14
  - !ruby/object:Gem::Dependency
26
15
  name: activerecord-import
27
- requirement: &70313477471600 !ruby/object:Gem::Requirement
16
+ requirement: &70124414344240 !ruby/object:Gem::Requirement
28
17
  none: false
29
18
  requirements:
30
19
  - - =
@@ -32,8 +21,8 @@ dependencies:
32
21
  version: 0.3.0
33
22
  type: :runtime
34
23
  prerelease: false
35
- version_requirements: *70313477471600
36
- description: CSV import for Active Admin
24
+ version_requirements: *70124414344240
25
+ description: The most efficient way to import for Active Admin
37
26
  email:
38
27
  - fedoronchuk@gmail.com
39
28
  executables: []
@@ -51,6 +40,9 @@ files:
51
40
  - lib/active_admin_import/dsl.rb
52
41
  - lib/active_admin_import/engine.rb
53
42
  - lib/active_admin_import/importer.rb
43
+ - lib/active_admin_import/locales/en.yml
44
+ - lib/active_admin_import/locales/it.yml
45
+ - lib/active_admin_import/model.rb
54
46
  - lib/active_admin_import/version.rb
55
47
  homepage: http://github.com/Fivell/active_admin_import
56
48
  licenses: []