sneaky-save 0.1.0 → 0.1.2

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.
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.