active_admin_import 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []