sneaky-save 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9819547cbb741ef5983b1583f0dba3ea21d5e683
4
- data.tar.gz: 14647c2c9aba00d24aacf85167b5982fefb43b06
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjU4Y2NiYjczZmQwNTMxMTk1Y2IzMzRmZTk2MzIwOTFlN2RlNDc3MA==
5
+ data.tar.gz: !binary |-
6
+ OWZkMzVhZjE2NjdjY2Q5ZGJiMWZiMDFhYjhmOTI0NmRjNTMwNzBkNA==
5
7
  SHA512:
6
- metadata.gz: 64abcfe769be6e0e5011c11c45664247f33ed6e7b25e6b5d292e64569b1496b2f58281de78d9035af1b31a76e76ae41dd7d91794c3557bfd513802b9e7fe6e93
7
- data.tar.gz: 174ab52ca4496909d2aa2f3fa2cc303836f6282fab665f79c2477bf2212fd21928ee399efcdc66815b509e42d71186b57d99f02d847277926af35c3ea2464eaa
8
+ metadata.gz: !binary |-
9
+ ZGY1MzIzN2QyZDlhZDk2ODI0ZWQxMTc2N2MyN2VmMGRkODUzZDAyNGJjY2Fj
10
+ ZWQ3MzcyMmI1ZDI4ZWNiZDk4ZWViYTM3MjFhZjA2NmQ2MzQ0OTViZjFlNDlk
11
+ NTU3MDUxMTAwOWEwZTAxYTEzNTgwNTQ1NzZlZjRkOTc2NjFkODg=
12
+ data.tar.gz: !binary |-
13
+ Mzg5ZTFjZGNkMTVmM2E4OWYzNTNmMzkyZjMyZjliZWVlMGI0MGY3YzBmN2E1
14
+ ZGI3ZWJiMmE0MzJkZDUwNTkwYmIyZjU5MzFhMjk1YTJjNDg5M2I3YzFmZjlh
15
+ YjNlYmViMDRlZTQxZTc4NmM1MGQwNWVmNzIzMTMwZTViNDY5MzM=
@@ -1,9 +1,20 @@
1
+ script: bundle exec rake -t
1
2
  language: ruby
2
3
  rvm:
3
- - "1.9.3"
4
- - "2.0.0"
5
- - "2.1.2"
4
+ - "2.2.2"
5
+ - "2.3.1"
6
+ matrix:
7
+ include:
8
+ - rvm: 1.9.3
9
+ gemfile: gemfiles/rails_3_2
10
+ - rvm: 2.0.0
11
+ gemfile: gemfiles/rails_3_2
12
+ - rvm: 2.1.2
13
+ gemfile: gemfiles/rails_3_2
14
+ - rvm: 2.2.0
15
+ gemfile: gemfiles/rails_3_2
6
16
  gemfile:
7
17
  - Gemfile
18
+ - gemfiles/rails_3_2
8
19
  - gemfiles/rails_4
9
- - gemfiles/rails_3.2
20
+ - gemfiles/rails_5
File without changes
@@ -0,0 +1,7 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 5.0.0'
4
+ gem 'rake'
5
+ gem 'rspec'
6
+ gem 'sqlite3'
7
+
@@ -4,8 +4,8 @@
4
4
  #++
5
5
  module SneakySave
6
6
 
7
- # Saves record without running callbacks/validations.
8
- # Returns true if any record is changed.
7
+ # Saves the record without running callbacks/validations.
8
+ # Returns true if the record is changed.
9
9
  # @note - Does not reload updated record by default.
10
10
  # - Does not save associated collections.
11
11
  # - Saves only belongs_to relations.
@@ -19,71 +19,84 @@ module SneakySave
19
19
  end
20
20
  end
21
21
 
22
- # Saves the record raising an exception if it fails.
22
+ # Saves record without running callbacks/validations.
23
+ # @see ActiveRecord::Base#sneaky_save
23
24
  # @return [true] if save was successful.
24
- # @raise [ActiveRecord::StatementInvalid] if save failed.
25
+ # @raise [ActiveRecord::StatementInvalid] if saving failed.
25
26
  def sneaky_save!
26
27
  sneaky_create_or_update
27
28
  end
28
29
 
29
30
  protected
30
31
 
31
- def sneaky_create_or_update
32
- new_record? ? sneaky_create : sneaky_update
33
- end
32
+ def sneaky_create_or_update
33
+ new_record? ? sneaky_create : sneaky_update
34
+ end
34
35
 
35
- # Makes INSERT query in database without running any callbacks
36
- # @return [false, true]
37
- def sneaky_create
38
- if self.id.nil? && sneaky_connection.prefetch_primary_key?(self.class.table_name)
39
- self.id = sneaky_connection.next_sequence_value(self.class.sequence_name)
40
- end
36
+ # Performs INSERT query without running any callbacks
37
+ # @return [false, true]
38
+ def sneaky_create
39
+ prefetch_pk_allowed = sneaky_connection.prefetch_primary_key?(self.class.table_name)
41
40
 
42
- attributes_values = skeaky_attributes_values
41
+ if id.nil? && prefetch_pk_allowed
42
+ self.id = sneaky_connection.next_sequence_value(self.class.sequence_name)
43
+ end
43
44
 
44
- # Remove the id field for databases like Postgres which will raise an error on id being NULL
45
- if self.id.nil? && !sneaky_connection.prefetch_primary_key?(self.class.table_name)
46
- attributes_values.reject! { |key,_| key.name == 'id' }
47
- end
45
+ attributes_values = sneaky_attributes_values
48
46
 
49
- new_id = if attributes_values.empty?
50
- self.class.unscoped.insert sneaky_connection.empty_insert_statement_value
51
- else
52
- self.class.unscoped.insert attributes_values
53
- end
47
+ # Remove the id field for databases like Postgres
48
+ # which fail with id passed as NULL
49
+ if id.nil? && !prefetch_pk_allowed
50
+ attributes_values.reject! { |key, _| key.name == 'id' }
51
+ end
54
52
 
55
- @new_record = false
56
- !!(self.id ||= new_id)
53
+ if attributes_values.empty?
54
+ new_id = self.class.unscoped.insert(sneaky_connection.empty_insert_statement_value)
55
+ else
56
+ new_id = self.class.unscoped.insert(attributes_values)
57
57
  end
58
58
 
59
- # Makes update query without running callbacks
60
- # @return [false, true]
61
- def sneaky_update
59
+ @new_record = false
60
+ !!(self.id ||= new_id)
61
+ end
62
62
 
63
- # Handle no changes.
64
- return true if changes.empty?
63
+ # Performs update query without running callbacks
64
+ # @return [false, true]
65
+ def sneaky_update
66
+ return true if changes.empty?
65
67
 
66
- # Here we have changes --> save them.
67
- pk = self.class.primary_key
68
- original_id = changed_attributes.has_key?(pk) ? changes[pk].first : send(pk)
69
- !self.class.where(pk => original_id).update_all(attributes).zero?
68
+ pk = self.class.primary_key
69
+ original_id = changed_attributes.key?(pk) ? changes[pk].first : send(pk)
70
+
71
+ !self.class.where(pk => original_id).
72
+ update_all(sneaky_update_fields).zero?
73
+ end
74
+
75
+ def sneaky_attributes_values
76
+ if sneaky_new_rails?
77
+ send :arel_attributes_with_values_for_create, attribute_names
78
+ else
79
+ send :arel_attributes_values
70
80
  end
81
+ end
71
82
 
72
- def skeaky_attributes_values
73
- if ActiveRecord::VERSION::STRING.split('.').first.to_i > 3
74
- send :arel_attributes_with_values_for_create, attribute_names
75
- else
76
- send :arel_attributes_values
77
- end
83
+ def sneaky_update_fields
84
+ changes.keys.each_with_object({}) do |field, result|
85
+ result[field] = read_attribute(field)
78
86
  end
87
+ end
79
88
 
80
- def sneaky_connection
81
- if ActiveRecord::VERSION::STRING.split('.').first.to_i > 3
82
- self.class.connection
83
- else
84
- connection
85
- end
89
+ def sneaky_connection
90
+ if sneaky_new_rails?
91
+ self.class.connection
92
+ else
93
+ connection
86
94
  end
95
+ end
96
+
97
+ def sneaky_new_rails?
98
+ ActiveRecord::VERSION::STRING.to_i > 3
99
+ end
87
100
  end
88
101
 
89
102
  ActiveRecord::Base.send :include, SneakySave
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{sneaky-save}
5
- s.version = '0.1.0'
5
+ s.version = '0.1.2'
6
6
 
7
- s.date = %q{2013-12-09}
7
+ s.date = %q{2016-08-06}
8
8
  s.authors = ["Sergei Zinin (einzige)"]
9
- s.email = %q{zinin@xakep.ru}
9
+ s.email = %q{szinin@gmail.com}
10
10
  s.homepage = %q{http://github.com/einzige/sneaky-save}
11
11
 
12
12
  s.licenses = ["MIT"]
@@ -1,88 +1,110 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe SneakySave, use_connection: true do
4
- context 'new record' do
5
- subject { Fake.new(name: 'test') }
4
+ context "new record" do
5
+ subject { Fake.new(name: "test") }
6
6
 
7
- describe '#sneaky_save' do
8
- it 'returns true if everything is good' do
7
+ describe "#sneaky_save" do
8
+ it "returns true if everything is good" do
9
9
  expect(subject.sneaky_save).to eq(true)
10
10
  end
11
11
 
12
- it 'inserts the new record' do
12
+ it "inserts the new record" do
13
13
  allow(subject).to receive(:sneaky_create).once.and_return(true)
14
14
  expect(subject.sneaky_save).to eq(true)
15
15
  end
16
16
 
17
- it 'stores attributes in database' do
18
- subject.name = 'test'
17
+ it "stores attributes in database" do
18
+ subject.name = "test"
19
19
  expect(subject.sneaky_save).to eq(true)
20
20
  subject.reload
21
- expect(subject.name).to eq('test')
21
+ expect(subject.name).to eq("test")
22
22
  end
23
23
 
24
- it 'does not call any callback' do
25
- Fake.any_instance.should_not_receive :before_save_callback
24
+ it "does not call any callback" do
25
+ expect_any_instance_of(Fake).not_to receive(:before_save_callback)
26
26
  subject.sneaky_save
27
27
  end
28
28
 
29
- it 'does not call validations' do
29
+ it "does not call validations" do
30
30
  expect_any_instance_of(Fake).to_not receive(:valid?)
31
31
  subject.sneaky_save
32
32
  end
33
33
  end
34
34
 
35
- describe '#sneaky_save!' do
36
- it 'raises an exception when insert fails' do
35
+ describe "#sneaky_save!" do
36
+ it "raises an exception when insert fails" do
37
37
  subject.name = nil
38
38
  expect { subject.sneaky_save! }.to raise_error(ActiveRecord::StatementInvalid)
39
39
  end
40
+
41
+ context "associations" do
42
+ let(:belonger) { Belonger.create! }
43
+
44
+ it "stores associations" do
45
+ subject.belonger = belonger
46
+ subject.sneaky_save!
47
+ subject.reload
48
+ expect(subject.belonger_id).to eq(belonger.id)
49
+ end
50
+ end
40
51
  end
41
52
  end
42
53
 
43
- context 'existing record' do
44
- subject { Fake.create! :name => 'test' }
54
+ context "existing record" do
55
+ subject { Fake.create!(name: "test") }
45
56
 
46
- describe '#sneaky_save' do
47
- context 'record is not changed' do
48
- it 'does nothing' do
49
- Fake.should_not_receive(:update_all)
57
+ describe "#sneaky_save" do
58
+ context "record is not changed" do
59
+ it "does nothing" do
60
+ expect(Fake).not_to receive(:update_all)
50
61
  expect(subject.sneaky_save).to eq(true)
51
62
  end
52
63
  end
53
64
 
54
- context 'record is changed' do
55
- it 'updates attributes' do
56
- subject.should_receive(:sneaky_update).once.and_return true
57
- subject.name = 'new name'
65
+ context "record is changed" do
66
+ it "updates attributes" do
67
+ expect(subject).to receive(:sneaky_update).once.and_return true
68
+ subject.name = "new name"
58
69
  expect(subject.sneaky_save).to eq(true)
59
70
  end
60
71
 
61
- it 'stores attributes in database' do
62
- subject.name = 'new name'
72
+ it "stores attributes in database" do
73
+ subject.name = "new name"
63
74
  expect(subject.sneaky_save).to eq(true)
64
75
  subject.reload
65
- expect(subject.name).to eq('new name')
76
+ expect(subject.name).to eq("new name")
66
77
  expect(subject.sneaky_save).to eq(true)
67
78
  end
68
79
 
69
- it 'does not call any callback' do
70
- subject.should_not_receive :before_save_callback
80
+ it "does not call any callback" do
81
+ expect(subject).not_to receive(:before_save_callback)
71
82
  subject.sneaky_save
72
83
  end
73
84
 
74
- it 'does not call validations' do
75
- subject.should_not_receive :valid?
85
+ it "does not call validations" do
86
+ expect(subject).not_to receive(:valid?)
76
87
  subject.sneaky_save
77
88
  end
78
89
  end
79
90
  end
80
91
 
81
- describe '#sneaky_save!' do
82
- it 'raises an exception when update fails' do
92
+ describe "#sneaky_save!" do
93
+ it "raises an exception when update fails" do
83
94
  subject.name = nil
84
95
  expect { subject.sneaky_save! }.to raise_error(ActiveRecord::StatementInvalid)
85
96
  end
97
+
98
+ context "associations" do
99
+ let(:belonger) { Belonger.create! }
100
+
101
+ it "stores associations" do
102
+ subject.belonger = belonger
103
+ subject.sneaky_save!
104
+ subject.reload
105
+ expect(subject.belonger_id).to eq(belonger.id)
106
+ end
107
+ end
86
108
  end
87
109
  end
88
110
  end
@@ -1,23 +1,33 @@
1
- require 'active_record'
2
- require 'sqlite3'
3
- require 'sneaky-save'
1
+ require "active_record"
2
+ require "sqlite3"
3
+ require "sneaky-save"
4
4
 
5
- shared_context 'use connection', use_connection: true do
6
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
5
+ shared_context "use connection", use_connection: true do
6
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
7
7
 
8
8
  ActiveRecord::Schema.define do
9
- create_table 'fakes' do |table|
9
+ create_table "fakes" do |table|
10
10
  table.column :name, :string, null: false
11
+ table.column :belonger_id, :integer
12
+ end
13
+
14
+ create_table "belongers" do |table|
11
15
  end
12
16
  end
13
17
 
18
+ class Belonger < ActiveRecord::Base
19
+ has_many :fakes
20
+ end
21
+
14
22
  class Fake < ActiveRecord::Base
15
23
  validates :name, presence: true
16
24
 
17
25
  before_save :before_save_callback
18
26
 
27
+ belongs_to :belonger
28
+
19
29
  def before_save_callback
20
- 'BEFORE SAVE CALLED'
30
+ "BEFORE SAVE CALLED"
21
31
  end
22
32
  end
23
33
  end
metadata CHANGED
@@ -1,59 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sneaky-save
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergei Zinin (einzige)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-09 00:00:00.000000000 Z
11
+ date: 2016-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  description: ActiveRecord extension. Allows to save record without calling callbacks
42
42
  and validations.
43
- email: zinin@xakep.ru
43
+ email: szinin@gmail.com
44
44
  executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files:
47
47
  - README.md
48
48
  files:
49
- - ".gitignore"
50
- - ".travis.yml"
49
+ - .gitignore
50
+ - .travis.yml
51
51
  - Gemfile
52
52
  - README.md
53
53
  - Rakefile
54
54
  - VERSION
55
- - gemfiles/rails_3.2
55
+ - gemfiles/rails_3_2
56
56
  - gemfiles/rails_4
57
+ - gemfiles/rails_5
57
58
  - lib/sneaky-save.rb
58
59
  - sneaky-save.gemspec
59
60
  - spec/lib/sneaky_save_spec.rb
@@ -68,17 +69,17 @@ require_paths:
68
69
  - lib
69
70
  required_ruby_version: !ruby/object:Gem::Requirement
70
71
  requirements:
71
- - - ">="
72
+ - - ! '>='
72
73
  - !ruby/object:Gem::Version
73
74
  version: '0'
74
75
  required_rubygems_version: !ruby/object:Gem::Requirement
75
76
  requirements:
76
- - - ">="
77
+ - - ! '>='
77
78
  - !ruby/object:Gem::Version
78
79
  version: '0'
79
80
  requirements: []
80
81
  rubyforge_project:
81
- rubygems_version: 2.2.2
82
+ rubygems_version: 2.1.5
82
83
  signing_key:
83
84
  specification_version: 4
84
85
  summary: Allows to save record without calling callbacks and validations.