Module: Glue::Orderable

Includes:
Aspects
Defined in:
lib/glue/orderable.rb

Overview

Attach list/ordering methods to the enchanted class.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included_with_parameters(base, opt) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/glue/orderable.rb', line 11

def self.included_with_parameters(base, opt)
  base.module_eval do

    opt_position = opt[:position] || 'position'

    opt_type = opt[:type] || Fixnum

    # provide a user defined condition.
    
    opt_condition = opt[:condition]

    # provide a condition based on a key field (?)
    
    opt_scope = opt[:scope]

    # clean scope field.
    
    if opt_scope
      if opt_scope.to_s !~ /_oid$/
        opt_scope = "#{opt_scope}_oid".to_sym
      else
        opt_scope = opt_scope.to_sym
      end
    end

    define_method :orderable_position do
      opt_position
    end

    define_method :orderable_type do
      opt_type
    end

    define_method :orderable_scope do
      opt_scope
    end

    define_method :orderable_condition do
      scope = orderable_scope
      if scope
        scope_value = send(scope)
        scope = scope_value ? "#{scope} = #{scope_value}" : "#{scope} IS NULL"
      end
      return [ opt_condition, scope ].compact
    end

    # How to check if property is already defined?
    
    unless method_defined?( opt_position )
      define_method( opt_position ) do @position ; end
      define_method( "#{opt_position}=" ) do |x| @position = x ; end
      property opt_position, opt_type
    end

    # Use position for general reference.
    
    attr_accessor :position

  end
end

Instance Method Details

#add_toObject



147
148
149
# File 'lib/glue/orderable.rb', line 147

def add_to
  # TODO
end

#add_to_bottomObject



143
144
145
# File 'lib/glue/orderable.rb', line 143

def add_to_bottom
  @position = bottom_position + 1
end

#add_to_topObject



139
140
141
# File 'lib/glue/orderable.rb', line 139

def add_to_top
  increment_position_of_all_items
end

#bottom?Boolean Also known as: last?

Returns:

  • (Boolean)


183
184
185
# File 'lib/glue/orderable.rb', line 183

def bottom?
  @position == bottom_position
end

#bottom_itemObject



170
171
172
173
174
175
# File 'lib/glue/orderable.rb', line 170

def bottom_item
  pos = orderable_position
  con = orderable_condition
  con = con.empty? ? nil : con.join(' AND ')
  self.class.one(:condition => con, :order => "#{pos} DESC", :limit => 1)
end

#bottom_positionObject



198
199
200
201
# File 'lib/glue/orderable.rb', line 198

def bottom_position
  item = bottom_item
  item ? item.send(orderable_position) : 0
end

#decrement_positionObject



193
194
195
196
# File 'lib/glue/orderable.rb', line 193

def decrement_position
  @position -= 1
  update_property(orderable_position.to_sym)
end

#decrement_position_of_lower_itemsObject



226
227
228
229
230
# File 'lib/glue/orderable.rb', line 226

def decrement_position_of_lower_items
  pos = orderable_position
  con = orderable_condition + [ "#{pos} > #{@position}" ]
  self.class.update "#{pos}=(#{pos} - 1)",  :condition => con.join(' AND ')
end

#higher_itemObject Also known as: previous_item



151
152
153
154
155
# File 'lib/glue/orderable.rb', line 151

def higher_item
  pos = orderable_position
  con = orderable_condition + [ "#{pos} = #{@position - 1}" ]
  self.class.one( :condition => con.join(' AND ') )
end

#increment_positionObject



188
189
190
191
# File 'lib/glue/orderable.rb', line 188

def increment_position
  @position += 1
  update_property(orderable_position.to_sym)
end

#increment_position_of_all_itemsObject



219
220
221
222
223
224
# File 'lib/glue/orderable.rb', line 219

def increment_position_of_all_items
  pos = orderable_position
  con = orderable_condition
  con = con.empty? ? nil : con.join(' AND ')
  self.class.update "#{pos}=(#{pos} + 1)", :condition => con 
end

#increment_position_of_higher_itemsObject



213
214
215
216
217
# File 'lib/glue/orderable.rb', line 213

def increment_position_of_higher_items
  pos = orderable_position
  con = orderable_condition + [ "#{pos} < #{@position}" ]
  self.class.update "#{pos}=(#{pos} + 1)",  :condition => con.join(' AND ')
end

#lower_itemObject Also known as: next_item



158
159
160
161
162
# File 'lib/glue/orderable.rb', line 158

def lower_item
  pos = orderable_position
  con = orderable_condition + [ "#{pos} = #{@position + 1}" ]
  self.class.one( :condition => con.join(' AND ') )
end

#move_higherObject

Move higher.



77
78
79
80
81
82
83
84
# File 'lib/glue/orderable.rb', line 77

def move_higher
  if higher = higher_item
    self.class.transaction do
      higher.increment_position
      decrement_position
    end
  end
end

#move_lowerObject

Move lower.



88
89
90
91
92
93
94
95
# File 'lib/glue/orderable.rb', line 88

def move_lower
  if lower = lower_item
    self.class.transaction do
      lower.decrement_position
      increment_position
    end
  end
end

#move_to(dest_position) ⇒ Object

Move to a specific position.



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/glue/orderable.rb', line 117

def move_to(dest_position)
  return if @position == dest_position

  pos = orderable_position
  con = orderable_condition

  self.class.transaction do
    if @position < dest_position
      adj = "#{pos} = #{pos} - 1"
      con = con + [ "#{pos} > #{@position}", "#{pos} <= #{dest_position}" ]
    else
      adj = "#{pos} = #{pos} + 1"
      con = con + [ "#{pos} < #{@position}", "#{pos} >= #{dest_position}" ]
    end
    self.class.update( adj, :condition => con.join(' AND ') )
    @position = dest_position
    update_property(pos.to_sym)
  end

  self
end

#move_to_bottomObject

Move to the bottom.



108
109
110
111
112
113
# File 'lib/glue/orderable.rb', line 108

def move_to_bottom
  self.class.transaction do
    decrement_position_of_lower_items
    set_bottom_position
  end
end

#move_to_topObject

Move to the top.



99
100
101
102
103
104
# File 'lib/glue/orderable.rb', line 99

def move_to_top
  self.class.transaction do
    increment_position_of_higher_items
    set_top_position
  end
end

#set_bottom_positionObject



208
209
210
211
# File 'lib/glue/orderable.rb', line 208

def set_bottom_position
  @position = bottom_position + 1
  update_property(orderable_position.to_sym)
end

#set_top_positionObject



203
204
205
206
# File 'lib/glue/orderable.rb', line 203

def set_top_position
  @position = 1
  update_property(orderable_position.to_sym)
end

#top?Boolean Also known as: first?

Returns:

  • (Boolean)


178
179
180
# File 'lib/glue/orderable.rb', line 178

def top?
  @position == 1
end

#top_itemObject Also known as: first_item



165
166
167
# File 'lib/glue/orderable.rb', line 165

def top_item
  # TODO
end