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