acts-as-joinable 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/Rakefile +1 -1
  2. data/lib/acts_as_joinable/core.rb +73 -63
  3. metadata +3 -3
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
5
5
  spec = Gem::Specification.new do |s|
6
6
  s.name = "acts-as-joinable"
7
7
  s.authors = ["Lance Pollard"]
8
- s.version = "0.1.1"
8
+ s.version = "0.1.3"
9
9
  s.summary = "ActsAsJoinable: DRYing up Many-to-Many Relationships in ActiveRecord"
10
10
  s.homepage = "http://github.com/viatropos/acts-as-joinable"
11
11
  s.email = "lancejpollard@gmail.com"
@@ -42,35 +42,35 @@ module ActsAsJoinable
42
42
  def initialize_acts_as_joinable_on_core
43
43
  joins = acts_as_joinable_config.dup
44
44
  block = joins.pop
45
- options = joins.extract_options!
45
+ opts = joins.extract_options!
46
46
  if joins.empty?
47
47
  joins = ActsAsJoinable.models
48
48
  relationships = [:child]
49
49
  else
50
- relationships = [options[:as] || :parent].flatten.map(&:to_sym)
50
+ relationships = [opts[:as] || :parent].flatten.map(&:to_sym)
51
51
  end
52
52
 
53
- options[:class_name] ||= options[:source].to_s.camelize if options[:source]
53
+ opts[:class_name] ||= opts[:source].to_s.camelize if opts[:source]
54
54
 
55
- association_type = options[:limit] == 1 ? :has_one : :has_many
55
+ association_type = opts[:limit] == 1 ? :has_one : :has_many
56
56
 
57
- scope_name = options[:named_scope]
57
+ scope_name = opts[:named_scope]
58
58
 
59
59
  joins.map!(&:to_sym)
60
60
 
61
61
  # class name of the model we're joining to self
62
62
  # otherwise it's retrieved from joins.each...
63
- class_name = options[:class_name] || nil
63
+ class_name = opts[:class_name] || nil
64
64
  # contexts defining the relationship between self and target
65
- contexts = [options[:context] || []].flatten
65
+ contexts = [opts[:context] || []].flatten
66
66
  context = contexts.first
67
67
  # possible values of the context
68
- values = [options[:values] || options[:value] || []].flatten.compact
68
+ values = [opts[:values] || opts[:value] || []].flatten.compact
69
69
  value = values.first
70
70
 
71
- sql = options[:conditions]
71
+ sql = opts[:conditions]
72
72
 
73
- nestable = options[:nestable] || false
73
+ nestable = opts[:nestable] || false
74
74
 
75
75
  # parent, child, or contexts (both) for custom helper getters/setters
76
76
 
@@ -89,75 +89,72 @@ module ActsAsJoinable
89
89
  joins.each do |type|
90
90
  singular_type = type.to_s.singularize
91
91
  if association_type == :has_one
92
- plural_type = type.to_s.pluralize
92
+ plural_type = type.to_s.pluralize.to_sym
93
93
  else
94
- plural_type = type.to_s
94
+ plural_type = type.to_s.to_sym
95
95
  end
96
- class_name = options[:class_name] || type.to_s.classify
96
+ class_name = opts[:class_name] || type.to_s.classify
97
97
 
98
98
  join_context = (context || singular_type).to_s
99
99
 
100
100
  options = {
101
- :through => :relationships,
102
- :class_name => class_name,
103
- :source => :child,
104
- :source_type => class_name,
105
- :conditions => sql
101
+ :through => :relationships,
102
+ :class_name => class_name,
103
+ :source => :child,
104
+ :source_type => class_name,
105
+ :conditions => sql
106
106
  }
107
107
 
108
108
  # relationships == [:parent, :child]
109
109
  relationships.each do |relationship|
110
- relationship = opposite_for(relationship)
111
- singular_relationship = "#{relationship.to_s}_relationship".to_sym
112
- plural_relationship = "#{relationship.to_s}_relationships".to_sym
113
- plural_relationship = "#{relationship.to_s}_relationships".to_sym
110
+ # Post.joins :tags, :as => :parent
111
+ # through_relationship = child_tag_relationships
112
+ # relationship_table = `relationships`
113
+ relationship = opposite_for(relationship)
114
+ through_relationship = "#{relationship.to_s}_#{singular_type}_relationships".to_sym
115
+ relationship_table = ActsAsJoinable::Relationship.quoted_table_name
114
116
 
115
- if association_type == :has_one
116
- relationship_with_context = "#{relationship.to_s}_#{singular_type}_relationship".to_sym
117
+ options.merge!(:through => through_relationship, :source => relationship, :uniq => true)
118
+
119
+ join_value = value
120
+
121
+ # conditions for the join model
122
+ condition_string = ""
123
+ #if join_context == class_name.underscore
124
+
125
+ # condition_string << "(#{relationship_table}.#{relationship}_type IN (?))"
126
+ if join_context == class_name.underscore
127
+ #conditions = [condition_string, [class_name]]
117
128
  else
118
- relationship_with_context = "#{relationship.to_s}_#{singular_type}_relationships".to_sym
129
+ condition_string << "(#{relationship_table}.context IN (?))"
130
+ condition_string << " AND (#{relationship_table}.value = ?)" if join_value
131
+ join_contexts = [join_context]#[join_context, class_name.underscore].uniq
132
+ conditions = [condition_string, join_contexts]
133
+ conditions << join_value.to_s if join_value
119
134
  end
120
135
 
121
- options = options.merge(
122
- :through => relationship_with_context,
123
- :source => relationship
124
- )
136
+ through_options = {
137
+ :class_name => "ActsAsJoinable::Relationship",
138
+ :conditions => conditions,
139
+ :as => opposite_for(relationship).to_sym
140
+ }
125
141
 
126
- join_value = value
127
- if join_context
128
- condition_string = "(#{ActsAsJoinable::Relationship.table_name.to_s}.context IN (?))"
129
- condition_string << " AND (#{ActsAsJoinable::Relationship.table_name.to_s}.value = ?)" if join_value
130
- join_contexts = [join_context, class_name.underscore]
131
- conditions = [condition_string, join_contexts]
132
- conditions << join_value.to_s if join_value
133
-
134
- through_options = {
135
- :class_name => "ActsAsJoinable::Relationship",
136
- :conditions => conditions,
137
- :as => opposite_for(relationship).to_sym
138
- }
139
-
140
- through_options[:uniq] = true unless association_type == :has_one
141
-
142
- # has_many :member_relationships
143
- # conditions: context == x, value == y
144
- send(:has_many, relationship_with_context, through_options)
145
-
146
- options = options.merge(
147
- :through => relationship_with_context,
148
- :source => relationship,
149
- :uniq => true
150
- )
142
+ if association_type == :has_one
143
+ options.delete(:after_add)
144
+ options.delete(:uniq)
145
+ else
146
+ through_options[:uniq] = true
151
147
  end
152
148
 
153
- options.delete(:after_add) if association_type == :has_one
154
- options.delete(:uniq) if association_type == :has_one
149
+ unless has_association?(through_relationship)
150
+ has_many through_relationship, through_options
151
+ end
155
152
 
156
- method_scope = association_type == :has_one ? :protected : :public
157
- #send(method_scope)
158
- # has_many :child_users, :through => :child_relationships
159
153
  add_association(relationship.to_s, plural_type, options, join_context, join_value, nestable, &block)
160
- add_has_one(singular_type, plural_type, relationship_with_context, class_name) if association_type == :has_one
154
+
155
+ if association_type == :has_one
156
+ add_has_one(singular_type, plural_type, through_relationship, class_name)
157
+ end
161
158
  end
162
159
  end
163
160
  end
@@ -172,12 +169,16 @@ module ActsAsJoinable
172
169
  role.to_s == "parent" ? "child" : "parent"
173
170
  end
174
171
 
172
+ def has_association?(name)
173
+ self.reflect_on_all_associations.map(&:name).include?(name.to_sym)
174
+ end
175
+
175
176
  def add_has_one(singular_type, plural_type, relationship_with_context, class_name)
176
177
  define_method singular_type do
177
178
  send(plural_type).last
178
179
  end
179
180
  define_method "#{singular_type}=" do |value|
180
- # send(relationship_with_context).delete_all
181
+ send(relationship_with_context).delete_all
181
182
  send(plural_type) << value
182
183
  end
183
184
  define_method "#{singular_type}_id" do
@@ -192,15 +193,24 @@ module ActsAsJoinable
192
193
  eval_options = {:context => join_context}
193
194
  eval_options[:value] = join_value unless join_value.blank?
194
195
  # has_many :users, :through => :child_relationships
196
+ plural_relationship = "#{relationship}_#{plural_type}".to_sym
197
+ unless has_association?(plural_relationship)
198
+ send(:has_many, plural_relationship, options) do
199
+ class_eval <<-EOF
200
+ def construct_join_attributes(associate)
201
+ super.merge(#{eval_options.inspect})
202
+ end
203
+ EOF
204
+ end
205
+ end
195
206
 
196
- unless self.reflect_on_all_associations.map(&:name).include?(plural_type.to_sym)
207
+ unless has_association?(plural_type)
197
208
  send(:has_many, plural_type.to_sym, options) do
198
209
  class_eval <<-EOF
199
210
  def construct_join_attributes(associate)
200
211
  super.merge(#{eval_options.inspect})
201
212
  end
202
213
  EOF
203
-
204
214
  end
205
215
  accepts_nested_attributes_for plural_type.to_sym if nestable
206
216
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-joinable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 3
10
+ version: 0.1.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Lance Pollard