mass_insert 0.0.2 → 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.
Files changed (31) hide show
  1. data/README.md +3 -3
  2. data/lib/mass_insert/adapters.rb +0 -1
  3. data/lib/mass_insert/adapters/adapter.rb +1 -7
  4. data/lib/mass_insert/adapters/column_value.rb +33 -29
  5. data/lib/mass_insert/adapters/helpers.rb +3 -2
  6. data/lib/mass_insert/adapters/helpers/abstract_query.rb +48 -0
  7. data/lib/mass_insert/adapters/helpers/sanitizer.rb +6 -0
  8. data/lib/mass_insert/adapters/mysql2_adapter.rb +1 -1
  9. data/lib/mass_insert/base.rb +49 -20
  10. data/lib/mass_insert/query_builder.rb +6 -6
  11. data/lib/mass_insert/version.rb +1 -1
  12. data/spec/active_record_dummy/Gemfile +1 -1
  13. data/spec/active_record_dummy/config/database.yml +1 -1
  14. data/spec/mass_insert/adapters/adapter_spec.rb +23 -45
  15. data/spec/mass_insert/adapters/column_value_spec.rb +107 -154
  16. data/spec/mass_insert/adapters/{abstract_query_spec.rb → helpers/abstract_query_spec.rb} +23 -27
  17. data/spec/mass_insert/adapters/helpers/sanitizer_spec.rb +16 -9
  18. data/spec/mass_insert/adapters/helpers/timestamp_spec.rb +11 -15
  19. data/spec/mass_insert/adapters/helpers_spec.rb +7 -3
  20. data/spec/mass_insert/adapters/mysql_adapter_spec.rb +6 -10
  21. data/spec/mass_insert/adapters/postgresql_adapter_spec.rb +4 -8
  22. data/spec/mass_insert/adapters/sqlite3_adapter_spec.rb +24 -30
  23. data/spec/mass_insert/adapters/sqlserver_adapter_spec.rb +16 -21
  24. data/spec/mass_insert/adapters_spec.rb +8 -12
  25. data/spec/mass_insert/base_spec.rb +13 -13
  26. data/spec/mass_insert/process_control_spec.rb +33 -40
  27. data/spec/mass_insert/query_builder_spec.rb +20 -24
  28. data/spec/mass_insert/query_execution_spec.rb +13 -16
  29. data/spec/mass_insert_spec.rb +6 -6
  30. metadata +7 -7
  31. data/lib/mass_insert/adapters/abstract_query.rb +0 -47
data/README.md CHANGED
@@ -77,15 +77,15 @@ OR directly
77
77
 
78
78
  Some options that you can include are...
79
79
 
80
- 1. `:table_name` : Default value is the table name to your model. This options rarely needs to change but you can do it if you pass a string with the table name. Example...
80
+ `:table_name` : Default value is the table name to your model. This options rarely needs to change but you can do it if you pass a string with the table name. Example...
81
81
 
82
82
  options = {:table_name => "users"}
83
83
 
84
- 2. `:primary_key` : Default value is `:id`. You can change the name of primary key column send it a symbol with the column name.
84
+ `:primary_key` : Default value is `:id`. You can change the name of primary key column send it a symbol with the column name.
85
85
 
86
86
  options = {:primary_key => :post_id}
87
87
 
88
- 3. `:primary_key_mode` : Default value is `:auto`. When is `:auto` MassInsert knows that the database will generate the value of the primary key column automatically. If you pass `:manual` as primary key mode you need to create your value hashes with the key and value of the primary key column.
88
+ `:primary_key_mode` : Default value is `:auto`. When is `:auto` MassInsert knows that the database will generate the value of the primary key column automatically. If you pass `:manual` as primary key mode you need to create your value hashes with the key and value of the primary key column.
89
89
 
90
90
  options = {:primary_key_mode => :manual}
91
91
 
@@ -1,7 +1,6 @@
1
1
  module MassInsert
2
2
  module Adapters
3
3
  autoload :Adapter, 'mass_insert/adapters/adapter.rb'
4
- autoload :AbstractQuery, 'mass_insert/adapters/abstract_query.rb'
5
4
  autoload :ColumnValue, 'mass_insert/adapters/column_value.rb'
6
5
  autoload :Helpers, 'mass_insert/adapters/helpers.rb'
7
6
  autoload :Mysql2Adapter, 'mass_insert/adapters/mysql2_adapter.rb'
@@ -4,7 +4,7 @@ module MassInsert
4
4
  # be executed. The methods here provides a functionality that be required
5
5
  # in all the adapters.
6
6
  class Adapter
7
- include AbstractQuery
7
+ include Helpers::AbstractQuery
8
8
  include Helpers::Timestamp
9
9
  include Helpers::Sanitizer
10
10
 
@@ -27,12 +27,6 @@ module MassInsert
27
27
  options[:table_name]
28
28
  end
29
29
 
30
- # Returns an array with the column names in the database table like
31
- # a symbols.
32
- def table_columns
33
- class_name.column_names.map(&:to_sym)
34
- end
35
-
36
30
  # Returns the array with the column names valid to be included into the
37
31
  # query string according to the options.
38
32
  def column_names
@@ -49,15 +49,17 @@ module MassInsert
49
49
 
50
50
  # Returns a single column string value with the correct format and
51
51
  # according to the database configuration, column type and presence.
52
+ # If the row hash does not include the value to this column return the
53
+ # default value according to database configuration.
52
54
  def build
53
- self.send "column_value_#{column_type}".to_sym
55
+ column_value.nil? ? default_value : send(:"column_value_#{column_type}")
54
56
  end
55
57
 
56
58
  # Returns the correct value when the column value is string, text,
57
- # date, time, datetime, timestamp. There are alias method to the
59
+ # date, time, datetime, timestamp. There are alias methods to the
58
60
  # other column types that need a similar query value.
59
61
  def column_value_string
60
- column_value.nil? ? default_value : "'#{column_value}'"
62
+ "'#{column_value}'"
61
63
  end
62
64
  alias :column_value_text :column_value_string
63
65
  alias :column_value_date :column_value_string
@@ -66,40 +68,42 @@ module MassInsert
66
68
  alias :column_value_timestamp :column_value_string
67
69
  alias :column_value_binary :column_value_string
68
70
 
69
- # Returns the correct value to column value is integer. If the row
70
- # hash does not include the value to this column return the default
71
- # value according to database configuration.
71
+ # Returns the correct value to integer column. The column values is
72
+ # converted to integer to be sure that the value is correct to be
73
+ # persisted into the database and after it, it's converted to string.
72
74
  def column_value_integer
73
- column_value.nil? ? default_value : column_value.to_i.to_s
75
+ column_value.to_i.to_s
74
76
  end
75
77
 
76
- # Returns the correct value to column value is decimal. There is an
77
- # alias method to float type. If the row hash does not include the
78
- # value to this column return the default value according to database
79
- # configuration.
78
+ # Returns the correct value to decimal column. There is an alias method
79
+ # to float type. The column values is converted to decimal to be sure
80
+ # that the value is correct to be persisted into the database and after
81
+ # it, it's converted to string.
80
82
  def column_value_decimal
81
- column_value.nil? ? default_value : column_value.to_f.to_s
83
+ column_value.to_f.to_s
82
84
  end
83
85
  alias :column_value_float :column_value_decimal
84
86
 
85
- # Returns the correct value to column value is boolean. If the row
86
- # hash does not include the value to this column return the default
87
- # value according to database configuration.
87
+ # Returns the correct value to boolean column. This column calls the
88
+ # correct method according to the database adapter to return the correct
89
+ # value to that database engine.
88
90
  def column_value_boolean
89
- case adapter
90
- when "mysql2", "postgresql", "sqlserver"
91
- if column_value.nil?
92
- default_value
93
- else
94
- column_value ? "true" : "false"
95
- end
96
- when "sqlite3"
97
- if column_value.nil?
98
- default_value
99
- else
100
- column_value ? "1" : "0"
101
- end
102
- end
91
+ self.send(:"#{adapter}_column_value_boolean")
92
+ end
93
+
94
+ # Returns the column value to boolean column like a string. If the
95
+ # column value exists returns a true string else false string. There
96
+ # are alias methods to the database engines that works similarity.
97
+ def mysql2_column_value_boolean
98
+ column_value ? "true" : "false"
99
+ end
100
+ alias :postgresql_column_value_boolean :mysql2_column_value_boolean
101
+ alias :sqlserver_column_value_boolean :mysql2_column_value_boolean
102
+
103
+ # Returns the column value to boolean column like a string. If the
104
+ # column value exists returns a "1" else "0".
105
+ def sqlite3_column_value_boolean
106
+ column_value ? "1" : "0"
103
107
  end
104
108
 
105
109
  end
@@ -1,8 +1,9 @@
1
1
  module MassInsert
2
2
  module Adapters
3
3
  module Helpers
4
- autoload :Timestamp, 'mass_insert/adapters/helpers/timestamp.rb'
5
- autoload :Sanitizer, 'mass_insert/adapters/helpers/sanitizer.rb'
4
+ autoload :AbstractQuery, 'mass_insert/adapters/helpers/abstract_query.rb'
5
+ autoload :Timestamp, 'mass_insert/adapters/helpers/timestamp.rb'
6
+ autoload :Sanitizer, 'mass_insert/adapters/helpers/sanitizer.rb'
6
7
  end
7
8
  end
8
9
  end
@@ -0,0 +1,48 @@
1
+ module MassInsert
2
+ module Adapters
3
+ module Helpers
4
+ module AbstractQuery
5
+
6
+ # Returns a begin string to a basic mysql query insertion. Include
7
+ # the class table_name and it's included in the string.
8
+ def begin_string
9
+ "INSERT INTO #{table_name} "
10
+ end
11
+
12
+ # Returns a string with the column names to the class table name
13
+ # and divided by commas.
14
+ def string_columns
15
+ "(#{column_names.join(", ")}) "
16
+ end
17
+
18
+ # Returns the string with all the row values that will be included
19
+ # in the sql string.
20
+ def string_values
21
+ "VALUES (#{string_rows_values});"
22
+ end
23
+
24
+ # Gives the correct format to the values string to all rows. This
25
+ # functions calls a function that will generate a single string row
26
+ # and at the end all the strings are concatenated.
27
+ def string_rows_values
28
+ values.map{ |row| string_single_row_values(row) }.join("), (")
29
+ end
30
+
31
+ # Returns the row column values string to be added in query string
32
+ # according to the type column and values.
33
+ # Before that row is prepared with the correct values.
34
+ def string_single_row_values row
35
+ row.merge!(timestamp_values) if timestamp?
36
+ column_names.map{ |col| string_single_value(row, col) }.join(", ")
37
+ end
38
+
39
+ # Returns a single column string value with the correct format and
40
+ # according to the database configuration, column type and presence.
41
+ def string_single_value row, column
42
+ ColumnValue.new(row, column, options).build
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -3,6 +3,12 @@ module MassInsert
3
3
  module Helpers
4
4
  module Sanitizer
5
5
 
6
+ # Returns an array with the column names in the database table like
7
+ # a symbols.
8
+ def table_columns
9
+ class_name.column_names.map(&:to_sym)
10
+ end
11
+
6
12
  # Update the array with the columns names according to the options
7
13
  # and prepare the columns array with only valid columns.
8
14
  def sanitized_columns
@@ -5,7 +5,7 @@ module MassInsert
5
5
  # This method is overwrite because the timestamp format to this
6
6
  # database engine does not need precision in nanoseconds.
7
7
  def timestamp_format
8
- @timestamp_format ||= "%Y-%m-%d %H:%M:%S"
8
+ "%Y-%m-%d %H:%M:%S"
9
9
  end
10
10
 
11
11
  # This functions calls the necessary functions to create a complete
@@ -1,7 +1,10 @@
1
1
  module MassInsert
2
2
  module Base
3
3
 
4
- # This method do a mass database insertion. Example...
4
+ # = MassInsert
5
+ #
6
+ # This method does a mass database insertion just calling it from your
7
+ # ActiveRecord model. Example...
5
8
  #
6
9
  # User.mass_insert(values)
7
10
  #
@@ -14,21 +17,52 @@ module MassInsert
14
17
  # {:name => "user name", :email => "user email"}
15
18
  # ]
16
19
  #
20
+ # == Options
21
+ #
22
+ # And MassInset gem allow you to send it some options as second param
23
+ # Example...
24
+ #
25
+ # User.mass_insert(values, options)
26
+ #
27
+ # === table_name
28
+ #
29
+ # Default value is the table name to your model. This options rarely
30
+ # needs to change but you can do it if you pass a string with the table
31
+ # name. Example...
32
+ #
33
+ # options = {:table_name => "users"}
34
+ #
35
+ # === primary_key
36
+ #
37
+ # Default value is :id. You can change the name of primary key column
38
+ # send it a symbol with the column name.
39
+ #
40
+ # options = {:primary_key => :post_id}
41
+ #
42
+ # === primary_key_mode
43
+ #
44
+ # Default value is :auto. When is :auto MassInsert knows that database
45
+ # will generate the value of the primary key column automatically. If
46
+ # you pass :manual as primary key mode you need to create your value
47
+ # hashes with the key and value of the primary key column.
48
+ #
49
+ # options = {:primary_key_mode => :manual}
50
+ #
17
51
  # When a class that inherit from ActiveRecord::Base calls this method
18
52
  # is going to extend the methods in ClassMethods module. This module
19
53
  # contains some methods that provides some necessary functionality.
20
54
  #
21
55
  # After extends the class with methods in ClassMethods module. The
22
56
  # options that were passed by params are sanitized in the method
23
- # called mass_insert_options_sanitized to be passed by params to
24
- # do ProcessControl instance. The values are passed too.
57
+ # called mass_insert_options to be passed by params to ProcessControl
58
+ # class. The record values are passed too.
25
59
  def mass_insert values, args = {}
26
60
  class_eval do
27
61
  extend ClassMethods
28
62
  end
29
63
 
30
64
  options = mass_insert_options(args)
31
- @mass_insert_process = MassInsert::ProcessControl.new(values, options)
65
+ @mass_insert_process = ProcessControl.new(values, options)
32
66
  @mass_insert_process.start
33
67
  end
34
68
 
@@ -43,22 +77,17 @@ module MassInsert
43
77
  end
44
78
 
45
79
  private
46
-
47
- def mass_insert_options args = {}
48
- # prepare default options that come in the class that invokes the
49
- # mass_insert function.
50
- args[:class_name] ||= self
51
- args[:table_name] ||= self.table_name
52
-
53
- # prepare attributes options that were configured by the user and
54
- # if the options weren't passed, they would be initialized with the
55
- # default values.
56
- args[:primary_key] ||= :id
57
- args[:primary_key_mode] ||= :auto
58
-
59
- # Returns the arguments but sanitized and ready to be used. This
60
- # args will be passed by params to ProcessControl class.
61
- args
80
+ # Sanitizes the MassInset options that were passed by params.
81
+ # Prepares default options that come in the class that invokes the
82
+ # mass_insert function and attributes options that were configured
83
+ # and if the options weren't passed, they would be initialized with
84
+ # the default values.
85
+ def mass_insert_options options = {}
86
+ options[:class_name] ||= self
87
+ options[:table_name] ||= self.table_name
88
+ options[:primary_key] ||= :id
89
+ options[:primary_key_mode] ||= :auto
90
+ options
62
91
  end
63
92
 
64
93
  end
@@ -12,7 +12,7 @@ module MassInsert
12
12
  # sql string ready to be executed and returns it to be execute in
13
13
  # the QueryExecution class.
14
14
  def build
15
- adapter_instance_class.execute
15
+ adapter_class.new(values, options).execute
16
16
  end
17
17
 
18
18
  # Returns a string that contains the adapter type previosly
@@ -25,16 +25,16 @@ module MassInsert
25
25
  # instance will be called to generate the sql string. The values
26
26
  # and options are passed by params when the correct adapter class
27
27
  # is instanced.
28
- def adapter_instance_class
28
+ def adapter_class
29
29
  case adapter
30
30
  when "mysql2"
31
- Adapters::Mysql2Adapter.new(values, options)
31
+ Adapters::Mysql2Adapter
32
32
  when "postgresql"
33
- Adapters::PostgreSQLAdapter.new(values, options)
33
+ Adapters::PostgreSQLAdapter
34
34
  when "sqlite3"
35
- Adapters::SQLite3Adapter.new(values, options)
35
+ Adapters::SQLite3Adapter
36
36
  when "sqlserver"
37
- Adapters::SQLServerAdapter.new(values, options)
37
+ Adapters::SQLServerAdapter
38
38
  end
39
39
  end
40
40
 
@@ -1,3 +1,3 @@
1
1
  module MassInsert
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -8,7 +8,7 @@ gem 'rails', '3.2.13'
8
8
  gem 'sqlite3'
9
9
  gem 'mysql2'
10
10
  gem 'pg'
11
- gem 'mass_insert', :git => 'git@github.com:alejandrogutierrez/mass_insert.git', :branch => 'master'
11
+ gem 'mass_insert'
12
12
 
13
13
  # Gems used only for assets and not required
14
14
  # in production environments by default.
@@ -12,7 +12,7 @@ mysql2:
12
12
  adapter: mysql2
13
13
  database: mysql2_test
14
14
  user: root
15
- password: D3s4rr0ll0
15
+ password: D3s4rr0ll0$.
16
16
  pool: 5
17
17
  timeout: 5000
18
18
  encoding: utf8
@@ -3,113 +3,91 @@ require "./lib/mass_insert"
3
3
  require "./spec/dummy_models/test"
4
4
 
5
5
  describe MassInsert::Adapters::Adapter do
6
- before :each do
7
- @adapter = MassInsert::Adapters::Adapter.new([], {})
8
- end
9
-
10
- subject{ @adapter }
6
+ let!(:subject){ MassInsert::Adapters::Adapter.new([], {}) }
11
7
 
12
8
  describe "instance methods" do
13
9
  describe "#initialize" do
14
-
15
- before :each do
16
- @values = [{:name => "name"}]
17
- @options = {:option_one => 10}
18
- @adapter = MassInsert::Adapters::Adapter.new(@values, @options)
19
- end
10
+ let(:adapter){MassInsert::Adapters::Adapter.new("values", "options")}
20
11
 
21
12
  it "should initialize the values" do
22
- @adapter.values.should eq(@values)
13
+ expect(adapter.values).to eq("values")
23
14
  end
24
15
 
25
16
  it "should initialize the options" do
26
- @adapter.options.should eq(@options)
17
+ expect(adapter.options).to eq("options")
27
18
  end
28
19
  end
29
20
 
30
21
  describe "#class_name" do
31
22
  it "should respond to class name method" do
32
- subject.respond_to?(:class_name).should be_true
23
+ expect(subject).to respond_to(:class_name)
33
24
  end
34
25
 
35
26
  it "should returns the class_name in options" do
36
27
  subject.options = {:class_name => Test}
37
- subject.class_name.should eq(Test)
28
+ expect(subject.class_name).to eq(Test)
38
29
  end
39
30
  end
40
31
 
41
32
  describe "#table_name" do
42
33
  it "should respond to table_name method" do
43
- subject.respond_to?(:table_name).should be_true
34
+ expect(subject).to respond_to(:table_name)
44
35
  end
45
36
 
46
37
  it "should returns the table_name in options" do
47
38
  subject.options = {:table_name => "users"}
48
- subject.table_name.should eq("users")
39
+ expect(subject.table_name).to eq("users")
49
40
  end
50
41
  end
51
42
 
52
- describe "#table_columns" do
53
- it "should respond to table_columns method" do
54
- subject.respond_to?(:table_columns).should be_true
55
- end
56
-
57
- it "should returns the table_columns in ActiveRecord class" do
58
- subject.options = {:class_name => Test}
59
- columns = [:id, :name, :email]
60
- subject.table_columns.should eq(columns)
43
+ describe "#column_names" do
44
+ before :each do
45
+ subject.options.merge!({
46
+ :class_name => Test,
47
+ :primary_key => :id,
48
+ :primary_key_mode => :auto
49
+ })
61
50
  end
62
- end
63
51
 
64
- describe "#column_names" do
65
52
  it "should respond to column_names method" do
66
- subject.respond_to?(:column_names).should be_true
53
+ expect(subject).to respond_to(:column_names)
67
54
  end
68
55
 
69
56
  context "when primary_key is auto" do
70
57
  it "should return an array without primary key column" do
71
- subject.options.merge!({
72
- :class_name => Test,
73
- :primary_key => :id,
74
- :primary_key_mode => :auto
75
- })
76
58
  column_names = [:name, :email]
77
- subject.column_names.should eq(column_names)
59
+ expect(subject.column_names).to eq(column_names)
78
60
  end
79
61
  end
80
62
 
81
63
  context "when primary key is manual" do
82
64
  it "should return an array with primary key column" do
83
- subject.options.merge!({
84
- :class_name => Test,
85
- :primary_key => :id,
86
- :primary_key_mode => :manual
87
- })
65
+ subject.options.merge!({:primary_key_mode => :manual})
88
66
  column_names = [:id, :name, :email]
89
- subject.column_names.should eq(column_names)
67
+ expect(subject.column_names).to eq(column_names)
90
68
  end
91
69
  end
92
70
  end
93
71
 
94
72
  describe "#primary_key" do
95
73
  it "should respond to primary_key method" do
96
- subject.respond_to?(:primary_key).should be_true
74
+ expect(subject).to respond_to(:primary_key)
97
75
  end
98
76
 
99
77
  it "should returns the primary_key in options" do
100
78
  subject.options = {:primary_key => :user_id}
101
- subject.primary_key.should eq(:user_id)
79
+ expect(subject.primary_key).to eq(:user_id)
102
80
  end
103
81
  end
104
82
 
105
83
  describe "#primary_key_mode" do
106
84
  it "should respond to primary_key_mode method" do
107
- subject.respond_to?(:primary_key_mode).should be_true
85
+ expect(subject).to respond_to(:primary_key_mode)
108
86
  end
109
87
 
110
88
  it "should returns the primary_key_mode in options" do
111
89
  subject.options = {:primary_key_mode => :auto}
112
- subject.primary_key_mode.should eq(:auto)
90
+ expect(subject.primary_key_mode).to eq(:auto)
113
91
  end
114
92
  end
115
93