baza_models 0.0.9 → 0.0.14

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 (45) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +134 -25
  3. data/.rubocop_todo.yml +47 -32
  4. data/.ruby-version +1 -0
  5. data/Gemfile +17 -19
  6. data/Gemfile.lock +126 -110
  7. data/Rakefile +5 -7
  8. data/VERSION +1 -1
  9. data/baza_models.gemspec +71 -65
  10. data/lib/baza_models/autoloader.rb +1 -0
  11. data/lib/baza_models/class_translation.rb +4 -0
  12. data/lib/baza_models/errors.rb +2 -3
  13. data/lib/baza_models/helpers/ransacker_helper.rb +2 -2
  14. data/lib/baza_models/model.rb +43 -23
  15. data/lib/baza_models/model/belongs_to_relations.rb +1 -3
  16. data/lib/baza_models/model/has_many_relations.rb +2 -2
  17. data/lib/baza_models/model/has_one_relations.rb +2 -2
  18. data/lib/baza_models/model/manipulation.rb +24 -15
  19. data/lib/baza_models/model/queries.rb +2 -0
  20. data/lib/baza_models/model/scopes.rb +1 -0
  21. data/lib/baza_models/model/validations.rb +1 -0
  22. data/lib/baza_models/query.rb +16 -14
  23. data/lib/baza_models/query/inspector.rb +2 -0
  24. data/lib/baza_models/query/pagination.rb +5 -7
  25. data/lib/baza_models/query/sql_generator.rb +3 -3
  26. data/lib/baza_models/ransacker.rb +3 -1
  27. data/lib/baza_models/ransacker/relationship_scanner.rb +4 -1
  28. data/lib/baza_models/validators/confirmation_validator.rb +1 -3
  29. data/lib/baza_models/validators/uniqueness_validator.rb +2 -4
  30. data/peak_flow.yml +4 -0
  31. data/spec/baza_models/autoloader_spec.rb +1 -1
  32. data/spec/baza_models/baza_orm_adapter_spec.rb +1 -1
  33. data/spec/baza_models/class_translation_spec.rb +4 -0
  34. data/spec/baza_models/model/has_many_relations_spec.rb +1 -1
  35. data/spec/baza_models/model/manipulation_spec.rb +3 -3
  36. data/spec/baza_models/model_spec.rb +46 -3
  37. data/spec/baza_models/query_spec.rb +14 -6
  38. data/spec/factories/organization.rb +2 -2
  39. data/spec/factories/user.rb +2 -2
  40. data/spec/spec_helper.rb +3 -6
  41. data/spec/support/database_helper.rb +6 -3
  42. data/spec/test_classes/user.rb +2 -1
  43. metadata +81 -54
  44. data/shippable.yml +0 -11
  45. data/spec/baza_models_spec.rb +0 -4
data/Rakefile CHANGED
@@ -1,18 +1,16 @@
1
- # encoding: utf-8
2
-
3
1
  require "rubygems"
4
2
  require "bundler"
5
3
  begin
6
4
  Bundler.setup(:default, :development)
7
5
  rescue Bundler::BundlerError => e
8
- $stderr.puts e.message
9
- $stderr.puts "Run `bundle install` to install missing gems"
6
+ warn e.message
7
+ warn "Run `bundle install` to install missing gems"
10
8
  exit e.status_code
11
9
  end
12
10
  require "rake"
13
11
 
14
- require "jeweler"
15
- Jeweler::Tasks.new do |gem|
12
+ require "juwelier"
13
+ Juwelier::Tasks.new do |gem|
16
14
  # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
15
  gem.name = "baza_models"
18
16
  gem.homepage = "http://github.com/kaspernj/baza_models"
@@ -23,7 +21,7 @@ Jeweler::Tasks.new do |gem|
23
21
  gem.authors = ["kaspernj"]
24
22
  # dependencies defined in Gemfile
25
23
  end
26
- Jeweler::RubygemsDotOrgTasks.new
24
+ Juwelier::RubygemsDotOrgTasks.new
27
25
 
28
26
  require "rspec/core"
29
27
  require "rspec/core/rake_task"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.9
1
+ 0.0.14
@@ -1,19 +1,19 @@
1
- # Generated by jeweler
1
+ # Generated by juwelier
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
3
+ # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: baza_models 0.0.9 ruby lib
5
+ # stub: baza_models 0.0.14 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
- s.name = "baza_models"
9
- s.version = "0.0.9"
8
+ s.name = "baza_models".freeze
9
+ s.version = "0.0.14"
10
10
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
- s.authors = ["kaspernj"]
14
- s.date = "2016-08-10"
15
- s.description = "ActiveRecord like models for the Baza database framework"
16
- s.email = "k@spernj.org"
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["kaspernj".freeze]
14
+ s.date = "2021-01-02"
15
+ s.description = "ActiveRecord like models for the Baza database framework".freeze
16
+ s.email = "k@spernj.org".freeze
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE.txt",
19
19
  "README.md"
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  ".rspec",
24
24
  ".rubocop.yml",
25
25
  ".rubocop_todo.yml",
26
+ ".ruby-version",
26
27
  "Gemfile",
27
28
  "Gemfile.lock",
28
29
  "LICENSE.txt",
@@ -67,7 +68,7 @@ Gem::Specification.new do |s|
67
68
  "lib/baza_models/validators/length_validator.rb",
68
69
  "lib/baza_models/validators/presence_validator.rb",
69
70
  "lib/baza_models/validators/uniqueness_validator.rb",
70
- "shippable.yml",
71
+ "peak_flow.yml",
71
72
  "spec/baza_models/autoloader_spec.rb",
72
73
  "spec/baza_models/baza_orm_adapter_spec.rb",
73
74
  "spec/baza_models/class_translation_spec.rb",
@@ -91,7 +92,6 @@ Gem::Specification.new do |s|
91
92
  "spec/baza_models/validators/format_validator_spec.rb",
92
93
  "spec/baza_models/validators/length_validator_spec.rb",
93
94
  "spec/baza_models/validators/uniqueness_validator_spec.rb",
94
- "spec/baza_models_spec.rb",
95
95
  "spec/factories/organization.rb",
96
96
  "spec/factories/user.rb",
97
97
  "spec/spec_helper.rb",
@@ -102,66 +102,72 @@ Gem::Specification.new do |s|
102
102
  "spec/test_classes/user.rb",
103
103
  "spec/test_classes/user_passport.rb"
104
104
  ]
105
- s.homepage = "http://github.com/kaspernj/baza_models"
106
- s.licenses = ["MIT"]
107
- s.rubygems_version = "2.4.0"
108
- s.summary = "ActiveRecord like models for the Baza database framework"
105
+ s.homepage = "http://github.com/kaspernj/baza_models".freeze
106
+ s.licenses = ["MIT".freeze]
107
+ s.rubygems_version = "3.0.6".freeze
108
+ s.summary = "ActiveRecord like models for the Baza database framework".freeze
109
109
 
110
110
  if s.respond_to? :specification_version then
111
111
  s.specification_version = 4
112
112
 
113
113
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
114
- s.add_runtime_dependency(%q<array_enumerator>, [">= 0.0.10"])
115
- s.add_runtime_dependency(%q<baza>, ["~> 0.0.21"])
116
- s.add_runtime_dependency(%q<string-cases>, [">= 0.0.3"])
117
- s.add_runtime_dependency(%q<auto_autoloader>, [">= 0.0.1"])
118
- s.add_runtime_dependency(%q<html_gen>, [">= 0.0.12"])
119
- s.add_runtime_dependency(%q<simple_delegate>, [">= 0.0.2"])
120
- s.add_development_dependency(%q<rspec>, ["~> 3.3.0"])
121
- s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
122
- s.add_development_dependency(%q<bundler>, ["~> 1.0"])
123
- s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
124
- s.add_development_dependency(%q<factory_girl>, [">= 0"])
125
- s.add_development_dependency(%q<sqlite3>, [">= 0"])
126
- s.add_development_dependency(%q<jdbc-sqlite3>, [">= 0"])
127
- s.add_development_dependency(%q<best_practice_project>, [">= 0"])
128
- s.add_development_dependency(%q<rubocop>, ["= 0.37.0"])
129
- s.add_development_dependency(%q<orm_adapter>, [">= 0"])
114
+ s.add_runtime_dependency(%q<array_enumerator>.freeze, [">= 0"])
115
+ s.add_runtime_dependency(%q<auto_autoloader>.freeze, [">= 0"])
116
+ s.add_runtime_dependency(%q<baza>.freeze, [">= 0"])
117
+ s.add_runtime_dependency(%q<html_gen>.freeze, [">= 0"])
118
+ s.add_runtime_dependency(%q<simple_delegate>.freeze, [">= 0"])
119
+ s.add_runtime_dependency(%q<string-cases>.freeze, [">= 0"])
120
+ s.add_development_dependency(%q<best_practice_project>.freeze, [">= 0"])
121
+ s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
122
+ s.add_development_dependency(%q<factory_bot>.freeze, [">= 0"])
123
+ s.add_development_dependency(%q<jdbc-sqlite3>.freeze, [">= 0"])
124
+ s.add_development_dependency(%q<juwelier>.freeze, [">= 0"])
125
+ s.add_development_dependency(%q<orm_adapter>.freeze, [">= 0"])
126
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
127
+ s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
128
+ s.add_development_dependency(%q<rubocop>.freeze, [">= 0"])
129
+ s.add_development_dependency(%q<rubocop-performance>.freeze, [">= 0"])
130
+ s.add_development_dependency(%q<rubocop-rspec>.freeze, [">= 0"])
131
+ s.add_development_dependency(%q<sqlite3>.freeze, [">= 0"])
130
132
  else
131
- s.add_dependency(%q<array_enumerator>, [">= 0.0.10"])
132
- s.add_dependency(%q<baza>, ["~> 0.0.21"])
133
- s.add_dependency(%q<string-cases>, [">= 0.0.3"])
134
- s.add_dependency(%q<auto_autoloader>, [">= 0.0.1"])
135
- s.add_dependency(%q<html_gen>, [">= 0.0.12"])
136
- s.add_dependency(%q<simple_delegate>, [">= 0.0.2"])
137
- s.add_dependency(%q<rspec>, ["~> 3.3.0"])
138
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
139
- s.add_dependency(%q<bundler>, ["~> 1.0"])
140
- s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
141
- s.add_dependency(%q<factory_girl>, [">= 0"])
142
- s.add_dependency(%q<sqlite3>, [">= 0"])
143
- s.add_dependency(%q<jdbc-sqlite3>, [">= 0"])
144
- s.add_dependency(%q<best_practice_project>, [">= 0"])
145
- s.add_dependency(%q<rubocop>, ["= 0.37.0"])
146
- s.add_dependency(%q<orm_adapter>, [">= 0"])
133
+ s.add_dependency(%q<array_enumerator>.freeze, [">= 0"])
134
+ s.add_dependency(%q<auto_autoloader>.freeze, [">= 0"])
135
+ s.add_dependency(%q<baza>.freeze, [">= 0"])
136
+ s.add_dependency(%q<html_gen>.freeze, [">= 0"])
137
+ s.add_dependency(%q<simple_delegate>.freeze, [">= 0"])
138
+ s.add_dependency(%q<string-cases>.freeze, [">= 0"])
139
+ s.add_dependency(%q<best_practice_project>.freeze, [">= 0"])
140
+ s.add_dependency(%q<bundler>.freeze, [">= 0"])
141
+ s.add_dependency(%q<factory_bot>.freeze, [">= 0"])
142
+ s.add_dependency(%q<jdbc-sqlite3>.freeze, [">= 0"])
143
+ s.add_dependency(%q<juwelier>.freeze, [">= 0"])
144
+ s.add_dependency(%q<orm_adapter>.freeze, [">= 0"])
145
+ s.add_dependency(%q<rdoc>.freeze, [">= 0"])
146
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
147
+ s.add_dependency(%q<rubocop>.freeze, [">= 0"])
148
+ s.add_dependency(%q<rubocop-performance>.freeze, [">= 0"])
149
+ s.add_dependency(%q<rubocop-rspec>.freeze, [">= 0"])
150
+ s.add_dependency(%q<sqlite3>.freeze, [">= 0"])
147
151
  end
148
152
  else
149
- s.add_dependency(%q<array_enumerator>, [">= 0.0.10"])
150
- s.add_dependency(%q<baza>, ["~> 0.0.21"])
151
- s.add_dependency(%q<string-cases>, [">= 0.0.3"])
152
- s.add_dependency(%q<auto_autoloader>, [">= 0.0.1"])
153
- s.add_dependency(%q<html_gen>, [">= 0.0.12"])
154
- s.add_dependency(%q<simple_delegate>, [">= 0.0.2"])
155
- s.add_dependency(%q<rspec>, ["~> 3.3.0"])
156
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
157
- s.add_dependency(%q<bundler>, ["~> 1.0"])
158
- s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
159
- s.add_dependency(%q<factory_girl>, [">= 0"])
160
- s.add_dependency(%q<sqlite3>, [">= 0"])
161
- s.add_dependency(%q<jdbc-sqlite3>, [">= 0"])
162
- s.add_dependency(%q<best_practice_project>, [">= 0"])
163
- s.add_dependency(%q<rubocop>, ["= 0.37.0"])
164
- s.add_dependency(%q<orm_adapter>, [">= 0"])
153
+ s.add_dependency(%q<array_enumerator>.freeze, [">= 0"])
154
+ s.add_dependency(%q<auto_autoloader>.freeze, [">= 0"])
155
+ s.add_dependency(%q<baza>.freeze, [">= 0"])
156
+ s.add_dependency(%q<html_gen>.freeze, [">= 0"])
157
+ s.add_dependency(%q<simple_delegate>.freeze, [">= 0"])
158
+ s.add_dependency(%q<string-cases>.freeze, [">= 0"])
159
+ s.add_dependency(%q<best_practice_project>.freeze, [">= 0"])
160
+ s.add_dependency(%q<bundler>.freeze, [">= 0"])
161
+ s.add_dependency(%q<factory_bot>.freeze, [">= 0"])
162
+ s.add_dependency(%q<jdbc-sqlite3>.freeze, [">= 0"])
163
+ s.add_dependency(%q<juwelier>.freeze, [">= 0"])
164
+ s.add_dependency(%q<orm_adapter>.freeze, [">= 0"])
165
+ s.add_dependency(%q<rdoc>.freeze, [">= 0"])
166
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
167
+ s.add_dependency(%q<rubocop>.freeze, [">= 0"])
168
+ s.add_dependency(%q<rubocop-performance>.freeze, [">= 0"])
169
+ s.add_dependency(%q<rubocop-rspec>.freeze, [">= 0"])
170
+ s.add_dependency(%q<sqlite3>.freeze, [">= 0"])
165
171
  end
166
172
  end
167
173
 
@@ -125,6 +125,7 @@ private
125
125
  orig_model = @models.detect { |array_model| array_model.id == orig_model_id }
126
126
 
127
127
  raise "Already autoloaded?" if orig_model.autoloads.key?(autoload_name)
128
+
128
129
  orig_model.autoloads[autoload_name] = model
129
130
 
130
131
  result.fetch(:models) << model
@@ -39,6 +39,10 @@ class BazaModels::ClassTranslation
39
39
  @klass.name.split("::").last
40
40
  end
41
41
 
42
+ def name
43
+ @klass.name
44
+ end
45
+
42
46
  def param_key
43
47
  @param_key ||= class_name_snake
44
48
  end
@@ -1,5 +1,6 @@
1
1
  class BazaModels::Errors
2
2
  class InvalidRecord < RuntimeError; end
3
+
3
4
  class RecordNotFound < RuntimeError; end
4
5
 
5
6
  def initialize
@@ -18,9 +19,7 @@ class BazaModels::Errors
18
19
  errors.each do |error|
19
20
  message = ""
20
21
 
21
- unless attribute_name == :base
22
- message << "#{StringCases.snake_to_camel(attribute_name)} "
23
- end
22
+ message << "#{StringCases.snake_to_camel(attribute_name)} " unless attribute_name == :base
24
23
 
25
24
  message << error
26
25
  messages << message
@@ -2,7 +2,7 @@ module BazaModels::Helpers::RansackerHelper
2
2
  def bm_paginate_content(collection)
3
3
  require "html_gen"
4
4
 
5
- new_params = params.dup
5
+ new_params = params.dup.permit!
6
6
  current_page = collection.page
7
7
  total_pages = collection.total_pages
8
8
 
@@ -53,7 +53,7 @@ module BazaModels::Helpers::RansackerHelper
53
53
  new_params[:q][:s] = sort_asc
54
54
  end
55
55
 
56
- href = url_for(new_params)
56
+ href = url_for(new_params.permit!)
57
57
 
58
58
  element = HtmlGen::Element.new(:a, str: label, attr: {href: href})
59
59
  element.html
@@ -16,6 +16,7 @@ class BazaModels::Model
16
16
 
17
17
  attr_accessor :data, :db
18
18
  attr_reader :changes, :errors
19
+ attr_writer :db, :table_name
19
20
 
20
21
  # Define all callback methods.
21
22
  CALLBACK_TYPES = [
@@ -45,7 +46,7 @@ class BazaModels::Model
45
46
 
46
47
  QUERY_METHODS = [
47
48
  :average, :all, :any?, :destroy_all, :each, :empty?, :ids, :maximum, :minimum, :none?, :count, :find, :first, :find_first, :last,
48
- :length, :size, :select, :includes, :joins, :group, :where, :order, :pluck, :preloads, :sum, :limit, :to_a, :accessible_by, :ransack
49
+ :length, :size, :select, :includes, :joins, :group, :where, :order, :pluck, :preloads, :sum, :limit, :accessible_by, :ransack
49
50
  ].freeze
50
51
  QUERY_METHODS.each do |query_method|
51
52
  (class << self; self; end).__send__(:define_method, query_method) do |*args, &blk|
@@ -57,6 +58,7 @@ class BazaModels::Model
57
58
  self.class.init_model
58
59
 
59
60
  reset_errors
61
+ @before_last_save = {}
60
62
  @changes = {}
61
63
 
62
64
  if args[:init]
@@ -74,9 +76,7 @@ class BazaModels::Model
74
76
  end
75
77
  end
76
78
 
77
- # rubocop:disable Style/TrivialAccessors
78
79
  def new_record?
79
- # rubocop:enable Style/TrivialAccessors
80
80
  @new_record
81
81
  end
82
82
 
@@ -86,21 +86,23 @@ class BazaModels::Model
86
86
 
87
87
  def db
88
88
  return @db if @db
89
+
89
90
  @db ||= self.class.db
90
91
  end
91
92
 
92
- attr_writer :db
93
-
94
93
  def self.attribute_names
95
94
  init_model
96
95
  @table.columns.map(&:name).map(&:clone)
97
96
  end
98
97
 
99
98
  def self.db
100
- @db = nil if @db && @db.closed?
99
+ @db = nil if
100
+ @db&.closed?
101
101
  return @db if @db
102
+
102
103
  @db ||= BazaModels.primary_db
103
104
  raise "No Baza database has been configured" unless @db
105
+
104
106
  @db
105
107
  end
106
108
 
@@ -143,8 +145,6 @@ class BazaModels::Model
143
145
  attr_writer :db, :table_name
144
146
  end
145
147
 
146
- attr_writer :table_name
147
-
148
148
  def autoloads
149
149
  @autoloads ||= {}
150
150
  @autoloads
@@ -186,7 +186,7 @@ class BazaModels::Model
186
186
  end
187
187
 
188
188
  def to_param
189
- id.to_s if id
189
+ id&.to_s
190
190
  end
191
191
 
192
192
  def to_key
@@ -200,6 +200,7 @@ class BazaModels::Model
200
200
  def reload
201
201
  @data = db.single(table_name, {id: id}, limit: 1)
202
202
  raise BazaModels::Errors::RecordNotFound unless @data
203
+
203
204
  @changes = {}
204
205
  self
205
206
  end
@@ -232,15 +233,15 @@ class BazaModels::Model
232
233
  return false unless self.class == other.class
233
234
 
234
235
  if new_record? && other.new_record?
235
- return merged_data == other.__send__(:merged_data)
236
+ merged_data == other.__send__(:merged_data)
236
237
  else
237
- return id == other.id
238
+ id == other.id
238
239
  end
239
240
  end
240
241
 
241
- # rubocop:disable Style/PredicateName
242
+ # rubocop:disable Naming/PredicateName
242
243
  def has_attribute?(name)
243
- # rubocop:enable Style/PredicateName
244
+ # rubocop:enable Naming/PredicateName
244
245
  self.class.column_names.include?(name.to_s)
245
246
  end
246
247
 
@@ -259,6 +260,7 @@ class BazaModels::Model
259
260
 
260
261
  def read_attribute(attribute_name)
261
262
  return @changes.fetch(attribute_name) if @changes.key?(attribute_name)
263
+
262
264
  @data.fetch(attribute_name)
263
265
  end
264
266
 
@@ -270,6 +272,7 @@ class BazaModels::Model
270
272
  changed = false
271
273
  @changes.each do |key, value|
272
274
  next if @data.fetch(key) == value
275
+
273
276
  changed = true
274
277
  break
275
278
  end
@@ -282,10 +285,7 @@ protected
282
285
  class << self
283
286
  attr_reader :__blank_attributes
284
287
  end
285
-
286
- # rubocop:disable Style/TrivialAccessors
287
288
  def self.model_initialized?
288
- # rubocop:enable Style/TrivialAccessors
289
289
  @model_initialized
290
290
  end
291
291
 
@@ -315,6 +315,14 @@ protected
315
315
  false
316
316
  end
317
317
  end
318
+
319
+ define_method("will_save_change_to_#{column_name}?") do
320
+ will_save_change_to_attribute?(column_name)
321
+ end
322
+
323
+ define_method("#{column_name}_before_last_save") do
324
+ attribute_before_last_save(column_name)
325
+ end
318
326
  end
319
327
 
320
328
  def reset_errors
@@ -333,7 +341,7 @@ protected
333
341
  pass_args = callback_data.fetch(:args)
334
342
  pass_args = [] if method_obj.arity == 0
335
343
 
336
- __send__(callback_data[:method_name], *pass_args)
344
+ __send__(callback_data.fetch(:method_name), *pass_args)
337
345
  else
338
346
  raise "Didn't know how to perform callbacks for #{name}"
339
347
  end
@@ -350,12 +358,11 @@ protected
350
358
  attributes.each do |attribute_name, attribute_value|
351
359
  belongs_to_relations = self.class.instance_variable_get(:@belongs_to_relations)
352
360
 
353
- if belongs_to_relations
354
- belongs_to_relations.each do |relation|
355
- if attribute_name.to_s == relation[:relation_name].to_s
356
- attribute_name = :"#{attribute_name}_id"
357
- attribute_value = attribute_value.id if attribute_value
358
- end
361
+
362
+ belongs_to_relations&.each do |relation|
363
+ if attribute_name.to_s == relation[:relation_name].to_s
364
+ attribute_name = :"#{attribute_name}_id"
365
+ attribute_value = attribute_value.id if attribute_value
359
366
  end
360
367
  end
361
368
 
@@ -374,8 +381,21 @@ protected
374
381
  new_attributes
375
382
  end
376
383
 
384
+ def attribute_before_last_save(attribute_name)
385
+ return @before_last_save.fetch(attribute_name) if @before_last_save.key?(attribute_name)
386
+
387
+ @data.fetch(attribute_name)
388
+ end
389
+
390
+ def will_save_change_to_attribute?(attribute_name)
391
+ return true if @changes.key?(attribute_name) && @changes[attribute_name] != data[attribute_name]
392
+
393
+ false
394
+ end
395
+
377
396
  def method_missing(method_name, *args, &blk)
378
397
  return @data.fetch(method_name) if @data.key?(method_name)
398
+
379
399
  super
380
400
  end
381
401
  end