osm 0.1.17 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  module Osm
2
2
 
3
3
  class Event < Osm::Model
4
- class Column; end # Ensure the constant exists for the validators
4
+ class Column < Osm::Model; end # Ensure the constant exists for the validators
5
5
 
6
6
  # @!attribute [rw] id
7
7
  # @return [Fixnum] the id for the event
@@ -21,9 +21,6 @@ module Osm
21
21
  # @return [String] notes about the event
22
22
  # @!attribute [rw] archived
23
23
  # @return [Boolean] if the event has been archived
24
- # @!attribute [rw] fields
25
- # @deprecated use columns instead
26
- # @return [Hash] Keys are the field's id, values are the field names
27
24
  # @!attribute [rw] columns
28
25
  # @return [Array<Osm::Event::Column>] the custom columns for the event
29
26
  # @!attribute [rw] notepad
@@ -75,36 +72,41 @@ module Osm
75
72
 
76
73
  # @!method initialize
77
74
  # Initialize a new Event
78
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
75
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
79
76
 
80
77
 
81
78
  # Get events for a section
82
79
  # @param [Osm::Api] api The api to use to make the request
83
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the events for
80
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the events for
84
81
  # @!macro options_get
85
82
  # @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
86
83
  # @return [Array<Osm::Event>]
87
84
  def self.get_for_section(api, section, options={})
85
+ require_ability_to(api, :read, :events, section, options)
88
86
  section_id = section.to_i
89
87
  cache_key = ['events', section_id]
90
88
  events = nil
91
89
 
92
- if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permission(api, section_id, :events).include?(:read)
93
- return cache_read(api, cache_key)
90
+ if !options[:no_cache] && cache_exist?(api, cache_key)
91
+ ids = cache_read(api, cache_key)
92
+ events = get_from_ids(api, ids, 'event', section, options, :get_for_section)
94
93
  end
95
94
 
96
- data = api.perform_query("events.php?action=getEvents&sectionid=#{section_id}&showArchived=true")
97
-
98
- events = Array.new
99
- unless data['items'].nil?
100
- data['items'].map { |i| i['eventid'].to_i }.each do |event_id|
101
- event_data = api.perform_query("events.php?action=getEvent&sectionid=#{section_id}&eventid=#{event_id}")
102
- event = self.new_event_from_data(event_data)
103
- events.push event
104
- cache_write(api, ['event', event.id], event)
95
+ if events.nil?
96
+ data = api.perform_query("events.php?action=getEvents&sectionid=#{section_id}&showArchived=true")
97
+ events = Array.new
98
+ ids = Array.new
99
+ unless data['items'].nil?
100
+ data['items'].map { |i| i['eventid'].to_i }.each do |event_id|
101
+ event_data = api.perform_query("events.php?action=getEvent&sectionid=#{section_id}&eventid=#{event_id}")
102
+ event = self.new_event_from_data(event_data)
103
+ events.push event
104
+ ids.push event.id
105
+ cache_write(api, ['event', event.id], event)
106
+ end
105
107
  end
108
+ cache_write(api, cache_key, ids)
106
109
  end
107
- cache_write(api, cache_key, events)
108
110
 
109
111
  return events if options[:include_archived]
110
112
  return events.reject do |event|
@@ -114,16 +116,17 @@ module Osm
114
116
 
115
117
  # Get an event
116
118
  # @param [Osm::Api] api The api to use to make the request
117
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the events for
118
- # @param [Fixnum] event_id the id of the event to get
119
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the events for
120
+ # @param [Fixnum] event_id The id of the event to get
119
121
  # @!macro options_get
120
122
  # @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
121
123
  # @return [Osm::Event, nil] the event (or nil if it couldn't be found
122
124
  def self.get(api, section, event_id, options={})
125
+ require_ability_to(api, :read, :events, section, options)
123
126
  section_id = section.to_i
124
127
  cache_key = ['event', event_id]
125
128
 
126
- if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permission(api, section_id, :events).include?(:read)
129
+ if !options[:no_cache] && cache_exist?(api, cache_key)
127
130
  return cache_read(api, cache_key)
128
131
  end
129
132
 
@@ -135,10 +138,11 @@ module Osm
135
138
  # Create an event in OSM
136
139
  # @param [Osm::Api] api The api to use to make the request
137
140
  # @return [Osm::Event, nil] the created event, nil if failed
141
+ # @raise [Osm::ObjectIsInvalid] If the Event is invalid
138
142
  def self.create(api, parameters)
143
+ require_ability_to(api, :write, :events, parameters[:section_id])
139
144
  event = new(parameters)
140
- raise ObjectIsInvalid, 'event is invalid' unless event.valid?
141
- raise Forbidden, 'you do not have permission to write to events for this section' unless get_user_permission(api, event.section_id, :events).include?(:write)
145
+ raise Osm::ObjectIsInvalid, 'event is invalid' unless event.valid?
142
146
 
143
147
  data = api.perform_query("events.php?action=addEvent&sectionid=#{event.section_id}", {
144
148
  'name' => event.name,
@@ -172,7 +176,9 @@ module Osm
172
176
  # @param [Osm::Api] api The api to use to make the request
173
177
  # @return [Boolean] whether the update succedded
174
178
  def update(api)
175
- raise Forbidden, 'you do not have permission to write to events for this section' unless get_user_permission(api, section_id, :events).include?(:write)
179
+ require_ability_to(api, :write, :events, section_id)
180
+
181
+ to_update = changed_attributes
176
182
 
177
183
  data = api.perform_query("events.php?action=addEvent&sectionid=#{section_id}", {
178
184
  'eventid' => id,
@@ -190,49 +196,55 @@ module Osm
190
196
  'attendancelimit' => attendance_limit,
191
197
  'limitincludesleaders' => attendance_limit_includes_leaders,
192
198
  })
199
+
193
200
  api.perform_query("events.php?action=saveNotepad&sectionid=#{section_id}", {
194
201
  'eventid' => id,
195
202
  'notepad' => notepad,
196
- })
203
+ }) if to_update.include?('notepad')
204
+
197
205
  api.perform_query("events.php?action=saveNotepad&sectionid=#{section_id}", {
198
206
  'eventid' => id,
199
207
  'pnnotepad' => public_notepad,
200
- })
201
-
202
- # The cached events for the section will be out of date - remove them
203
- cache_delete(api, ['event', id])
204
- cache_delete(api, ['events', section_id])
208
+ }) if to_update.include?('public_notepad')
205
209
 
206
- return data.is_a?(Hash) && (data['id'].to_i == id)
210
+ if data.is_a?(Hash) && (data['id'].to_i == id)
211
+ reset_changed_attributes
212
+ # The cached event will be out of date - remove it
213
+ cache_delete(api, ['event', id])
214
+ return true
215
+ else
216
+ return false
217
+ end
207
218
  end
208
219
 
209
220
  # Delete event from OSM
210
221
  # @param [Osm::Api] api The api to use to make the request
211
222
  # @return [Boolean] whether the delete succedded
212
223
  def delete(api)
213
- raise Forbidden, 'you do not have permission to write to events for this section' unless get_user_permission(api, section_id, :events).include?(:write)
224
+ require_ability_to(api, :write, :events, section_id)
214
225
 
215
226
  data = api.perform_query("events.php?action=deleteEvent&sectionid=#{section_id}&eventid=#{id}")
216
227
 
217
- # The cached events for the section will be out of date - remove them
218
- cache_delete(api, ['events', section_id])
219
- cache_delete(api, ['event', id])
220
-
221
- return data.is_a?(Hash) ? data['ok'] : false
228
+ if data.is_a?(Hash) && data['ok']
229
+ cache_delete(api, ['event', id])
230
+ return true
231
+ end
232
+ return false
222
233
  end
223
234
 
224
235
 
225
236
  # Get event attendance
226
237
  # @param [Osm::Api] api The api to use to make the request
227
- # @param [Osm::Term, Fixnum, nil] term the term (or its ID) to get the members for, passing nil causes the current term to be used
238
+ # @param [Osm::Term, Fixnum, #to_i, nil] term The term (or its ID) to get the members for, passing nil causes the current term to be used
228
239
  # @!macro options_get
229
240
  # @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
230
241
  # @return [Array<Osm::Event::Attendance>]
231
242
  def get_attendance(api, term=nil, options={})
243
+ require_ability_to(api, :read, :events, section_id, options)
232
244
  term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section_id).id : term.to_i
233
245
  cache_key = ['event_attendance', id]
234
246
 
235
- if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permission(api, section_id, :events).include?(:read)
247
+ if !options[:no_cache] && cache_exist?(api, cache_key)
236
248
  return cache_read(api, cache_key)
237
249
  end
238
250
 
@@ -264,12 +276,13 @@ module Osm
264
276
 
265
277
  # Add a column to the event in OSM
266
278
  # @param [Osm::Api] api The api to use to make the request
267
- # @param [String] label the label for the field in OSM
268
- # @param [String] name the label for the field in My.SCOUT (if this is blank then parents can't edit it)
279
+ # @param [String] label The label for the field in OSM
280
+ # @param [String] name The label for the field in My.SCOUT (if this is blank then parents can't edit it)
269
281
  # @return [Boolean] whether the update succedded
282
+ # @raise [Osm::ArgumentIsInvalid] If the name is blank
270
283
  def add_column(api, name, label='')
271
- raise ArgumentIsInvalid, 'name is invalid' if name.blank?
272
- raise Forbidden, 'you do not have permission to write to events for this section' unless get_user_permission(api, section_id, :events).include?(:write)
284
+ require_ability_to(api, :write, :events, section_id)
285
+ raise Osm::ArgumentIsInvalid, 'name is invalid' if name.blank?
273
286
 
274
287
  data = api.perform_query("events.php?action=addColumn&sectionid=#{section_id}&eventid=#{id}", {
275
288
  'columnName' => name,
@@ -286,41 +299,8 @@ module Osm
286
299
  return data.is_a?(Hash) && (data['eventid'].to_i == id)
287
300
  end
288
301
 
289
- # Add a field in OSM
290
- # @deprecated use add_column instead
291
- # @param [Osm::Api] api The api to use to make the request
292
- # @param [String] field_label the label for the field to add
293
- # @return [Boolean] whether the update succedded
294
- # TODO - Remove this method when upping the version
295
- def add_field(api, label)
296
- warn "[DEPRECATION OF METHOD] this method is being depreiated, use add_column instead"
297
- raise ArgumentIsInvalid, 'label is invalid' if label.blank?
298
- raise Forbidden, 'you do not have permission to write to events for this section' unless get_user_permission(api, section_id, :events).include?(:write)
299
-
300
- data = api.perform_query("events.php?action=addColumn&sectionid=#{section_id}&eventid=#{id}", {
301
- 'columnName' => label,
302
- 'parentLabel' => ''
303
- })
304
-
305
- # The cached events for the section will be out of date - remove them
306
- cache_delete(api, ['events', section_id])
307
- cache_delete(api, ['event', id])
308
- cache_delete(api, ['event_attendance', id])
309
-
310
- return data.is_a?(Hash) && (data['eventid'].to_i == id)
311
- end
312
-
313
-
314
- # TODO - Remove this attribute when upping the version
315
- def fields
316
- warn "[DEPRECATION OF ATTRIBUTE] this attribute is being depreiated, in favor of returning an array of Field objects."
317
- return columns.inject({}){ |h,(c)| h[c.id] = c.name; h}
318
- end
319
- def fields=(value)
320
- raise "[DEPRECATION OF ATTRIBUTE] this attribute is being depreiated, in favor of returning an array of Field objects."
321
- end
322
-
323
-
302
+ # Whether thete is a limit on attendance for this event
303
+ # @return [Boolean] whether thete is a limit on attendance for this event
324
304
  def limited_attendance?
325
305
  (attendance_limit != 0)
326
306
  end
@@ -380,10 +360,7 @@ module Osm
380
360
  end
381
361
 
382
362
 
383
- class Column
384
- include ::ActiveAttr::MassAssignmentSecurity
385
- include ::ActiveAttr::Model
386
-
363
+ class Column < Osm::Model
387
364
  # @!attribute [rw] id
388
365
  # @return [String] OSM id for the column
389
366
  # @!attribute [rw] name
@@ -406,14 +383,14 @@ module Osm
406
383
 
407
384
  # @!method initialize
408
385
  # Initialize a new Column
409
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
386
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
410
387
 
411
388
 
412
389
  # Update event column in OSM
413
390
  # @param [Osm::Api] api The api to use to make the request
414
391
  # @return [Boolean] if the operation suceeded or not
415
392
  def update(api)
416
- raise Forbidden, 'you do not have permission to write to events for this section' unless Osm::Model.get_user_permission(api, event.section_id, :events).include?(:write)
393
+ require_ability_to(api, :write, :events, event.section_id)
417
394
 
418
395
  data = api.perform_query("events.php?action=renameColumn&sectionid=#{event.section_id}&eventid=#{event.id}", {
419
396
  'columnId' => id,
@@ -421,13 +398,16 @@ module Osm
421
398
  'pL' => label
422
399
  })
423
400
 
424
- # The cached events for the section will be out of date - remove them
425
- Osm::Model.cache_delete(api, ['events', event.section_id])
426
- Osm::Model.cache_delete(api, ['event', event.id])
427
-
428
401
  (ActiveSupport::JSON.decode(data['config']) || []).each do |i|
429
402
  if i['id'] == id
430
- return i['name'].eql?(name) && (i['pL'].nil? || i['pL'].eql?(label))
403
+ if i['name'].eql?(name) && (i['pL'].nil? || i['pL'].eql?(label))
404
+ reset_changed_attributes
405
+ # The cached event will be out of date - remove it
406
+ cache_delete(api, ['event', event.id])
407
+ # The cached event attedance will be out of date
408
+ cache_delete(api, ['event_attendance', event.id])
409
+ return true
410
+ end
431
411
  end
432
412
  end
433
413
  return false
@@ -437,16 +417,12 @@ module Osm
437
417
  # @param [Osm::Api] api The api to use to make the request
438
418
  # @return [Boolean] whether the delete succedded
439
419
  def delete(api)
440
- raise Forbidden, 'you do not have permission to write to events for this section' unless Osm::Model.get_user_permission(api, event.section_id, :events).include?(:write)
420
+ require_ability_to(api, :write, :events, event.section_id)
441
421
 
442
422
  data = api.perform_query("events.php?action=deleteColumn&sectionid=#{event.section_id}&eventid=#{event.id}", {
443
423
  'columnId' => id
444
424
  })
445
425
 
446
- # The cached events for the section will be out of date - remove them
447
- Osm::Model.cache_delete(api, ['events', event.section_id])
448
- Osm::Model.cache_delete(api, ['event', event.id])
449
-
450
426
  (ActiveSupport::JSON.decode(data['config']) || []).each do |i|
451
427
  return false if i['id'] == id
452
428
  end
@@ -456,16 +432,15 @@ module Osm
456
432
  new_columns.push(column) unless column == self
457
433
  end
458
434
  event.columns = new_columns
435
+
436
+ cache_write(api, ['event', event.id], event)
459
437
  return true
460
438
  end
461
439
 
462
440
  end # class Column
463
441
 
464
442
 
465
- class Attendance
466
- include ::ActiveAttr::MassAssignmentSecurity
467
- include ::ActiveAttr::Model
468
-
443
+ class Attendance < Osm::Model
469
444
  # @!attribute [rw] member_id
470
445
  # @return [Fixnum] OSM id for the member
471
446
  # @!attribute [rw] grouping__id
@@ -496,16 +471,17 @@ module Osm
496
471
 
497
472
  # @!method initialize
498
473
  # Initialize a new Attendance
499
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
474
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
500
475
 
501
476
 
502
477
  # Update event attendance
503
478
  # @param [Osm::Api] api The api to use to make the request
504
- # @param [String] field_id the id of the field to update (must be 'attending' or /\Af_\d+\Z/)
479
+ # @param [String] field_id The id of the field to update (must be 'attending' or /\Af_\d+\Z/)
505
480
  # @return [Boolean] if the operation suceeded or not
481
+ # @raise [Osm::ArgumentIsInvalid] If field_id does not match the pattern "f_#{number}" or is "attending"
506
482
  def update(api, field_id)
507
- raise ArgumentIsInvalid, 'field_id is invalid' unless field_id.match(/\Af_\d+\Z/) || field_id.eql?('attending')
508
- raise Forbidden, 'you do not have permission to write to events for this section' unless Osm::Model.get_user_permission(api, event.section_id, :events).include?(:write)
483
+ require_ability_to(api, :write, :events, event.section_id)
484
+ raise Osm::ArgumentIsInvalid, 'field_id is invalid' unless field_id.match(/\Af_\d+\Z/) || field_id.eql?('attending')
509
485
 
510
486
  data = api.perform_query("events.php?action=updateScout", {
511
487
  'scoutid' => member_id,
@@ -515,11 +491,15 @@ module Osm
515
491
  'row' => row,
516
492
  'eventid' => event.id,
517
493
  })
518
-
519
- # The cached event attedance will be out of date
520
- Osm::Model.cache_delete(api, ['event_attendance', event.id])
521
-
522
- return data.is_a?(Hash)
494
+
495
+ if data.is_a?(Hash)
496
+ reset_changed_attributes
497
+ # The cached event attedance will be out of date
498
+ Osm::Model.cache_delete(api, ['event_attendance', event.id])
499
+ return true
500
+ else
501
+ return false
502
+ end
523
503
  end
524
504
 
525
505
  end # Class Attendance
@@ -1,32 +1,46 @@
1
- # TODO make 'proper' class
2
-
3
1
  module Osm
4
2
 
5
- class FlexiRecord
3
+ class FlexiRecord < Osm::Model
4
+ # @!attribute [rw] id
5
+ # @return [Fixnum] the id for the flexi_record
6
+ # @!attribute [rw] section_id
7
+ # @return [Fixnum] the section the member belongs to
8
+ # @!attribute [rw] name
9
+ # @return [String] the flexi record's name name
10
+
11
+ attribute :id, :type => Integer
12
+ attribute :section_id, :type => Integer
13
+ attribute :name, :type => String
14
+
15
+ attr_accessible :id, :section_id, :name
16
+
17
+ validates_numericality_of :id, :only_integer=>true, :greater_than=>0, :unless => Proc.new { |r| r.id.nil? }
18
+ validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
19
+ validates_presence_of :name
6
20
 
7
- # Get structure for a flexi record
21
+
22
+ # Get structure for the flexi record
8
23
  # @param [Osm::Api] api The api to use to make the request
9
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the structure for
10
- # @param [Fixnum] id the id of the Flexi Record
11
24
  # @!macro options_get
12
- # @return [Array<Osm::FlexiRecordField>] representing the fields of the flexi record
13
- def self.get_fields(api, section, id, options={})
14
- section_id = section.to_i
15
- cache_key = ['flexi_record_fields', id]
25
+ # @return [Array<Osm::FlexiRecordColumn>] representing the columns of the flexi record
26
+ def get_columns(api, options={})
27
+ require_ability_to(api, :read, :flexi, section_id, options)
28
+ cache_key = ['flexi_record_columns', self.id]
16
29
 
17
- if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key) && Osm::Model.get_user_permission(api, section_id, :flexi).include?(:read)
30
+ if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key)
18
31
  return Osm::Model.cache_read(api, cache_key)
19
32
  end
20
33
 
21
- data = api.perform_query("extras.php?action=getExtra&sectionid=#{section_id}&extraid=#{id}")
34
+ data = api.perform_query("extras.php?action=getExtra&sectionid=#{self.section_id}&extraid=#{self.id}")
22
35
 
23
36
  structure = []
24
37
  data['structure'].each do |item|
25
38
  item['rows'].each do |row|
26
- structure.push Osm::FlexiRecord::Field.new(
39
+ structure.push Osm::FlexiRecord::Column.new(
27
40
  :id => row['field'],
28
41
  :name => row['name'],
29
42
  :editable => row['editable'] || false,
43
+ :flexi_record => self,
30
44
  )
31
45
  end
32
46
  end
@@ -35,15 +49,13 @@ module Osm
35
49
  return structure
36
50
  end
37
51
 
38
- # Add a field in OSM
52
+ # Add a column in OSM
39
53
  # @param [Osm::Api] api The api to use to make the request
40
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the structure for
41
- # @param [Fixnum] id the id of the Flexi Record
42
54
  # @param [String] name The name for the created column
43
- # @return [Boolean] whether the field was created in OSM
44
- def self.add_field(api, section, id, name)
55
+ # @return [Boolean] whether the column was created in OSM
56
+ def add_column(api, name)
57
+ require_ability_to(api, :write, :flexi, section_id)
45
58
  raise ArgumentError, 'name is invalid' if name.blank?
46
- section_id = section.to_i
47
59
 
48
60
  data = api.perform_query("extras.php?action=addColumn&sectionid=#{section_id}&extraid=#{id}", {
49
61
  'columnName' => name,
@@ -53,35 +65,7 @@ module Osm
53
65
  ActiveSupport::JSON.decode(data['config']).each do |field|
54
66
  if field['name'] == name
55
67
  # The cached fields for the flexi record will be out of date - remove them
56
- Osm::Model.cache_delete(api, ['flexi_record_fields', id])
57
- return true
58
- end
59
- end
60
- end
61
- return false
62
- end
63
-
64
- # Update a field in OSM
65
- # @param [Osm::Api] api The api to use to make the request
66
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the structure for
67
- # @param [Fixnum] id the id of the Flexi Record
68
- # @param [String] field the id of the Flexi Record Field
69
- # @param [String] name The new name for the created column
70
- # @return [Boolean] whether the field was updated in OSM
71
- def self.update_field(api, section, id, field, name)
72
- raise ArgumentError, 'name is invalid' if name.blank?
73
- section_id = section.to_i
74
-
75
- data = api.perform_query("extras.php?action=renameColumn&sectionid=#{section_id}&extraid=#{id}", {
76
- 'columnId' => field,
77
- 'columnName' => name,
78
- })
79
-
80
- if (data.is_a?(Hash) && data.has_key?('config'))
81
- ActiveSupport::JSON.decode(data['config']).each do |f|
82
- if (f['id'] == field) && (f['name'] == name)
83
- # The cached fields for the flexi record will be out of date - remove them
84
- Osm::Model.cache_delete(api, ['flexi_record_fields', id])
68
+ Osm::Model.cache_delete(api, ['flexi_record_columns', id])
85
69
  return true
86
70
  end
87
71
  end
@@ -89,46 +73,18 @@ module Osm
89
73
  return false
90
74
  end
91
75
 
92
- # Update a field in OSM
93
- # @param [Osm::Api] api The api to use to make the request
94
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the structure for
95
- # @param [Fixnum] id the id of the Flexi Record
96
- # @param [String] field the id of the Flexi Record Field
97
- # @return [Boolean] whether the field was updated in OSM
98
- def self.delete_field(api, section, id, field)
99
- section_id = section.to_i
100
-
101
- data = api.perform_query("extras.php?action=deleteColumn&sectionid=#{section_id}&extraid=#{id}", {
102
- 'columnId' => field,
103
- })
104
-
105
- if (data.is_a?(Hash) && data.has_key?('config'))
106
- ActiveSupport::JSON.decode(data['config']).each do |f|
107
- if f['id'] == field
108
- # It wasn't deleted
109
- return false
110
- end
111
- end
112
- end
113
-
114
- # The cached fields for the flexi record will be out of date - remove them
115
- Osm::Model.cache_delete(api, ['flexi_record_fields', id])
116
- return true
117
- end
118
-
119
76
  # Get data for flexi record
120
77
  # @param [Osm::Api] api The api to use to make the request
121
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the register for
122
- # @param [Fixnum] the id of the Flexi Record
123
- # @param [Osm::Term, Fixnum, nil] section the term (or its ID) to get the register for, passing nil causes the current term to be used
78
+ # @param [Osm::Term, Fixnum, #to_i, nil] term The term (or its ID) to get the register for, passing nil causes the current term to be used
124
79
  # @!macro options_get
125
80
  # @return [Array<FlexiRecordData>]
126
- def self.get_data(api, section, id, term=nil, options={})
127
- section = Osm::Section.get(api, section) if section.is_a?(Fixnum)
81
+ def get_data(api, term=nil, options={})
82
+ require_ability_to(api, :read, :flexi, section_id, options)
83
+ section = Osm::Section.get(api, self.section_id)
128
84
  term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section).id : term.to_i
129
85
  cache_key = ['flexi_record_data', id, term_id]
130
86
 
131
- if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key) && Osm::Model.get_user_permission(api, section.id, :flexi).include?(:read)
87
+ if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key)
132
88
  return Osm::Model.cache_read(api, cache_key)
133
89
  end
134
90
 
@@ -150,7 +106,8 @@ module Osm
150
106
  to_return.push Osm::FlexiRecord::Data.new(
151
107
  :member_id => Osm::to_i_or_nil(item['scoutid']),
152
108
  :grouping_id => Osm::to_i_or_nil(item['patrolid'].eql?('') ? nil : item['patrolid']),
153
- :fields => fields
109
+ :fields => fields,
110
+ :flexi_record => self,
154
111
  )
155
112
  end
156
113
  end
@@ -159,40 +116,20 @@ module Osm
159
116
  return to_return
160
117
  end
161
118
 
162
- # Update a field in OSM
163
- # @param [Osm::Api] api The api to use to make the request
164
- # @param [Osm::Section, Fixnum] section the section (or its ID) to update the data for
165
- # @param [Fixnum] flexi_record_id the id of the Flexi Record
166
- # @param [Osm::Member, Fixnum] member the member (or their ID) to update
167
- # @param [String] column the id of the Flexi Record Field
168
- # @param [String] value The updated value
169
- # @return [Boolean] whether the field was updated in OSM
170
- def self.update_data(api, section, flexi_record_id, member, column, value)
171
- raise ArgumentError, 'name is invalid' if name.blank?
172
- section_id = section.to_i
173
- member_id = member.to_i
174
- term_id = Osm::Term.get_current_term_for_section(api, section).id
175
-
176
- data = api.perform_query("extras.php?action=updateScout", {
177
- 'termid' => term_id,
178
- 'scoutid' => member_id,
179
- 'column' => column,
180
- 'value' => value,
181
- 'sectionid' => section_id,
182
- 'extraid' => flexi_record_id,
183
- })
184
119
 
185
- if (data.is_a?(Hash) && data['items'].is_a?(Array))
186
- data['items'].each do |item|
187
- return true if (item[column] == value) && (item['scoutid'] == member_id.to_s)
188
- end
120
+ def <=>(another)
121
+ begin
122
+ return self.name <=> another.name
123
+ rescue NoMethodError
124
+ return 1
189
125
  end
190
- return false
191
126
  end
192
127
 
193
128
 
194
129
 
195
- class Field < Osm::Model
130
+ class Column < Osm::Model
131
+ # @!attribute [rw] flexi_record
132
+ # @return [Boolean] The FlexiRecord this column belongs to
196
133
  # @!attribute [rw] id
197
134
  # @return [String] OSM identifier for the field. Special ones are 'dob', 'total', 'completed', 'age', 'firstname' and 'lastname', user ones are of the format 'f\_NUMBER'
198
135
  # @!attribute [rw] name
@@ -200,24 +137,83 @@ module Osm
200
137
  # @!attribute [rw] editable
201
138
  # @return [Boolean] Wether the field can be edited
202
139
 
140
+ attribute :flexi_record, :type => Object
203
141
  attribute :id, :type => String
204
142
  attribute :name, :type => String
205
143
  attribute :editable, :type => Boolean, :default => false
206
144
 
207
- attr_accessible :id, :name, :editable
145
+ attr_accessible :flexi_record, :id, :name, :editable
208
146
 
147
+ validates_presence_of :flexi_record
209
148
  validates_presence_of :id
210
149
  validates_presence_of :name
211
150
  validates_inclusion_of :editable, :in => [true, false]
212
151
 
213
152
  # @!method initialize
214
- # Initialize a new FlexiRecordField
215
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
153
+ # Initialize a new FlexiRecord::Column
154
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
155
+
156
+
157
+ # Update a column in OSM
158
+ # @param [Osm::Api] api The api to use to make the request
159
+ # @return [Boolean] whether the column was updated in OSM
160
+ # @raise [Osm::ObjectIsInvalid] If the Column is invalid
161
+ # @raise [Osm::Forbidden] If the COlumn is not editable
162
+ def update(api)
163
+ raise Osm::ObjectIsInvalid, 'column is invalid' unless valid?
164
+ require_ability_to(api, :write, :flexi, flexi_record.section_id)
165
+ raise Osm::Forbidden, 'this column is not editable' unless self.editable
166
+
167
+ data = api.perform_query("extras.php?action=renameColumn&sectionid=#{flexi_record.section_id}&extraid=#{flexi_record.id}", {
168
+ 'columnId' => self.id,
169
+ 'columnName' => self.name,
170
+ })
171
+
172
+ if (data.is_a?(Hash) && data.has_key?('config'))
173
+ ActiveSupport::JSON.decode(data['config']).each do |f|
174
+ if (f['id'] == self.id) && (f['name'] == self.name)
175
+ reset_changed_attributes
176
+ # The cached columns for the flexi record will be out of date - remove them
177
+ cache_delete(api, ['flexi_record_columns', flexi_record.id])
178
+ return true
179
+ end
180
+ end
181
+ end
182
+ return false
183
+ end
216
184
 
217
- end # Class FlexiRecord::Data
185
+ # Delete a column in OSM
186
+ # @param [Osm::Api] api The api to use to make the request
187
+ # @return [Boolean] whether the column was deleted from OSM
188
+ # @raise [Osm::Forbidden] If this Column is not editable
189
+ def delete(api)
190
+ require_ability_to(api, :write, :flexi, flexi_record.section_id)
191
+ raise Osm::Forbidden, 'this column is not editable' unless self.editable
192
+
193
+ data = api.perform_query("extras.php?action=deleteColumn&sectionid=#{flexi_record.section_id}&extraid=#{flexi_record.id}", {
194
+ 'columnId' => self.id,
195
+ })
196
+
197
+ if (data.is_a?(Hash) && data.has_key?('config'))
198
+ ActiveSupport::JSON.decode(data['config']).each do |f|
199
+ if f['id'] == self.id
200
+ # It wasn't deleted
201
+ return false
202
+ end
203
+ end
204
+ end
205
+
206
+ # The cached columns for the flexi record will be out of date - remove them
207
+ cache_delete(api, ['flexi_record_columns', flexi_record.id])
208
+ return true
209
+ end
210
+
211
+ end # Class FlexiRecord::Column
218
212
 
219
213
 
220
214
  class Data < Osm::Model
215
+ # @!attribute [rw] flexi_record
216
+ # @return [Boolean] The FlexiRecord this column belongs to
221
217
  # @!attribute [rw] member_id
222
218
  # @return [Fixnum] OSM id for the member
223
219
  # @!attribute [rw] grouping__id
@@ -225,20 +221,65 @@ module Osm
225
221
  # @!attribute [rw] fields
226
222
  # @return [Hash] Keys are the field's id, values are the field values
227
223
 
224
+ attribute :flexi_record, :type => Object
228
225
  attribute :member_id, :type => Integer
229
226
  attribute :grouping_id, :type => Integer
230
227
  attribute :fields, :default => {}
231
228
 
232
- attr_accessible :member_id, :grouping_id, :fields
229
+ attr_accessible :flexi_record, :member_id, :grouping_id, :fields
233
230
 
231
+ validates_presence_of :flexi_record
234
232
  validates_numericality_of :member_id, :only_integer=>true, :greater_than=>0
235
233
  validates_numericality_of :grouping_id, :only_integer=>true, :greater_than_or_equal_to=>-2
236
234
  validates :fields, :hash => {:key_type => String}
237
235
 
238
236
  # @!method initialize
239
- # Initialize a new FlexiRecordData
240
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
241
-
237
+ # Initialize a new FlexiRecord::Data
238
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
239
+
240
+
241
+ # Update data in OSM
242
+ # @param [Osm::Api] api The api to use to make the request
243
+ # @return [Boolean] whether the data was updated in OSM
244
+ # @raise [Osm::ObjectIsInvalid] If the Data is invalid
245
+ def update(api)
246
+ raise Osm::ObjectIsInvalid, 'data is invalid' unless valid?
247
+ require_ability_to(api, :write, :flexi, flexi_record.section_id)
248
+
249
+ term_id = Osm::Term.get_current_term_for_section(api, flexi_record.section_id).id
250
+
251
+ updated = true
252
+ flexi_record.get_columns(api).each do |column|
253
+ if column.editable
254
+ data = api.perform_query("extras.php?action=updateScout", {
255
+ 'termid' => term_id,
256
+ 'scoutid' => self.member_id,
257
+ 'column' => column.id,
258
+ 'value' => fields[column.id],
259
+ 'sectionid' => flexi_record.section_id,
260
+ 'extraid' => flexi_record.id,
261
+ })
262
+ if (data.is_a?(Hash) && data['items'].is_a?(Array))
263
+ data['items'].each do |item|
264
+ if item['scoutid'] == member_id.to_s # Find this member from the list of all members
265
+ updated = false unless item[column.id] == self.fields[column.id]
266
+ end
267
+ end
268
+ else
269
+ updated = false
270
+ end
271
+ end
272
+ end
273
+
274
+ if updated
275
+ reset_changed_attributes
276
+ # The cached datas for the flexi record will be out of date - remove them
277
+ cache_delete(api, ['flexi_record_data', flexi_record.id])
278
+ end
279
+
280
+ return updated
281
+ end
282
+
242
283
  end # Class FlexiRecord::Data
243
284
 
244
285
  end # Class FlexiRecord