osm 0.0.17 → 0.0.18

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,59 +1,74 @@
1
1
  module Osm
2
2
 
3
3
  class Section
4
+ class FlexiRecord; end # Ensure the constant exists for the validators
4
5
 
5
- attr_reader :id, :name, :subscription_level, :subscription_expires, :type, :num_scouts, :column_names, :fields, :intouch_fields, :mobile_fields, :flexi_records, :role
6
- # @!attribute [r] id
6
+ include ::ActiveAttr::MassAssignmentSecurity
7
+ include ::ActiveAttr::Model
8
+
9
+ # @!attribute [rw] id
7
10
  # @return [Fixnum] the id for the section
8
- # @!attribute [r] name
11
+ # @!attribute [rw] name
9
12
  # @return [String] the section name
10
- # @!attribute [r] subscription_level
13
+ # @!attribute [rw] subscription_level
11
14
  # @return [Symbol] what subscription the section has to OSM (:bronze, :silver or :gold)
12
- # @!attribute [r] subscription_expires
15
+ # @!attribute [rw] subscription_expires
13
16
  # @return [Date] when the section's subscription to OSM expires
14
- # @!attribute [r] type
17
+ # @!attribute [rw] type
15
18
  # @return [Symbol] the section type (:beavers, :cubs, :scouts, :exporers, :adults, :waiting, :unknown)
16
- # @!attribute [r] num_scouts
19
+ # @!attribute [rw] num_scouts
17
20
  # @return [Fixnum] how many members the section has
18
- # @!attribute [r] column_names
21
+ # @!attribute [rw] column_names
19
22
  # @return [Hash] custom names to use for the data columns
20
- # @!attribute [r] fields
23
+ # @!attribute [rw] fields
21
24
  # @return [Hash] which columns are shown in OSM
22
- # @!attribute [r] intouch_fields
25
+ # @!attribute [rw] intouch_fields
23
26
  # @return [Hash] which columns are shown in OSM's in touch reports
24
- # @!attribute [r] mobile_fields
27
+ # @!attribute [rw] mobile_fields
25
28
  # @return [Hash] which columns are shown in the OSM mobile app
26
- # @!attribute [r] flexi_records
29
+ # @!attribute [rw] flexi_records
27
30
  # @return [Array<FlexiRecord>] list of the extra records the section has
28
- # @!attribute [r] role
31
+ # @!attribute [rw] role
29
32
  # @return [Osm::Role] the role linking the user to this section
30
33
 
31
-
32
- # Initialize a new Section
33
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
34
- def initialize(attributes={})
35
- raise ArgumentError, ':id must be nil or a Fixnum > 0' unless attributes[:id].nil? || (attributes[:id].is_a?(Fixnum) && attributes[:id] > 0)
36
- raise ArgumentError, ':section_name must be nil or a String' unless attributes[:section_name].nil? || attributes[:section_name].is_a?(String)
37
- raise ArgumentError, ':num_scouts must be nil or a Fixnum >= 0' unless attributes[:num_scouts].nil? || (attributes[:num_scouts].is_a?(Fixnum) && attributes[:num_scouts] >= 0)
38
- [:column_names, :fields, :intouch_fields, :mobile_fields].each do |attribute|
39
- raise ArgumentError, ":#{attribute} must be nil or a Hash" unless attributes[attribute].nil? || attributes[attribute].is_a?(Hash)
40
- end
41
- [:type, :subscription_level].each do |attribute|
42
- raise ArgumentError, ":#{attribute} must be nil or a Symbol" unless attributes[attribute].nil? || attributes[attribute].is_a?(Symbol)
43
- end
44
- raise ArgumentError, ':flexi_records must be nil or an Array' unless attributes[:flexi_records].nil? || attributes[:flexi_records].is_a?(Array)
45
-
46
- attributes.each { |k,v| instance_variable_set("@#{k}", v) }
47
-
48
- @section_name ||= ''
49
- @column_names ||= {}
50
- @fields ||= {}
51
- @intouch_fields ||= {}
52
- @mobile_fields ||= {}
53
- @flexi_records ||= []
54
- @subscription_level ||= :unknown
55
- @type ||= :unknown
56
- end
34
+ attribute :id, :type => Integer
35
+ attribute :name, :type => String
36
+ attribute :subscription_level, :default => :unknown
37
+ attribute :subscription_expires, :type => Date
38
+ attribute :type, :default => :unknown
39
+ attribute :num_scouts, :type => Integer
40
+ attribute :column_names, :default => {}
41
+ attribute :fields, :default => {}
42
+ attribute :intouch_fields, :default => {}
43
+ attribute :mobile_fields, :default => {}
44
+ attribute :flexi_records, :default => []
45
+ attribute :role
46
+
47
+ attr_accessible :id, :name, :subscription_level, :subscription_expires, :type, :num_scouts, :column_names, :fields, :intouch_fields, :mobile_fields, :flexi_records, :role
48
+
49
+ validates_numericality_of :id, :only_integer=>true, :greater_than=>0, :allow_nil => true
50
+ validates_numericality_of :num_scouts, :only_integer=>true, :greater_than_or_equal_to=>0
51
+ validates_presence_of :subscription_level
52
+ validates_presence_of :subscription_expires
53
+ validates_presence_of :type
54
+ validates_presence_of :column_names, :unless => Proc.new { |a| a.column_names == {} }
55
+ validates_presence_of :fields, :unless => Proc.new { |a| a.fields == {} }
56
+ validates_presence_of :intouch_fields, :unless => Proc.new { |a| a.intouch_fields == {} }
57
+ validates_presence_of :mobile_fields, :unless => Proc.new { |a| a.mobile_fields == {} }
58
+ validates_presence_of :flexi_records, :unless => Proc.new { |a| a.flexi_records == [] }
59
+ validates_presence_of :role
60
+
61
+ validates_inclusion_of :subscription_level, :in => [:bronze, :silver, :gold, :unknown], :message => 'is not a valid level'
62
+
63
+ validates :column_names, :hash => {:key_type => Symbol, :value_type => String}
64
+ validates :fields, :hash => {:key_type => Symbol, :value_type => String}
65
+ validates :intouch_fields, :hash => {:key_type => Symbol, :value_type => String}
66
+ validates :mobile_fields, :hash => {:key_type => Symbol, :value_type => String}
67
+
68
+
69
+ # @!method initialize
70
+ # Initialize a new Section
71
+ # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
57
72
 
58
73
 
59
74
  # Initialize a new Sections from api data
@@ -80,12 +95,10 @@ module Osm
80
95
  :flexi_records => [],
81
96
  }
82
97
 
83
-
84
98
  # Populate arrays
85
99
  (data['extraRecords'].is_a?(Array) ? data['extraRecords'] : []).each do |record_data|
86
100
  attributes[:flexi_records].push FlexiRecord.from_api(record_data)
87
101
  end
88
- attributes[:flexi_records].freeze
89
102
 
90
103
  new(attributes)
91
104
  end
@@ -93,7 +106,7 @@ module Osm
93
106
  # Check if this section is one of the youth sections
94
107
  # @return [Boolean]
95
108
  def youth_section?
96
- [:beavers, :cubs, :scouts, :explorers].include?(@type)
109
+ [:beavers, :cubs, :scouts, :explorers].include?(type)
97
110
  end
98
111
 
99
112
  # Custom section type checkers
@@ -117,7 +130,7 @@ module Osm
117
130
  # @return (Boolean)
118
131
  [:beavers, :cubs, :scouts, :explorers, :adults, :waiting].each do |attribute|
119
132
  define_method "#{attribute}?" do
120
- @type == attribute
133
+ type == attribute
121
134
  end
122
135
  end
123
136
 
@@ -136,29 +149,49 @@ module Osm
136
149
  return false
137
150
  end
138
151
  end
152
+
153
+ def inspect
154
+ attribute_descriptions = attributes.merge('role' => role.inspect_without_section(self))
155
+ return_inspect(attribute_descriptions)
156
+ end
139
157
 
158
+ def inspect_without_role(exclude_role)
159
+ attribute_descriptions = (role == exclude_role) ? attributes.merge('role' => 'SET') : attributes
160
+ return_inspect(attribute_descriptions)
161
+ end
140
162
 
141
163
 
142
164
  private
165
+ def return_inspect(attribute_descriptions)
166
+ attribute_descriptions.sort.map { |key, value| "#{key}: #{key.eql?('role') ? value : value.inspect}" }.join(", ")
167
+ separator = " " unless attribute_descriptions.empty?
168
+ "#<#{self.class.name}#{separator}#{attribute_descriptions}>"
169
+ end
170
+
143
171
  class FlexiRecord
172
+ include ::ActiveAttr::MassAssignmentSecurity
173
+ include ::ActiveAttr::Model
144
174
 
145
- attr_reader :id, :name
146
- # @!attribute [r] id
175
+ # @!attribute [rw] id
147
176
  # @return [Fixnum] the aid of the flexi-record
148
- # @!attribute [r] name
177
+ # @!attribute [rw] name
149
178
  # @return [String] the name given to the flexi-record
150
-
151
- # Initialize a new ApiAccess
152
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
153
- def initialize(attributes={})
154
- raise ArgumentError, ':id must be a Fixnum > 0' unless (attributes[:id].is_a?(Fixnum) && attributes[:id] > 0)
155
- raise ArgumentError, ':name must be a String' unless attributes[:name].is_a?(String)
156
-
157
- attributes.each { |k,v| instance_variable_set("@#{k}", v) }
158
- end
159
-
160
-
161
- # Initialize a new ApiAccess from api data
179
+
180
+ attribute :id, :type => Integer
181
+ attribute :name, :type => String
182
+
183
+ attr_accessible :id, :name
184
+
185
+ validates_numericality_of :id, :only_integer=>true, :greater_than=>0
186
+ validates_presence_of :name
187
+
188
+
189
+ # @!method initialize
190
+ # Initialize a new FlexiRecord
191
+ # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
192
+
193
+
194
+ # Initialize a new FlexiRecord from api data
162
195
  # @param [Hash] data the hash of data provided by the API
163
196
  def self.from_api(data)
164
197
  # Expect item to be: {:name=>String, :extraid=>Fixnum}
@@ -170,8 +203,8 @@ module Osm
170
203
  :name => data['name'],
171
204
  })
172
205
  end
173
- end # FlexiRecord
206
+ end # Class Section::FlexiRecord
174
207
 
175
- end # Section
208
+ end # Class Section
176
209
 
177
210
  end # Module
@@ -1,30 +1,38 @@
1
1
  module Osm
2
2
 
3
3
  class Term
4
+ include ::ActiveAttr::MassAssignmentSecurity
5
+ include ::ActiveAttr::Model
4
6
 
5
- attr_reader :id, :section_id, :name, :start, :end
6
- # @!attribute [r] id
7
+ # @!attribute [rw] id
7
8
  # @return [Fixnum] the id for the term
8
- # @!attribute [r] section_id
9
+ # @!attribute [rw] section_id
9
10
  # @return [Fixnum] the section the term belongs to
10
- # @!attribute [r] name
11
+ # @!attribute [rw] name
11
12
  # @return [Fixnum] the name of the term
12
- # @!attribute [r] start
13
+ # @!attribute [rw] start
13
14
  # @return [Date] when the term starts
14
- # @!attribute [r] end
15
- # @return [Date] when the term ends
16
-
17
- # Initialize a new Term
18
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
19
- def initialize(attributes={})
20
- raise ArgumentError, ':id must be nil or a Fixnum > 0' unless attributes[:id].nil? || (attributes[:id].is_a?(Fixnum) && attributes[:id] > 0)
21
- raise ArgumentError, ':section_id must be nil or a Fixnum > 0' unless attributes[:section_id].nil? || (attributes[:section_id].is_a?(Fixnum) && attributes[:section_id] > 0)
22
- raise ArgumentError, ':name must be nil or a String' unless attributes[:name].nil? || attributes[:name].is_a?(String)
23
- raise ArgumentError, ':start must be nil or a Date' unless attributes[:start].nil? || attributes[:start].is_a?(Date)
24
- raise ArgumentError, ':end must be nil or a Date' unless attributes[:end].nil? || attributes[:end].is_a?(Date)
25
-
26
- attributes.each { |k,v| instance_variable_set("@#{k}", v) }
27
- end
15
+ # @!attribute [rw] finish
16
+ # @return [Date] when the term finishes
17
+
18
+ attribute :id, :type => Integer
19
+ attribute :section_id, :type => Integer
20
+ attribute :name, :type => String
21
+ attribute :start, :type => Date
22
+ attribute :finish, :type => Date
23
+
24
+ attr_accessible :id, :section_id, :name, :start, :finish
25
+
26
+ validates_numericality_of :id, :only_integer=>true, :greater_than=>0
27
+ validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
28
+ validates_presence_of :name
29
+ validates_presence_of :start
30
+ validates_presence_of :finish
31
+
32
+
33
+ # @!method initialize
34
+ # Initialize a new Term
35
+ # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
28
36
 
29
37
 
30
38
  # Initialize a new Term from api data
@@ -35,7 +43,7 @@ module Osm
35
43
  :section_id => Osm::to_i_or_nil(data['sectionid']),
36
44
  :name => data['name'],
37
45
  :start => Osm::parse_date(data['startdate']),
38
- :end => Osm::parse_date(data['enddate']),
46
+ :finish => Osm::parse_date(data['enddate']),
39
47
  )
40
48
  end
41
49
 
@@ -43,39 +51,39 @@ module Osm
43
51
  # @param [Date] date
44
52
  # @return [Boolean] if the term is completly before the passed date
45
53
  def before?(date)
46
- return @end < date.to_date
54
+ return finish < date.to_date
47
55
  end
48
56
 
49
57
  # Determine if the term is completly after the passed date
50
58
  # @param [Date] date
51
59
  # @return [Boolean] if the term is completly after the passed date
52
60
  def after?(date)
53
- return @start > date.to_date
61
+ return start > date.to_date
54
62
  end
55
63
 
56
64
  # Determine if the term is in the future
57
65
  # @return [Boolean] if the term starts after today
58
66
  def future?
59
- return @start > Date.today
67
+ return start > Date.today
60
68
  end
61
69
 
62
70
  # Determine if the term is in the past
63
71
  # @return [Boolean] if the term finished before today
64
72
  def past?
65
- return @end < Date.today
73
+ return finish < Date.today
66
74
  end
67
75
 
68
76
  # Determine if the term is current
69
77
  # @return [Boolean] if the term started before today and finishes after today
70
78
  def current?
71
- return (@start <= Date.today) && (@end >= Date.today)
79
+ return (start <= Date.today) && (finish >= Date.today)
72
80
  end
73
81
 
74
82
  # Determine if the provided date is within the term
75
83
  # @param [Date] date the date to test
76
84
  # @return [Boolean] if the term started before the date and finishes after the date
77
85
  def contains_date?(date)
78
- return (@start <= date) && (@end >= date)
86
+ return (start <= date) && (finish >= date)
79
87
  end
80
88
 
81
89
  def <=>(another_term)
@@ -100,6 +108,6 @@ module Osm
100
108
  end
101
109
  end
102
110
 
103
- end
111
+ end # Class Term
104
112
 
105
- end
113
+ end # Module
@@ -20,6 +20,8 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.add_runtime_dependency 'activesupport', '>= 3.2' # Used to parse JSON from OSM
22
22
  s.add_runtime_dependency 'httparty' # Used to make web requests to the API
23
+ s.add_runtime_dependency 'active_attr'
24
+ s.add_runtime_dependency 'activemodel'
23
25
 
24
26
  s.add_development_dependency 'rake'
25
27
  s.add_development_dependency 'rspec'
@@ -86,6 +86,8 @@ describe "Activity" do
86
86
  activity.badges[0].badge.should == 'badge'
87
87
  activity.badges[0].requirement.should == 'col_name'
88
88
  activity.badges[0].label.should == 'This is a label'
89
+
90
+ activity.valid?.should be_true
89
91
  end
90
92
 
91
93
  end
@@ -8,13 +8,14 @@ describe "API Access" do
8
8
  data = {
9
9
  'apiid' => '1',
10
10
  'name' => 'Name',
11
- 'permissions' => {'permission' => '100'},
11
+ 'permissions' => {'permission' => '10'},
12
12
  }
13
13
  api_access = Osm::ApiAccess.from_api(data)
14
14
 
15
15
  api_access.id.should == 1
16
16
  api_access.name.should == 'Name'
17
- api_access.permissions.should == {:permission => 100}
17
+ api_access.permissions.should == {:permission => 10}
18
+ api_access.valid?.should be_true
18
19
  end
19
20
 
20
21
 
@@ -419,7 +419,7 @@ describe "API" do
419
419
  'token' => @api_config[:api_token],
420
420
  'userid' => 'user',
421
421
  'secret' => 'secret',
422
- 'eveningid' => nil, 'sectionid' => nil, 'meetingdate' => '2000-01-02', 'starttime' => nil,
422
+ 'eveningid' => 1, 'sectionid' => 2, 'meetingdate' => '2000-01-02', 'starttime' => nil,
423
423
  'endtime' => nil, 'title' => 'Unnamed meeting', 'notesforparents' =>'', 'prenotes' => '',
424
424
  'postnotes' => '', 'games' => '', 'leaders' => '', 'activity' => '[]',
425
425
  }
@@ -427,7 +427,7 @@ describe "API" do
427
427
  api.stub(:get_terms) { [] }
428
428
  HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"result":0}'}) }
429
429
 
430
- evening = Osm::Evening.new({:meeting_date => Date.new(2000, 01, 02)})
430
+ evening = Osm::Evening.new(:id=>1, :section_id=>2, :meeting_date=>Date.new(2000, 01, 02))
431
431
  api.update_evening(evening).should be_true
432
432
  end
433
433
 
@@ -438,7 +438,7 @@ describe "API" do
438
438
  'token' => @api_config[:api_token],
439
439
  'userid' => 'user',
440
440
  'secret' => 'secret',
441
- 'eveningid' => nil, 'sectionid' => nil, 'meetingdate' => '2000-01-02', 'starttime' => nil,
441
+ 'eveningid' => 1, 'sectionid' => 2, 'meetingdate' => '2000-01-02', 'starttime' => nil,
442
442
  'endtime' => nil, 'title' => 'Unnamed meeting', 'notesforparents' =>'', 'prenotes' => '',
443
443
  'postnotes' => '', 'games' => '', 'leaders' => '', 'activity' => '[]',
444
444
  }
@@ -446,10 +446,15 @@ describe "API" do
446
446
  api.stub(:get_terms) { [] }
447
447
  HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"result":1}'}) }
448
448
 
449
- evening = Osm::Evening.new({:meeting_date => Date.new(2000, 01, 02)})
449
+ evening = Osm::Evening.new(:id=>1, :section_id=>2, :meeting_date=>Date.new(2000, 01, 02))
450
450
  api.update_evening(evening).should be_false
451
451
  end
452
- end
452
+
453
+ it "Update an evening (invalid evening)" do
454
+ api = Osm::Api.new('user', 'secret')
455
+ evening = Osm::Evening.new
456
+ expect{ api.update_evening(evening) }.to raise_error(Osm::ArgumentIsInvalid)
457
+ end end
453
458
 
454
459
 
455
460
  describe "Options Hash" do
@@ -52,6 +52,7 @@ describe "DueBadge" do
52
52
  db.descriptions.should == {:badge_name=>{:name=>"Badge Name", :section=>:cubs, :type=>:activity, :badge=>"badge_name"}, :cubs_core_participation=>{:name=>"Participation", :section=>:cubs, :type=>:core, :badge=>"participation"}}
53
53
  db.by_member.should == {"John Doe"=>[{:badge=>:badge_name, :extra_information=>""}, {:badge=>:cubs_core_participation, :extra_information=>"Lvl 2"}], "Jane Doe"=>[{:badge=>:cubs_core_participation, :extra_information=>"Lvl 3"}]}
54
54
  db.totals.should == {:badge_name=>{""=>1}, :cubs_core_participation=>{"Lvl 3"=>1, "Lvl 2"=>1}}
55
+ db.valid?.should be_true
55
56
  end
56
57
 
57
58
  end
@@ -6,7 +6,7 @@ describe "Evening" do
6
6
 
7
7
  before :each do
8
8
  @attributes = {
9
- :evening_id => 1,
9
+ :id => 1,
10
10
  :section_id => 2,
11
11
  :title => 'Evening Name',
12
12
  :notes_for_parents => 'Notes for parents',
@@ -15,7 +15,7 @@ describe "Evening" do
15
15
  :post_notes => 'After',
16
16
  :leaders => 'Leaders',
17
17
  :start_time => '19:00',
18
- :end_time => '21:00',
18
+ :finish_time => '21:00',
19
19
  :meeting_date => Date.new(2000, 01, 02),
20
20
  }
21
21
  end
@@ -42,7 +42,7 @@ describe "Evening" do
42
42
  }]
43
43
  e = Osm::Evening.from_api(data, activities)
44
44
 
45
- e.evening_id.should == 1
45
+ e.id.should == 1
46
46
  e.section_id.should == 2
47
47
  e.title.should == 'Evening Name'
48
48
  e.notes_for_parents.should == 'Notes for parents'
@@ -51,30 +51,15 @@ describe "Evening" do
51
51
  e.post_notes.should == 'After'
52
52
  e.leaders.should == 'Leaders'
53
53
  e.start_time.should == '19:00'
54
- e.end_time.should == '21:00'
54
+ e.finish_time.should == '21:00'
55
55
  e.meeting_date.should == Date.new(2000, 1, 2)
56
56
 
57
57
  ea = e.activities[0]
58
58
  ea.activity_id.should == 2
59
59
  ea.title.should == 'Activity Name'
60
60
  ea.notes.should == 'Notes'
61
- end
62
-
63
-
64
- it "Raises exceptions when trying to set invalid times" do
65
- e = Osm::Evening.new(@attributes)
66
-
67
- expect{ e.start_time = 'abcde' }.to raise_error(ArgumentError)
68
- expect{ e.start_time = '24:00' }.to raise_error(ArgumentError)
69
- expect{ e.start_time = '10:61' }.to raise_error(ArgumentError)
70
- e.start_time = '12:34'
71
- e.start_time.should == '12:34'
72
61
 
73
- expect{ e.end_time = 'abcde' }.to raise_error(ArgumentError)
74
- expect{ e.end_time = '24:00' }.to raise_error(ArgumentError)
75
- expect{ e.end_time = '10:61' }.to raise_error(ArgumentError)
76
- e.end_time = '23:45'
77
- e.end_time.should == '23:45'
62
+ e.valid?.should be_true
78
63
  end
79
64
 
80
65