Module: Sack::Database::Model::Data

Defined in:
lib/sack/database/model/data.rb

Overview

Data Module: Provides a simple data access layer through models.

Constant Summary collapse

VALIDATED_ACTIONS =

Actions requiring Validation

[
  :create,
    :update,
    :save
]

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Method Missing: Catches and routes model actions through database.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/sack/database/model/data.rb', line 33

def method_missing name, *args

  # Check action allowed
  super name, *args unless ACTIONS.include? name

  # Acquire Database
  db = args.slice! 0

  # Check Validation Required
  if VALIDATED_ACTIONS.include? name

    # Acquire Entity
    data = args.last

    # Pre-load for updates
    data = data.clone.merge find(db, args.slice(0)) if name == :update

    # Validate
    errors = []
    raise Validation::ValidationException.new "Invalid Entity [#{data}] for Model #{@model}", errors unless is_valid? db, data, errors
  end

  # Check Delete
  if name == :delete

    # Get ID
    id = args.first

    # Run through Relations
    relationships.each do |_rname, relationship|

      # Acquire Target Model
      tmodel = @model_root.const_get relationship[:target].to_s.camelcase

      # Switch on delete action
      case relationship[:options][:on_delete]
        when :detach
          tmodel.update_by db, relationship[:fk], id, relationship[:fk] => nil
        when :delete
          tmodel.delete_by db, relationship[:fk], id
        else
          # NoOp
      end
    end
  end

  # Check Delete By
  if name == :delete_by

    # Fetch Set
    set = fetch_by db, *args

    # Run through Relations
    relationships.each do |_rname, relationship|

      # Acquire Target Model
      tmodel = @model_root.const_get relationship[:target].to_s.camelcase

      # Switch on delete action
      case relationship[:options][:on_delete]
        when :detach
          set.each { |e| tmodel.update_by db, relationship[:fk], e[:id], relationship[:fk] => nil }
        when :delete
          set.each { |e| tmodel.delete_by db, relationship[:fk], e[:id] }
        else
          # NoOp
      end
    end
  end

  # Forward to Database
  result = db.send name, table_name, *args

  # Inject Model Proxy into Entity/ies
  (result.is_a?(Array) ? result : [result]).each { |e| e.instance_variable_set('@model_mod', self); e.define_singleton_method(:method_missing) { |n, *a| @model_mod.send n, *a, self } } unless result.frozen?

  result
end