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 ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in provisioner.gemspec
4
+ gemspec
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,3 @@
1
+ module InheritsMany
2
+ VERSION = "0.0.1"
3
+ end
@@ -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
@@ -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: []