Class: BelongsToOneOf::BelongsToOneOfModel

Inherits:
Object
  • Object
show all
Defined in:
lib/belongs_to_one_of/belongs_to_one_of_model.rb

Defined Under Namespace

Classes: InvalidParamsException

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(resource_key, raw_possible_resource_types, include_type_column, resource_type_field, model_class) ⇒ BelongsToOneOfModel

Returns a new instance of BelongsToOneOfModel.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 7

def initialize(
  resource_key,
  raw_possible_resource_types,
  include_type_column,
  resource_type_field,
  model_class
)
  @resource_key = resource_key
  @possible_resource_types = normalise_resource_types(raw_possible_resource_types)
  @include_type_column = include_type_column
  @resource_type_field = resource_type_field
  @model_class = model_class
  validate_config
  initialize_associations
end

Instance Attribute Details

#include_type_columnObject (readonly)

Returns the value of attribute include_type_column.



23
24
25
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 23

def include_type_column
  @include_type_column
end

#model_classObject (readonly)

Returns the value of attribute model_class.



23
24
25
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 23

def model_class
  @model_class
end

#possible_resource_typesObject (readonly)

Returns the value of attribute possible_resource_types.



23
24
25
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 23

def possible_resource_types
  @possible_resource_types
end

#resource_keyObject (readonly)

Returns the value of attribute resource_key.



23
24
25
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 23

def resource_key
  @resource_key
end

#resource_type_fieldObject (readonly)

Returns the value of attribute resource_type_field.



23
24
25
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 23

def resource_type_field
  @resource_type_field
end

Instance Method Details

#resource_getter(model) ⇒ Object



81
82
83
84
85
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 81

def resource_getter(model)
  possible_resource_types.keys.detect do |resource_type|
    return model.send(resource_type) if model.send(resource_type)
  end
end

#resource_id_getter(model) ⇒ Object



87
88
89
90
91
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 87

def resource_id_getter(model)
  possible_resource_types.values.detect do |id_column|
    return model.send(id_column) if model.send(id_column)
  end
end

#resource_setter(resource, model) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 54

def resource_setter(resource, model)
  return if resource.nil?

  possible_resource_types.each_key do |resource_type|
    model.public_send("#{resource_type}=", nil)
  end

  model.instance_variable_set("@#{resource_key}", resource)
  resource_type_accessor = find_resource_accessor(resource, model)

  unless resource_type_accessor
    message = "one of #{possible_resource_types.keys.join(', ')} expected, "\
              "got #{resource.inspect} which is an instance of "\
              "#{resource.class}(##{resource.class.object_id})"
    raise ActiveRecord::AssociationTypeMismatch, message
  end

  resource_setter_method = "#{resource_type_accessor}="
  model.public_send(resource_setter_method, resource)

  if include_type_column
    resource_type_setter_method = "#{resource_type_field}="
    resource_type_to_store = find_resource_type(resource, model)
    model.public_send(resource_type_setter_method, resource_type_to_store)
  end
end

#resource_type_getter(model) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 93

def resource_type_getter(model)
  resource = model.send(resource_key)
  return unless resource

  possible_resource_types.keys.detect do |resource_type_accessor|
    reflection = model.class.reflect_on_association(resource_type_accessor)
    return reflection.class_name if resource.is_a?(reflection.klass)
  end
end

#validate_at_most_one_resource(model) ⇒ Object



33
34
35
36
37
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 33

def validate_at_most_one_resource(model)
  return unless number_of_resources(model) > 1

  model.errors.add(:base, "model must belong to at most one #{resource_key}")
end

#validate_correct_resource_type(model) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 39

def validate_correct_resource_type(model)
  resource = model.send(resource_key)
  return unless resource

  actual_resource_type = resource_type_getter(model)
  specified_resource_type = model.send(resource_type_field)

  unless actual_resource_type == specified_resource_type
    model.errors.add(
      resource_type_field,
      "#{resource_type_field} must match the type of #{resource_key}",
    )
  end
end

#validate_exactly_one_resource(model) ⇒ Object

TODO: I18n the error messages (provide translations??)



27
28
29
30
31
# File 'lib/belongs_to_one_of/belongs_to_one_of_model.rb', line 27

def validate_exactly_one_resource(model)
  return if number_of_resources(model) == 1

  model.errors.add(:base, "model must belong to exactly one #{resource_key}")
end