inherits_many 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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/lib/inherits_many/version.rb +3 -0
- data/lib/inherits_many.rb +138 -0
- data/provisioner.gemspec +23 -0
- metadata +66 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
inherits_many
|
2
|
+
=============
|
3
|
+
|
4
|
+
An individual restaurant can have many menu items, but a restaurant that belongs to a chain inherits all it's menu items from the chain it belongs to.
|
5
|
+
|
6
|
+
* When a restaurant joins a chain, it gets a copy of all the menu items from that chain.
|
7
|
+
* When a restaurant leaves a chain, all those menu items go away.
|
8
|
+
* When a menu item is added to a chain, it is added to all the restaurants in that chain.
|
9
|
+
* When a menu item is removed from a chain, it is removed from all restaurants in that chain.
|
10
|
+
|
11
|
+
The ActiveRecord associations and `inherits_many` definition look like this:
|
12
|
+
|
13
|
+
class Chain < ActiveRecord::Base
|
14
|
+
has_many :restaurants
|
15
|
+
has_many :menu_items
|
16
|
+
end
|
17
|
+
|
18
|
+
class MenuItem < ActiveRecord::Base
|
19
|
+
has_many :restaurant_menu_items
|
20
|
+
has_many :restaurants, through: :restaurant_menu_items
|
21
|
+
belongs_to :chain
|
22
|
+
|
23
|
+
passes_on_to :restaurants, of: :chain
|
24
|
+
end
|
25
|
+
|
26
|
+
class Restaurant < ActiveRecord::Base
|
27
|
+
has_many :restaurant_menu_items
|
28
|
+
has_many :menu_items, through: :restaurant_menu_items
|
29
|
+
belongs_to :chain
|
30
|
+
|
31
|
+
inherits_many :menu_items, from: :chain
|
32
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require "inherits_many/version"
|
2
|
+
|
3
|
+
class ActiveRecord::Base
|
4
|
+
|
5
|
+
@@passes_on_to = {}
|
6
|
+
def self.passes_on_to(target, params)
|
7
|
+
unless @@passes_on_to.has_key? self.name
|
8
|
+
@@passes_on_to[self.name] = []
|
9
|
+
end
|
10
|
+
@@passes_on_to[self.name] << {target: target}.merge(params)
|
11
|
+
end
|
12
|
+
|
13
|
+
after_save :process_passes_on_to
|
14
|
+
def process_passes_on_to
|
15
|
+
|
16
|
+
concrete_class = self.class
|
17
|
+
|
18
|
+
while concrete_class.name != 'ActiveRecord::Base' do
|
19
|
+
|
20
|
+
unless @@passes_on_to[concrete_class.name].nil?
|
21
|
+
|
22
|
+
@@passes_on_to[concrete_class.name].each do |tt|
|
23
|
+
|
24
|
+
child = tt[:target]
|
25
|
+
parent = tt[:of]
|
26
|
+
parent_id = "#{parent}_id"
|
27
|
+
|
28
|
+
# if the chain has changed ..
|
29
|
+
# if chain_id_changed?
|
30
|
+
if self.changes.has_key? parent_id
|
31
|
+
|
32
|
+
parent_id_was = self.changes[parent_id][0]
|
33
|
+
parent_id_is = self.changes[parent_id][1]
|
34
|
+
|
35
|
+
# if there was previously a chain ..
|
36
|
+
if parent_id_was
|
37
|
+
|
38
|
+
# remove all restaurants from the old chain.
|
39
|
+
# self.restaurants = self.restaurants - Chain.find(chain_id_was).restaurants
|
40
|
+
self.send("#{child}=", self.send(child) - self.class.reflect_on_association(parent).class_name.constantize.find(parent_id_was).send(child))
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# if there is a new chain ..
|
45
|
+
if parent_id_is
|
46
|
+
|
47
|
+
# add all the menu items from the new chain to this restaurant.
|
48
|
+
self.send("#{child}=", self.send(child) + self.send(parent).send(child))
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
concrete_class = concrete_class.superclass
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
@@inherits_many = {}
|
64
|
+
def self.inherits_many(source, params)
|
65
|
+
unless @@inherits_many.has_key? self.name
|
66
|
+
@@inherits_many[self.name] = []
|
67
|
+
end
|
68
|
+
@@inherits_many[self.name] << {source: source}.merge(params)
|
69
|
+
end
|
70
|
+
|
71
|
+
after_save :process_inherits_many
|
72
|
+
def process_inherits_many
|
73
|
+
|
74
|
+
concrete_class = self.class
|
75
|
+
|
76
|
+
while concrete_class.name != 'ActiveRecord::Base' do
|
77
|
+
|
78
|
+
unless @@inherits_many[concrete_class.name].nil?
|
79
|
+
|
80
|
+
@@inherits_many[concrete_class.name].each do |tt|
|
81
|
+
|
82
|
+
child = tt[:source]
|
83
|
+
parent = tt[:from]
|
84
|
+
parent_id = "#{parent}_id"
|
85
|
+
|
86
|
+
# if the chain has changed ..
|
87
|
+
# if chain_id_changed?
|
88
|
+
if self.changes.has_key? parent_id
|
89
|
+
|
90
|
+
parent_id_was = self.changes[parent_id][0]
|
91
|
+
parent_id_is = self.changes[parent_id][1]
|
92
|
+
|
93
|
+
# if there was previously a chain ..
|
94
|
+
if parent_id_was
|
95
|
+
|
96
|
+
# remove all the menus from the old chain.
|
97
|
+
self.send("#{child}=", self.send(child) - self.class.reflect_on_association(parent).class_name.constantize.find(parent_id_was).send(child))
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# if there is a new chain ..
|
102
|
+
if parent_id_is
|
103
|
+
|
104
|
+
# add all the menu items from the new chain to this restaurant.
|
105
|
+
self.send("#{child}=", self.send(child) + self.send(parent).send(child))
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# if there was previously a chain ..
|
111
|
+
if parent_id_was
|
112
|
+
|
113
|
+
# remove all restaurants from the old chain.
|
114
|
+
# self.restaurants = self.restaurants - Chain.find(chain_id_was).restaurants
|
115
|
+
self.send("#{child}=", self.send(child) - self.class.reflect_on_association(parent).class_name.constantize.find(parent_id_was).send(child))
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
# if there is a new chain ..
|
120
|
+
if parent_id_is
|
121
|
+
|
122
|
+
# add all the menu items from the new chain to this restaurant.
|
123
|
+
self.send("#{child}=", self.send(child) + self.send(parent).send(child))
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
concrete_class = concrete_class.superclass
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
data/provisioner.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "inherits_many/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "inherits_many"
|
7
|
+
s.version = InheritsMany::VERSION
|
8
|
+
s.authors = ["Andrew Culver"]
|
9
|
+
s.email = ["andrew.culver@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/wearetitans/inherits_many"
|
11
|
+
s.summary = %q{Allow has_many relationships to inherit associated objects from a parent object's has_many association.}
|
12
|
+
s.description = %q{Example: "If a restaurant can have many menu items and a chain has many menu items, ensure all restaurants have the menu items of the chain they belong to."}
|
13
|
+
|
14
|
+
s.rubyforge_project = "inherits_many"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_runtime_dependency "activerecord"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: inherits_many
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Culver
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &70174225082380 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70174225082380
|
25
|
+
description: ! 'Example: "If a restaurant can have many menu items and a chain has
|
26
|
+
many menu items, ensure all restaurants have the menu items of the chain they belong
|
27
|
+
to."'
|
28
|
+
email:
|
29
|
+
- andrew.culver@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Gemfile
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- lib/inherits_many.rb
|
39
|
+
- lib/inherits_many/version.rb
|
40
|
+
- provisioner.gemspec
|
41
|
+
homepage: http://github.com/wearetitans/inherits_many
|
42
|
+
licenses: []
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
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
|
+
rubyforge_project: inherits_many
|
61
|
+
rubygems_version: 1.8.15
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Allow has_many relationships to inherit associated objects from a parent
|
65
|
+
object's has_many association.
|
66
|
+
test_files: []
|