osm 0.1.17 → 0.2.0

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