acts-as-joinable 0.1.1 → 0.1.3

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.
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