Module: RailsExtensions::HabtmList::AssociationListMethods

Defined in:
lib/webpulser-habtm_list.rb

Instance Method Summary collapse

Instance Method Details

#add_to_list_bottom(item) ⇒ Object



181
182
183
184
185
186
187
# File 'lib/webpulser-habtm_list.rb', line 181

def add_to_list_bottom(item)
  item.save! if item.id.nil? # Rails 2.0.2 - Callbacks don't save first on association.create()
  list_item_class.transaction do
    assume_bottom_position(item)
  end
  resort_array
end

#add_to_list_top(item) ⇒ Object



189
190
191
192
193
194
195
# File 'lib/webpulser-habtm_list.rb', line 189

def add_to_list_top(item)
  list_item_class.transaction do
    increment_positions_on_all_items
    assume_top_position(item)
  end
  resort_array
end

#assume_bottom_position(item) ⇒ Object



251
252
253
# File 'lib/webpulser-habtm_list.rb', line 251

def assume_bottom_position(item)
  set_position(item, self.length - 1)
end

#assume_top_position(item) ⇒ Object



255
256
257
# File 'lib/webpulser-habtm_list.rb', line 255

def assume_top_position(item)
  set_position(item, 0)
end

#decrement_position(item) ⇒ Object



275
276
277
# File 'lib/webpulser-habtm_list.rb', line 275

def decrement_position(item)
  increment_position_by(item, -1)
end

#decrement_positions_on_higher_items(position) ⇒ Object

This has the effect of moving all the higher items up one.



280
281
282
283
284
285
286
287
288
# File 'lib/webpulser-habtm_list.rb', line 280

def decrement_positions_on_higher_items(position)
  connection.update(
    "UPDATE #{join_table} SET #{position_column} = (#{position_column} - 1) " +
    "WHERE #{foreign_key} = #{owner.id} AND #{position_column} <= #{position}"
  )
  target.each { |obj|
    obj[position_column] = obj[position_column].to_i - 1 if in_list?(obj) && obj[position_column].to_i <= position
  } if target
end

#decrement_positions_on_lower_items(item) ⇒ Object

This has the effect of moving all the lower items up one.



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/webpulser-habtm_list.rb', line 85

def decrement_positions_on_lower_items(item)
  return unless in_list?(item)
  position = list_position(item)
  connection.update(
    "UPDATE #{join_table} SET #{position_column} = (#{position_column} - 1) " +
    "WHERE #{foreign_key} = #{owner.id} AND #{position_column} > #{position}"
  )
  target.each { |obj|
    obj[position_column] = obj[position_column].to_i - 1 if in_list?(obj) && obj[position_column].to_i > position
  } if target
end

#first?(item) ⇒ Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/webpulser-habtm_list.rb', line 159

def first?(item)
  item == self.first
end

#foreign_keyObject



239
240
241
# File 'lib/webpulser-habtm_list.rb', line 239

def foreign_key
  proxy_association.reflection.primary_key_name
end

#higher_item(item) ⇒ Object



167
168
169
170
# File 'lib/webpulser-habtm_list.rb', line 167

def higher_item(item)
  return nil unless in_list?(item)
  self.find(:first, :conditions => "#{position_column} = #{(list_position(item) - 1).to_s}")
end

#in_list?(item) ⇒ Boolean

Returns:

  • (Boolean)


177
178
179
# File 'lib/webpulser-habtm_list.rb', line 177

def in_list?(item)
  self.include?(item)
end

#increment_position(item) ⇒ Object



271
272
273
# File 'lib/webpulser-habtm_list.rb', line 271

def increment_position(item)
  increment_position_by(item, 1)
end

#increment_position_by(item, increment) ⇒ Object



259
260
261
262
263
264
265
266
267
268
269
# File 'lib/webpulser-habtm_list.rb', line 259

def increment_position_by(item, increment)
  return unless in_list?(item)
  connection.update(
    "UPDATE #{join_table} SET #{position_column} = #{position_column} + (#{increment}) " +
    "WHERE #{foreign_key} = #{owner.id} AND #{list_item_foreign_key} = #{item.id}"
  )
  if target
    obj = target.find {|obj| obj.id == item.id}
    obj[position_column] = obj[position_column].to_i + increment if obj
  end
end

#increment_positions_on_all_itemsObject



301
302
303
304
305
306
307
308
309
# File 'lib/webpulser-habtm_list.rb', line 301

def increment_positions_on_all_items
  connection.update(
    "UPDATE #{join_table} SET #{position_column} = (#{position_column} + 1) " +
    "WHERE #{foreign_key} = #{owner.id}"
  )
  target.each { |obj|
    obj[position_column] = obj[position_column].to_i + 1 if in_list?(obj)
  } if target
end

#increment_positions_on_higher_items(item) ⇒ Object

This has the effect of moving all the higher items down one.



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/webpulser-habtm_list.rb', line 98

def increment_positions_on_higher_items(item)
  return unless in_list?(item)
  position = list_position(item)
  connection.update(
    "UPDATE #{join_table} SET #{position_column} = (#{position_column} + 1) " +
    "WHERE #{foreign_key} = #{owner.id} AND #{position_column} < #{position}"
  )
  target.each { |obj|
    obj[position_column] = obj[position_column].to_i + 1 if in_list?(obj) && obj[position_column].to_i < position
  } if target
end

#increment_positions_on_lower_items(position) ⇒ Object

This has the effect of moving all the lower items down one.



291
292
293
294
295
296
297
298
299
# File 'lib/webpulser-habtm_list.rb', line 291

def increment_positions_on_lower_items(position)
  connection.update(
    "UPDATE #{join_table} SET #{position_column} = (#{position_column} + 1) " +
    "WHERE #{foreign_key} = #{owner.id} AND #{position_column} >= #{position}"
  )
  target.each { |obj|
    obj[position_column] = obj[position_column].to_i + 1 if in_list?(obj) && obj[position_column].to_i >= position
  } if target
end

#insert_at_position(item, position) ⇒ Object



79
80
81
82
# File 'lib/webpulser-habtm_list.rb', line 79

def insert_at_position(item, position)
  increment_positions_on_lower_items(position)
  set_position(item, position)
end

#join_tableObject



235
236
237
# File 'lib/webpulser-habtm_list.rb', line 235

def join_table
  proxy_association.reflection.options[:join_table]
end

#last?(item) ⇒ Boolean

Returns:

  • (Boolean)


163
164
165
# File 'lib/webpulser-habtm_list.rb', line 163

def last?(item)
  item == self.last
end

#list_item_classObject



223
224
225
# File 'lib/webpulser-habtm_list.rb', line 223

def list_item_class
  proxy_association.reflection.klass
end

#list_item_foreign_keyObject



243
244
245
# File 'lib/webpulser-habtm_list.rb', line 243

def list_item_foreign_key
  proxy_association.reflection.association_foreign_key
end

#list_position(item) ⇒ Object



247
248
249
# File 'lib/webpulser-habtm_list.rb', line 247

def list_position(item)
  self.index(item)
end

#lower_item(item) ⇒ Object



172
173
174
175
# File 'lib/webpulser-habtm_list.rb', line 172

def lower_item(item)
  return nil unless in_list?(item)
  self.find(:first, :conditions => "#{position_column} = #{(list_position(item) + 1).to_s}")
end

#move_higher(item) ⇒ Object



131
132
133
134
135
136
137
138
139
# File 'lib/webpulser-habtm_list.rb', line 131

def move_higher(item)
  list_item_class.transaction do
    higher = higher_item(item)
    return unless higher
    increment_position(higher)
    decrement_position(item)
  end
  resort_array
end

#move_lower(item) ⇒ Object



121
122
123
124
125
126
127
128
129
# File 'lib/webpulser-habtm_list.rb', line 121

def move_lower(item)
  list_item_class.transaction do
    lower = lower_item(item)
    return unless lower
    decrement_position(lower)
    increment_position(item)
  end
  resort_array
end

#move_to_bottom(item) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/webpulser-habtm_list.rb', line 141

def move_to_bottom(item)
  return unless in_list?(item)
  list_item_class.transaction do
    decrement_positions_on_lower_items(item)
    assume_bottom_position(item)
  end
  resort_array
end

#move_to_position(item, position) ⇒ Object



64
65
66
67
68
69
70
71
72
# File 'lib/webpulser-habtm_list.rb', line 64

def move_to_position(item, position)
  #return if !in_list?(item) || position.to_i == list_position(item)
  list_item_class.transaction do
    remove_from_list(item)
    decrement_positions_on_lower_items(item)
    insert_at_position(item, position)
  end
  resort_array
end

#move_to_top(item) ⇒ Object



150
151
152
153
154
155
156
157
# File 'lib/webpulser-habtm_list.rb', line 150

def move_to_top(item)
  return unless in_list?(item)
  list_item_class.transaction do
    increment_positions_on_higher_items(item)
    assume_top_position(item)
  end
  resort_array
end

#ownerObject



227
228
229
# File 'lib/webpulser-habtm_list.rb', line 227

def owner
  proxy_association.owner
end

#position_columnObject



219
220
221
# File 'lib/webpulser-habtm_list.rb', line 219

def position_column
  proxy_association.reflection.options[:order] || 'position'
end

#remove_from_list(item) ⇒ Object

should only be called externally from the before_remove callback



75
76
77
# File 'lib/webpulser-habtm_list.rb', line 75

def remove_from_list(item)
  item[position_column] = nil
end

#reset_positionsObject

“First aid” method in case someone shifts the array around outside these methods, or the positions in the joins table go totally out of whack. Don’t use it for simple ordering because it’s inefficient.



200
201
202
203
204
205
206
207
208
# File 'lib/webpulser-habtm_list.rb', line 200

def reset_positions
  self.each_index do |i|
    item = self[i]
    connection.update(
      "UPDATE #{join_table} SET #{position_column} = #{i} " +
      "WHERE #{foreign_key} = #{owner.id} AND #{list_item_foreign_key} = #{item.id}"
    )
  end
end

#reset_positions_by_ids(ids = self.collect(&:id)) ⇒ Object



210
211
212
213
214
215
216
217
# File 'lib/webpulser-habtm_list.rb', line 210

def reset_positions_by_ids(ids = self.collect(&:id))
  ids.each_with_index do |id, i|
    connection.update(
      "UPDATE #{join_table} SET #{position_column} = #{i} " +
      "WHERE #{foreign_key} = #{owner.id} AND #{list_item_foreign_key} = #{id}"
    ) if id.to_i != 0
  end
end

#resort_arrayObject

called after changing position values so the array reflects the updated ordering



312
313
314
# File 'lib/webpulser-habtm_list.rb', line 312

def resort_array
  target.sort! {|x,y| x[position_column].to_i <=> y[position_column].to_i} if target
end

#set_position(item, position) ⇒ Object



110
111
112
113
114
115
116
117
118
119
# File 'lib/webpulser-habtm_list.rb', line 110

def set_position(item, position)
  connection.update(
    "UPDATE #{join_table} SET #{position_column} = #{position} " +
    "WHERE #{foreign_key} = #{owner.id} AND #{list_item_foreign_key} = #{item.id}"
  ) if owner.id
  if target
    obj = target.find {|obj| obj.id == item.id}
    obj[position_column] = position if obj
  end
end

#targetObject



231
232
233
# File 'lib/webpulser-habtm_list.rb', line 231

def target
  proxy_association.target
end