mass_insert 0.0.2 → 0.0.3

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