cassiano-cassiano-model_lookup 0.1.5

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.
@@ -0,0 +1,83 @@
1
+ = ModelLookup
2
+
3
+ Rails gem that implements the notion of a virtual (transient) lookup table inside Active Record (AR), allowing for the creation of belongs_to and has_many associations between these and physical (persistent) AR entities.
4
+
5
+
6
+ == Install
7
+
8
+ gem install cassiano-model_lookup --source http://gems.github.com
9
+
10
+
11
+ == Usage
12
+
13
+ Let's assume we want to map the 1 x N association between (US) _States_ and _Customers_:
14
+
15
+ class State < ModelLookup
16
+ set_domain_values [
17
+ # :id :name
18
+ # ---- --------------
19
+ [ 'CA', 'California' ],
20
+ [ 'FL', 'Florida' ],
21
+ [ 'GA', 'Georgia' ],
22
+ ...
23
+ ]
24
+
25
+ model_lookup_has_many :customers
26
+ end
27
+
28
+ class Customer < ActiveRecord::Base
29
+ model_lookup_belongs_to :state
30
+ has_many :contacts
31
+
32
+ validates_presence_of :name, :city, :state
33
+ end
34
+
35
+ Now you can do things such as:
36
+
37
+ c = Customer.create :name => 'West Inc', :city => 'San Jose', :state => State.find_by_id('CA')
38
+ => #<Customer id: 1, name: "West Inc", city: "San Jose", state: "CA">
39
+
40
+ c.state
41
+ => #<State:0x449ee14 @id="CA", @name="California">
42
+
43
+ c.state.name
44
+ => "California"
45
+
46
+ c.state.id
47
+ => "CA"
48
+
49
+ State.all
50
+ => [#<State:0x449ee14 @id="CA", @name="California">, #<State:0x449ee15 @id="FL", @name="Florida">,
51
+ #<State:0x449ee16 @id="GA", @name="Georgia">]
52
+
53
+ s = State.first
54
+ => #<State:0x449ee14 @id="CA", @name="California">
55
+
56
+ State.last
57
+ => #<State:0x449ee16 @id="GA", @name="Georgia">
58
+
59
+ s.customers
60
+ => [#<Customer id: 1, name: "West Inc", city: "San Jose", state: "CA">]
61
+
62
+ == License
63
+
64
+ Copyright (C) 2008 Tagview Tecnologia (Cassiano D'Andrea - cassiano.dandrea@tagview.com.br)
65
+
66
+ Permission is hereby granted, free of charge, to any person obtaining
67
+ a copy of this software and associated documentation files (the
68
+ "Software"), to deal in the Software without restriction, including
69
+ without limitation the rights to use, copy, modify, merge, publish,
70
+ distribute, sublicense, and/or sell copies of the Software, and to
71
+ permit persons to whom the Software is furnished to do so, subject to
72
+ the following conditions:
73
+
74
+ The above copyright notice and this permission notice shall be
75
+ included in all copies or substantial portions of the Software.
76
+
77
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
78
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
79
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
80
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
81
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
82
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
83
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('cassiano-model_lookup', '0.1.5') do |p|
6
+ p.description = "Implements the notion of a virtual (transient) lookup table inside Active Record (AR), allowing for the creation of belongs_to and has_many associations between these and physical (persistent) AR entities"
7
+ p.url = "http://github.com/cassiano/model_lookup"
8
+ p.author = "Cassiano D'Andrea"
9
+ p.email = "cassiano.dandrea@tagview.com.br"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{cassiano-model_lookup}
3
+ s.version = "0.1.5"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Cassiano D'Andrea"]
7
+ s.date = %q{2008-11-13}
8
+ s.description = %q{Implements the notion of a virtual (transient) lookup table inside Active Record (AR), allowing for the creation of belongs_to and has_many associations between these and physical (persistent) AR entities}
9
+ s.email = %q{cassiano.dandrea@tagview.com.br}
10
+ s.extra_rdoc_files = ["lib/model_lookup.rb", "README.rdoc"]
11
+ s.files = ["cassiano-model_lookup.gemspec", "init.rb", "lib/model_lookup.rb", "Manifest", "model_lookup.gemspec", "Rakefile", "README.rdoc"]
12
+ s.has_rdoc = true
13
+ s.homepage = %q{http://github.com/cassiano/model_lookup}
14
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cassiano-model_lookup", "--main", "README.rdoc"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{cassiano-model_lookup}
17
+ s.rubygems_version = %q{1.2.0}
18
+ s.summary = %q{Implements the notion of a virtual (transient) lookup table inside Active Record (AR), allowing for the creation of belongs_to and has_many associations between these and physical (persistent) AR entities}
19
+
20
+ if s.respond_to? :specification_version then
21
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
22
+ s.specification_version = 2
23
+
24
+ if current_version >= 3 then
25
+ else
26
+ end
27
+ else
28
+ end
29
+ end
data/init.rb ADDED
@@ -0,0 +1,25 @@
1
+ ################################################################################
2
+ #
3
+ # Copyright (C) 2008 Tagview Tecnologia (Cassiano D'Andrea - cassiano.dandrea@tagview.com.br)
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #
24
+ ################################################################################
25
+ require 'model_lookup'
@@ -0,0 +1,227 @@
1
+ ################################################################################
2
+ #
3
+ # Copyright (C) 2008 Tagview Tecnologia (Cassiano D'Andrea - cassiano.dandrea@tagview.com.br)
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #
24
+ ################################################################################
25
+ # Implements the notion of a virtual (transient) lookup table inside Active Record (AR), allowing for the creation of belongs_to and has_many
26
+ # associations between these and physical (persistent) AR entities.
27
+ class ModelLookup
28
+ ################################################################################
29
+ attr_accessor :id, :name
30
+
31
+ ################################################################################
32
+ def initialize(id, name)
33
+ @id = id
34
+ @name = name
35
+ end
36
+
37
+ ################################################################################
38
+ def to_param
39
+ self.id
40
+ end
41
+
42
+ ################################################################################
43
+ def ==(another_model_lookup_object)
44
+ self.id == another_model_lookup_object.id
45
+ end
46
+
47
+ ################################################################################
48
+ # Class Methods
49
+ class << self
50
+ ################################################################################
51
+ attr_writer :values
52
+
53
+ ################################################################################
54
+ # Returns *all* instances of the model lookup table.
55
+ def all(options = {})
56
+ @all ||= {}
57
+
58
+ @all[options.inspect] ||=
59
+ returning(@values.map { |v| self.new *v }) do |collection|
60
+ if options[:order]
61
+ sort_attr, sort_dir = options[:order].to_s.split
62
+
63
+ asc = !sort_dir || sort_dir.downcase.to_sym == :asc
64
+
65
+ collection.sort! { |a, b| (asc ? a : b).__send__(sort_attr) <=> (asc ? b : a).__send__(sort_attr) }
66
+ end
67
+ end
68
+ end
69
+
70
+ ################################################################################
71
+ # Returns the *first* instance of a model lookup table.
72
+ def first(options = {})
73
+ self.all(options).first
74
+ end
75
+
76
+ ################################################################################
77
+ # Returns the *last* instance of a model lookup table.
78
+ def last(options = {})
79
+ self.all(options).last
80
+ end
81
+
82
+ ################################################################################
83
+ # Finds a model lookup instance with a given ID. Throws _ActiveRecord::RecordNotFound_ if not found.
84
+ def find(param)
85
+ self.all.find { |v| v.to_param == param } || raise(ActiveRecord::RecordNotFound)
86
+ end
87
+
88
+ ################################################################################
89
+ # Finds a model lookup instance with a given ID. Returns nil if not found.
90
+ def find_by_id(id)
91
+ self.all.find { |v| v.id == id }
92
+ end
93
+
94
+ ################################################################################
95
+ # Finds a model lookup instance with a given name. Returns nil if not found.
96
+ def find_by_name(name)
97
+ self.all.find { |v| v.name == name }
98
+ end
99
+
100
+ ################################################################################
101
+ # Returns a count/size of all model lookup instances.
102
+ def count
103
+ self.all.size
104
+ end
105
+
106
+ ################################################################################
107
+ def model_lookup_has_many(association_id, options = {})
108
+ begin
109
+ options.reverse_merge!(
110
+ :class_name => association_id.to_s.classify.constantize
111
+ )
112
+ rescue NameError
113
+ end
114
+
115
+ options[:class_name] = options[:class_name].to_s.constantize if !options[:class_name].is_a?(Class)
116
+
117
+ options.reverse_merge!(
118
+ :foreign_key => self.to_s.foreign_key,
119
+ :virtual_attribute => false
120
+ )
121
+
122
+ options.reverse_merge!(
123
+ :method => options[:foreign_key].to_s.sub(/_id$/, '').to_sym
124
+ )
125
+
126
+ define_method association_id do |*args|
127
+ finder_options = args[0] || {}
128
+
129
+ finder_options.reverse_merge!(
130
+ :order => options[:order],
131
+ :conditions => options[:conditions],
132
+ :limit => options[:limit]
133
+ )
134
+
135
+ this = self
136
+
137
+ options[:class_name].class_eval do
138
+ with_scope :find => finder_options do
139
+ if options[:virtual_attribute]
140
+ if options[:optimal_conditions]
141
+ self.all :conditions => options[:optimal_conditions].gsub('?', this.id)
142
+ else
143
+ self.all.select { |e| e.__send__(options[:foreign_key]) == this.id }
144
+ end
145
+ else
146
+ self.all :conditions => { options[:method] => this.id }
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ ################################################################################
154
+ def find_for_lookup_select(options = {}, finder_options = {})
155
+ self.all finder_options
156
+ end
157
+
158
+ ################################################################################
159
+ protected
160
+
161
+ ################################################################################
162
+ def set_domain_values(values)
163
+ @values = values
164
+ end
165
+ end
166
+ end
167
+
168
+ ################################################################################
169
+ module ModelLookupAssociations
170
+ ################################################################################
171
+ def self.included(base)
172
+ base.extend ClassMethods
173
+ end
174
+
175
+ ################################################################################
176
+ module ClassMethods
177
+ ################################################################################
178
+ def model_lookup_belongs_to(association_id, options = {})
179
+ begin
180
+ options.reverse_merge!(
181
+ :class_name => association_id.to_s.classify.constantize
182
+ )
183
+ rescue NameError
184
+ end
185
+
186
+ options[:class_name] = options[:class_name].to_s.constantize if !options[:class_name].is_a?(Class)
187
+
188
+ options.reverse_merge!(
189
+ :foreign_key => association_id.to_s.foreign_key
190
+ )
191
+
192
+ options.reverse_merge!(
193
+ :method => options[:foreign_key].to_s.sub(/_id$/, '').to_sym
194
+ )
195
+
196
+ # Include "referential integrity" validation.
197
+ self.validates_inclusion_of "#{association_id}_id", :in => options[:class_name].all.map(&:id), :allow_blank => true
198
+
199
+ # Define the getter (making it behave like if it were a proxy association).
200
+ define_method association_id do
201
+ association_value = self.__send__ "#{association_id}_id"
202
+ options[:class_name].find_by_id(association_value) if !association_value.blank?
203
+ end
204
+
205
+ # Define the setter.
206
+ define_method "#{association_id}=" do |new_association_id|
207
+ self.__send__ "#{association_id}_id=", new_association_id.to_param
208
+ end
209
+
210
+ # Define the "foreign key" getter.
211
+ define_method "#{association_id}_id" do
212
+ self.read_attribute options[:method]
213
+ end
214
+
215
+ # Define the "foreign key" setter.
216
+ define_method "#{association_id}_id=" do |new_id|
217
+ self.write_attribute options[:method], new_id
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ ################################################################################
224
+ class ActiveRecord::Base
225
+ ################################################################################
226
+ include ModelLookupAssociations
227
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cassiano-cassiano-model_lookup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Cassiano D'Andrea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-13 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Implements the notion of a virtual (transient) lookup table inside Active Record (AR), allowing for the creation of belongs_to and has_many associations between these and physical (persistent) AR entities
17
+ email: cassiano.dandrea@tagview.com.br
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - lib/model_lookup.rb
24
+ - README.rdoc
25
+ files:
26
+ - cassiano-model_lookup.gemspec
27
+ - init.rb
28
+ - lib/model_lookup.rb
29
+ - Manifest
30
+ - model_lookup.gemspec
31
+ - Rakefile
32
+ - README.rdoc
33
+ has_rdoc: true
34
+ homepage: http://github.com/cassiano/model_lookup
35
+ post_install_message:
36
+ rdoc_options:
37
+ - --line-numbers
38
+ - --inline-source
39
+ - --title
40
+ - Cassiano-model_lookup
41
+ - --main
42
+ - README.rdoc
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "1.2"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project: cassiano-model_lookup
60
+ rubygems_version: 1.2.0
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: Implements the notion of a virtual (transient) lookup table inside Active Record (AR), allowing for the creation of belongs_to and has_many associations between these and physical (persistent) AR entities
64
+ test_files: []
65
+