duck_record 0.0.16 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,23 +7,23 @@ module DuckRecord
7
7
  include ActiveModel::ForbiddenAttributesProtection
8
8
 
9
9
  # Alias for ActiveModel::AttributeAssignment#assign_attributes. See ActiveModel::AttributeAssignment.
10
- def attributes=(attributes, force_write_readonly: false)
11
- assign_attributes(attributes, force_write_readonly: force_write_readonly)
10
+ def attributes=(attributes)
11
+ assign_attributes(attributes)
12
12
  end
13
13
 
14
- def assign_attributes(new_attributes, force_write_readonly: false)
14
+ def assign_attributes(new_attributes)
15
15
  unless new_attributes.respond_to?(:stringify_keys)
16
16
  raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
17
17
  end
18
18
  return if new_attributes.nil? || new_attributes.empty?
19
19
 
20
20
  attributes = new_attributes.stringify_keys
21
- _assign_attributes(sanitize_for_mass_assignment(attributes), force_write_readonly: force_write_readonly)
21
+ _assign_attributes(sanitize_for_mass_assignment(attributes))
22
22
  end
23
23
 
24
24
  private
25
25
 
26
- def _assign_attributes(attributes, force_write_readonly: false)
26
+ def _assign_attributes(attributes)
27
27
  multi_parameter_attributes = {}
28
28
  nested_parameter_attributes = {}
29
29
 
@@ -36,21 +36,21 @@ module DuckRecord
36
36
  end
37
37
 
38
38
  attributes.each do |k, v|
39
- _assign_attribute(k, v, force_write_readonly: force_write_readonly)
39
+ _assign_attribute(k, v)
40
40
  end
41
41
 
42
42
  unless nested_parameter_attributes.empty?
43
- assign_nested_parameter_attributes(nested_parameter_attributes, force_write_readonly: force_write_readonly)
43
+ assign_nested_parameter_attributes(nested_parameter_attributes)
44
44
  end
45
45
 
46
46
  unless multi_parameter_attributes.empty?
47
- assign_multiparameter_attributes(multi_parameter_attributes, force_write_readonly: force_write_readonly)
47
+ assign_multiparameter_attributes(multi_parameter_attributes)
48
48
  end
49
49
  end
50
50
 
51
51
  # Assign any deferred nested attributes after the base attributes have been set.
52
- def assign_nested_parameter_attributes(pairs, force_write_readonly: false)
53
- pairs.each { |k, v| _assign_attribute(k, v, force_write_readonly: force_write_readonly) }
52
+ def assign_nested_parameter_attributes(pairs)
53
+ pairs.each { |k, v| _assign_attribute(k, v) }
54
54
  end
55
55
 
56
56
  # Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
@@ -59,14 +59,13 @@ module DuckRecord
59
59
  # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
60
60
  # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
61
61
  # f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
62
- def assign_multiparameter_attributes(pairs, force_write_readonly: false)
62
+ def assign_multiparameter_attributes(pairs)
63
63
  execute_callstack_for_multiparameter_attributes(
64
- extract_callstack_for_multiparameter_attributes(pairs),
65
- force_write_readonly: force_write_readonly
64
+ extract_callstack_for_multiparameter_attributes(pairs)
66
65
  )
67
66
  end
68
67
 
69
- def execute_callstack_for_multiparameter_attributes(callstack, force_write_readonly: false)
68
+ def execute_callstack_for_multiparameter_attributes(callstack)
70
69
  errors = []
71
70
  callstack.each do |name, values_with_empty_parameters|
72
71
  begin
@@ -75,7 +74,7 @@ module DuckRecord
75
74
  else
76
75
  values = values_with_empty_parameters
77
76
  end
78
- send("#{name}=", values, force_write_readonly: force_write_readonly)
77
+ send("#{name}=", values)
79
78
  rescue => ex
80
79
  errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
81
80
  end
@@ -108,9 +107,9 @@ module DuckRecord
108
107
  multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
109
108
  end
110
109
 
111
- def _assign_attribute(k, v, force_write_readonly: false)
110
+ def _assign_attribute(k, v)
112
111
  if respond_to?("#{k}=")
113
- public_send("#{k}=", v, force_write_readonly: force_write_readonly)
112
+ public_send("#{k}=", v)
114
113
  else
115
114
  raise UnknownAttributeError.new(self, k)
116
115
  end
@@ -15,9 +15,9 @@ module DuckRecord
15
15
  DuckRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
16
16
 
17
17
  generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
18
- def __temp__#{safe_name}=(value, force_write_readonly: false)
18
+ def __temp__#{safe_name}=(value)
19
19
  name = ::DuckRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
20
- write_attribute(name, value, force_write_readonly: force_write_readonly)
20
+ write_attribute(name, value)
21
21
  end
22
22
  alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
23
23
  undef_method :__temp__#{safe_name}=
@@ -28,32 +28,35 @@ module DuckRecord
28
28
  # Updates the attribute identified by <tt>attr_name</tt> with the
29
29
  # specified +value+. Empty strings for Integer and Float columns are
30
30
  # turned into +nil+.
31
- def write_attribute(attr_name, value, force_write_readonly: false)
32
- name = if self.class.attribute_alias?(attr_name)
33
- self.class.attribute_alias(attr_name).to_s
34
- else
35
- attr_name.to_s
36
- end
31
+ def write_attribute(attr_name, value)
32
+ name =
33
+ if self.class.attribute_alias?(attr_name)
34
+ self.class.attribute_alias(attr_name).to_s
35
+ else
36
+ attr_name.to_s
37
+ end
37
38
 
38
- write_attribute_with_type_cast(name, value, true, force_write_readonly: force_write_readonly)
39
+ if self.class.readonly_attributes.include?(name) && attr_readonly_enabled?
40
+ return
41
+ end
42
+
43
+ write_attribute_with_type_cast(name, value, true)
39
44
  end
40
45
 
41
- def raw_write_attribute(attr_name, value, force_write_readonly: false) # :nodoc:
42
- write_attribute_with_type_cast(attr_name, value, false, force_write_readonly: force_write_readonly)
46
+ def raw_write_attribute(attr_name, value) # :nodoc:
47
+ write_attribute_with_type_cast(attr_name, value, false)
43
48
  end
44
49
 
45
50
  private
46
51
 
47
52
  # Handle *= for method_missing.
48
- def attribute=(attribute_name, value, force_write_readonly: false)
49
- write_attribute(attribute_name, value, force_write_readonly: force_write_readonly)
53
+ def attribute=(attribute_name, value)
54
+ write_attribute(attribute_name, value)
50
55
  end
51
56
 
52
- def write_attribute_with_type_cast(attr_name, value, should_type_cast, force_write_readonly: false)
57
+ def write_attribute_with_type_cast(attr_name, value, should_type_cast)
53
58
  attr_name = attr_name.to_s
54
59
 
55
- return if !force_write_readonly && self.class.readonly_attributes.include?(attr_name)
56
-
57
60
  if should_type_cast
58
61
  @attributes.write_from_user(attr_name, value)
59
62
  else
@@ -294,26 +294,6 @@ module DuckRecord #:nodoc:
294
294
  include NestedAttributes
295
295
  include Reflection
296
296
  include Serialization
297
-
298
- def to_h(include_empty: true)
299
- hash = serializable_hash
300
-
301
- self.class.reflections.keys.each do |k|
302
- records = send(k)
303
- sub_hash =
304
- if records.respond_to?(:to_ary)
305
- records.to_ary.map { |a| a.to_h }
306
- else
307
- records.to_h
308
- end
309
-
310
- if include_empty || sub_hash.any?
311
- hash[k] = sub_hash
312
- end
313
- end
314
-
315
- hash
316
- end
317
297
  end
318
298
 
319
299
  ActiveSupport.run_load_hooks(:duck_record, Base)
@@ -63,16 +63,20 @@ module DuckRecord
63
63
  self.class.define_attribute_methods
64
64
  @attributes = self.class._default_attributes.deep_dup
65
65
 
66
+ disable_attr_readonly!
67
+
66
68
  init_internals
67
69
  initialize_internals_callback
68
70
 
69
71
  if attributes
70
- assign_attributes(attributes, force_write_readonly: true)
72
+ assign_attributes(attributes)
71
73
  clear_changes_information
72
74
  end
73
75
 
74
76
  yield self if block_given?
75
77
  _run_initialize_callbacks
78
+
79
+ enable_attr_readonly!
76
80
  end
77
81
 
78
82
  # Initialize an empty model object from +coder+. +coder+ should be
@@ -356,7 +356,7 @@ module DuckRecord
356
356
  if method_defined?(:#{association_name}_attributes=)
357
357
  remove_method(:#{association_name}_attributes=)
358
358
  end
359
- def #{association_name}_attributes=(attributes, force_write_readonly: false)
359
+ def #{association_name}_attributes=(attributes)
360
360
  assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
361
361
  end
362
362
  eoruby
@@ -139,7 +139,7 @@ module DuckRecord
139
139
  end
140
140
 
141
141
  included do
142
- Associations::Builder::Association.extensions << AssociationBuilderExtension
142
+ Associations::Builder::EmbedsAssociation.extensions << AssociationBuilderExtension
143
143
  mattr_accessor :index_nested_attribute_errors, instance_writer: false
144
144
  self.index_nested_attribute_errors = false
145
145
  end
@@ -3,10 +3,23 @@ module DuckRecord
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
+ attr_accessor :_attr_readonly_enabled
6
7
  class_attribute :_attr_readonly, instance_accessor: false
7
8
  self._attr_readonly = []
8
9
  end
9
10
 
11
+ def attr_readonly_enabled?
12
+ _attr_readonly_enabled
13
+ end
14
+
15
+ def enable_attr_readonly!
16
+ self._attr_readonly_enabled = true
17
+ end
18
+
19
+ def disable_attr_readonly!
20
+ self._attr_readonly_enabled = false
21
+ end
22
+
10
23
  module ClassMethods
11
24
  # Attributes listed as readonly will be used to create a new record but update operations will
12
25
  # ignore these fields.
@@ -15,10 +15,10 @@ module DuckRecord
15
15
  def self.create(macro, name, options, ar)
16
16
  klass = \
17
17
  case macro
18
- when :has_many
19
- HasManyReflection
20
- when :has_one
21
- HasOneReflection
18
+ when :embeds_many
19
+ EmbedsManyReflection
20
+ when :embeds_one
21
+ EmbedsOneReflection
22
22
  else
23
23
  raise "Unsupported Macro: #{macro}"
24
24
  end
@@ -182,7 +182,7 @@ module DuckRecord
182
182
 
183
183
  # Holds all the metadata about an association as it was specified in the
184
184
  # Active Record class.
185
- class AssociationReflection < MacroReflection #:nodoc:
185
+ class EmbedsAssociationReflection < MacroReflection #:nodoc:
186
186
  # Returns the target association's class.
187
187
  #
188
188
  # class Author < ActiveRecord::Base
@@ -286,23 +286,23 @@ module DuckRecord
286
286
  end
287
287
  end
288
288
 
289
- class HasManyReflection < AssociationReflection # :nodoc:
290
- def macro; :has_many; end
289
+ class EmbedsManyReflection < EmbedsAssociationReflection # :nodoc:
290
+ def macro; :embeds_many; end
291
291
 
292
292
  def collection?; true; end
293
293
 
294
294
  def association_class
295
- Associations::HasManyAssociation
295
+ Associations::EmbedsManyAssociation
296
296
  end
297
297
  end
298
298
 
299
- class HasOneReflection < AssociationReflection # :nodoc:
300
- def macro; :has_one; end
299
+ class EmbedsOneReflection < EmbedsAssociationReflection # :nodoc:
300
+ def macro; :embeds_one; end
301
301
 
302
302
  def has_one?; true; end
303
303
 
304
304
  def association_class
305
- Associations::HasOneAssociation
305
+ Associations::EmbedsOneAssociation
306
306
  end
307
307
  end
308
308
  end
@@ -8,24 +8,13 @@ module DuckRecord #:nodoc:
8
8
  self.include_root_in_json = false
9
9
  end
10
10
 
11
- def serializable_hash(options = {})
12
- options = (options || {}).reverse_merge except: Array(options[:except]).map(&:to_s)
13
- super options
14
- end
11
+ def serializable_hash(options = nil)
12
+ options = options.try(:dup) || {}
15
13
 
16
- private
14
+ options[:except] = Array(options[:except]).map(&:to_s)
15
+ options[:include] = Array(_reflections.keys).map(&:to_s)
17
16
 
18
- def read_attribute_for_serialization(key)
19
- v = send(key)
20
- if v.respond_to?(:serializable_hash)
21
- v.serializable_hash
22
- elsif v.respond_to?(:to_ary)
23
- v.to_ary
24
- elsif v.respond_to?(:to_hash)
25
- v.to_hash
26
- else
27
- v
28
- end
17
+ super(options)
29
18
  end
30
19
  end
31
20
  end
@@ -1,3 +1,3 @@
1
1
  module DuckRecord
2
- VERSION = "0.0.16"
2
+ VERSION = "0.0.18"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duck_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - jasl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-17 00:00:00.000000000 Z
11
+ date: 2017-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -83,17 +83,13 @@ files:
83
83
  - lib/core_ext/array_without_blank.rb
84
84
  - lib/duck_record.rb
85
85
  - lib/duck_record/associations.rb
86
- - lib/duck_record/associations/association.rb
87
- - lib/duck_record/associations/builder/association.rb
88
- - lib/duck_record/associations/builder/collection_association.rb
89
- - lib/duck_record/associations/builder/has_many.rb
90
- - lib/duck_record/associations/builder/has_one.rb
91
- - lib/duck_record/associations/builder/singular_association.rb
92
- - lib/duck_record/associations/collection_association.rb
93
- - lib/duck_record/associations/collection_proxy.rb
94
- - lib/duck_record/associations/has_many_association.rb
95
- - lib/duck_record/associations/has_one_association.rb
96
- - lib/duck_record/associations/singular_association.rb
86
+ - lib/duck_record/associations/builder/embeds_association.rb
87
+ - lib/duck_record/associations/builder/embeds_many.rb
88
+ - lib/duck_record/associations/builder/embeds_one.rb
89
+ - lib/duck_record/associations/embeds_association.rb
90
+ - lib/duck_record/associations/embeds_many_association.rb
91
+ - lib/duck_record/associations/embeds_many_proxy.rb
92
+ - lib/duck_record/associations/embeds_one_association.rb
97
93
  - lib/duck_record/attribute.rb
98
94
  - lib/duck_record/attribute/user_provided_default.rb
99
95
  - lib/duck_record/attribute_assignment.rb
@@ -164,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
160
  version: '0'
165
161
  requirements: []
166
162
  rubyforge_project:
167
- rubygems_version: 2.6.13
163
+ rubygems_version: 2.6.12
168
164
  signing_key:
169
165
  specification_version: 4
170
166
  summary: Used for creating virtual models like ActiveType or ModelAttribute does
@@ -1,7 +0,0 @@
1
- module DuckRecord::Associations::Builder # :nodoc:
2
- class HasMany < CollectionAssociation #:nodoc:
3
- def self.macro
4
- :has_many
5
- end
6
- end
7
- end
@@ -1,15 +0,0 @@
1
- module DuckRecord::Associations::Builder # :nodoc:
2
- class HasOne < SingularAssociation #:nodoc:
3
- def self.macro
4
- :has_one
5
- end
6
-
7
- def self.define_validations(model, reflection)
8
- super
9
-
10
- if reflection.options[:required]
11
- model.validates_presence_of reflection.name, message: :required
12
- end
13
- end
14
- end
15
- end
@@ -1,11 +0,0 @@
1
- module DuckRecord
2
- # = Active Record Has Many Association
3
- module Associations
4
- # This is the proxy that handles a has many association.
5
- #
6
- # If the association has a <tt>:through</tt> option further specialization
7
- # is provided by its child HasManyThroughAssociation.
8
- class HasManyAssociation < CollectionAssociation #:nodoc:
9
- end
10
- end
11
- end
@@ -1,17 +0,0 @@
1
- module DuckRecord
2
- # = Active Record Has One Association
3
- module Associations
4
- class HasOneAssociation < SingularAssociation #:nodoc:
5
- def replace(record)
6
- self.target =
7
- if record.is_a? klass
8
- record
9
- elsif record.respond_to?(:to_h)
10
- build_record(record.to_h)
11
- end
12
- rescue
13
- raise_on_type_mismatch!(record)
14
- end
15
- end
16
- end
17
- end