eav_presenter 0.0.1
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.
- data/lib/eav_presenter.rb +94 -0
- metadata +67 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
# Usage:
|
2
|
+
# Say you have an eav design pattern like this: Person, PersonAttribute and PersonAttrValue
|
3
|
+
# You can then define a new class:
|
4
|
+
# class EavPerson < Person
|
5
|
+
# include EavPresenter
|
6
|
+
# eav :eav_attr_class => PersonAttribute, :eav_value_class => PersonAttrValue, :eav_entity_foreign_key => "personId",
|
7
|
+
# :eav_attr_foreign_key => "attrId"
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# The attributes in PersonAttribute will now behave as DB columns. You can also use AR validation macros on them
|
11
|
+
# Dirty-tracking will not work in this case. Should be possible to implement.
|
12
|
+
# I have tested such a presenter model with scaffolding_extensions plugin only. More testing would be nice.
|
13
|
+
|
14
|
+
module EavPresenter
|
15
|
+
def self.included(base)
|
16
|
+
base.send(:extend, ClassMethods)
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_eav_attr_values_if_not_loaded
|
20
|
+
entity_foreign_key = self.class.instance_variable_get("@eav_entity_foreign_key")
|
21
|
+
@eav_attr_values ||= self.class.instance_variable_get("@eav_value_class").send("find_all_by_#{entity_foreign_key}",self.id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def save_eav_attr_values
|
25
|
+
self.class.instance_variable_get("@eav_attrs").each { |at|
|
26
|
+
eavs = load_eav_attr_values_if_not_loaded
|
27
|
+
eav = eavs.find { |i| i.attrId == at.id } #eav in the db
|
28
|
+
name = at.eav_attr_name
|
29
|
+
entity_foreign_key = self.class.instance_variable_get("@eav_entity_foreign_key")
|
30
|
+
attr_foreign_key = self.class.instance_variable_get("@eav_attr_foreign_key")
|
31
|
+
eav_value_class = self.class.instance_variable_get("@eav_value_class")
|
32
|
+
ivalue = send(name)
|
33
|
+
if attribute_changed?(name)
|
34
|
+
if eav
|
35
|
+
if ivalue.blank?
|
36
|
+
#eav needs to be deleted
|
37
|
+
eav_value_class.send("find_by_#{attr_foreign_key}_and_#{entity_foreign_key}",at.id,self.id).destroy
|
38
|
+
else
|
39
|
+
# eav has been modified. needs to be saved.
|
40
|
+
eav.value = ivalue
|
41
|
+
eav.save!
|
42
|
+
end
|
43
|
+
else
|
44
|
+
#eav needs to be created
|
45
|
+
eav_value_class.create({entity_foreign_key.to_sym => self.id, attr_foreign_key.to_sym => at.id, :value => ivalue})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
}
|
49
|
+
self.reload # Values have been changed in DB. Better reload them.
|
50
|
+
@eav_attr_values = nil
|
51
|
+
load_eav_attr_values_if_not_loaded
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
def eav(opts)
|
56
|
+
@eav_attr_class = opts[:eav_attr_class]
|
57
|
+
@eav_value_class = opts[:eav_value_class]
|
58
|
+
@eav_entity_foreign_key = opts[:eav_entity_foreign_key]
|
59
|
+
@eav_attr_foreign_key = opts[:eav_attr_foreign_key]
|
60
|
+
@eav_attrs = @eav_attr_class.all
|
61
|
+
|
62
|
+
define_method(:attributes) {
|
63
|
+
super.merge(Hash[self.class.instance_variable_get("@eav_attrs").map(&:eav_attr_name).map { |name| [name, send(name)] }])
|
64
|
+
}
|
65
|
+
# define_attribute_methods(@eav_attrs.collect(&:eav_attr_name))
|
66
|
+
|
67
|
+
@eav_attrs.each { |at|
|
68
|
+
define_method(at.eav_attr_name) { |*args|
|
69
|
+
eavs = load_eav_attr_values_if_not_loaded
|
70
|
+
if instance_variables.include?("@#{at.eav_attr_name}")
|
71
|
+
instance_variable_get("@#{at.eav_attr_name}")
|
72
|
+
else
|
73
|
+
eavs.find { |i| i.attrId == at.id }.try(:value)
|
74
|
+
end
|
75
|
+
}
|
76
|
+
|
77
|
+
define_method("#{at.eav_attr_name}=") { |value|
|
78
|
+
raise "EAV value for #{at.eav_attr_name} must be a string or nil" unless value.nil? || value.is_a?(String)
|
79
|
+
eavs = load_eav_attr_values_if_not_loaded
|
80
|
+
instance_variable_set("@#{at.eav_attr_name}",value)
|
81
|
+
old = eavs.find { |i| i.attrId == at.id }.try(:value)
|
82
|
+
if value == old
|
83
|
+
changed_attributes.delete(at.eav_attr_name)
|
84
|
+
else
|
85
|
+
changed_attributes[at.eav_attr_name] = old
|
86
|
+
end
|
87
|
+
}
|
88
|
+
}
|
89
|
+
after_save :save_eav_attr_values # Register a callback which makes sure that any changes made are sync'ed to the AttrValues table
|
90
|
+
after_find :load_eav_attr_values_if_not_loaded
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eav_presenter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nilesh Trivedi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-10-30 00:00:00 +05:30
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: activerecord
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
description: ActiveRecord model like presenter for Entity-Attribute-Value pattern
|
28
|
+
email:
|
29
|
+
- github@nileshtrivedi.com
|
30
|
+
executables: []
|
31
|
+
|
32
|
+
extensions: []
|
33
|
+
|
34
|
+
extra_rdoc_files: []
|
35
|
+
|
36
|
+
files:
|
37
|
+
- lib/eav_presenter.rb
|
38
|
+
has_rdoc: true
|
39
|
+
homepage: http://github.com/nileshtrivedi/eav_presenter
|
40
|
+
licenses: []
|
41
|
+
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.5.1
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: ActiveRecord model like presenter for Entity-Attribute-Value pattern
|
66
|
+
test_files: []
|
67
|
+
|