osm 0.0.1.alpha
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.
- data/.gitignore +25 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE.rdoc +39 -0
- data/README.md +24 -0
- data/Rakefile +14 -0
- data/lib/osm.rb +71 -0
- data/lib/osm/activity.rb +45 -0
- data/lib/osm/api.rb +688 -0
- data/lib/osm/api_access.rb +43 -0
- data/lib/osm/due_badges.rb +53 -0
- data/lib/osm/event.rb +22 -0
- data/lib/osm/grouping.rb +17 -0
- data/lib/osm/member.rb +64 -0
- data/lib/osm/programme_activity.rb +18 -0
- data/lib/osm/programme_item.rb +58 -0
- data/lib/osm/role.rb +66 -0
- data/lib/osm/section.rb +63 -0
- data/lib/osm/term.rb +72 -0
- data/osm.gemspec +29 -0
- data/spec/osm/activity_spec.rb +64 -0
- data/spec/osm/api_access_spec.rb +54 -0
- data/spec/osm/api_spec.rb +561 -0
- data/spec/osm/api_strangeness_spec.rb +48 -0
- data/spec/osm/due_badges_spec.rb +57 -0
- data/spec/osm/event_spec.rb +32 -0
- data/spec/osm/grouping_spec.rb +19 -0
- data/spec/osm/member_spec.rb +98 -0
- data/spec/osm/osm_spec.rb +82 -0
- data/spec/osm/programme_activity_spec.rb +21 -0
- data/spec/osm/programme_item_spec.rb +64 -0
- data/spec/osm/role_spec.rb +111 -0
- data/spec/osm/section_spec.rb +199 -0
- data/spec/osm/term_spec.rb +162 -0
- data/spec/spec_helper.rb +58 -0
- data/version.rb +3 -0
- metadata +152 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class ApiAccess
|
4
|
+
|
5
|
+
attr_reader :id, :name, :permissions
|
6
|
+
|
7
|
+
# Initialize a new API Access using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
@id = data['apiid'].to_i
|
11
|
+
@name = data['name']
|
12
|
+
@permissions = data['permissions'] || {}
|
13
|
+
|
14
|
+
# Rubyfy permissions hash
|
15
|
+
@permissions.keys.each do |key|
|
16
|
+
@permissions[key] = @permissions[key].to_i
|
17
|
+
@permissions[(key.to_sym rescue key) || key] = @permissions.delete(key) # Symbolize key
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Determine if this API has read access for the provided permission
|
22
|
+
# @param key - the key for the permission being queried
|
23
|
+
# @returns - true if this API can read the passed permission, false otherwise
|
24
|
+
def can_read?(key)
|
25
|
+
return [20, 10].include?(@permissions[key])
|
26
|
+
end
|
27
|
+
|
28
|
+
# Determine if this API has write access for the provided permission
|
29
|
+
# @param key - the key for the permission being queried
|
30
|
+
# @returns - true if this API can write the passed permission, false otherwise
|
31
|
+
def can_write?(key)
|
32
|
+
return [20].include?(@permissions[key])
|
33
|
+
end
|
34
|
+
|
35
|
+
# Determine if this API is the API being used to make requests
|
36
|
+
# @returns - true if this is the API being used, false otherwise
|
37
|
+
def our_api?
|
38
|
+
return @id == Osm::Api.api_id.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class DueBadges
|
4
|
+
|
5
|
+
attr_reader :descriptions, :by_member, :totals
|
6
|
+
|
7
|
+
# Initialize a new Event using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
data = {} unless data.is_a?(Hash)
|
11
|
+
|
12
|
+
@pending = (data['pending'] || {}).symbolize_keys
|
13
|
+
@descriptions = (data['description'] || {}).symbolize_keys
|
14
|
+
|
15
|
+
@pending.each_key do |key|
|
16
|
+
@pending[key].each do |item|
|
17
|
+
item.symbolize_keys!
|
18
|
+
item[:sid] = item[:sid].to_i
|
19
|
+
item[:completed] = item[:completed].to_i
|
20
|
+
end
|
21
|
+
end
|
22
|
+
@descriptions.each_key do |key|
|
23
|
+
@descriptions[key].symbolize_keys!
|
24
|
+
@descriptions[key][:section] = @descriptions[key][:section].to_sym
|
25
|
+
@descriptions[key][:type] = @descriptions[key][:type].to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
@by_member = {}
|
30
|
+
@totals = {}
|
31
|
+
@pending.each_key do |key|
|
32
|
+
@pending[key].each do |item|
|
33
|
+
name = "#{item[:firstname]} #{item[:lastname]}"
|
34
|
+
by_member[name] = [] if by_member[name].nil?
|
35
|
+
|
36
|
+
badge = {
|
37
|
+
:badge => key,
|
38
|
+
:extra_information => item[:extra]
|
39
|
+
}
|
40
|
+
by_member[name].push badge
|
41
|
+
@totals[key] = {} if @totals[key].nil?
|
42
|
+
@totals[key][item[:extra]] = @totals[key][item[:extra]].to_i + 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def empty?
|
48
|
+
return @by_member.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/osm/event.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class Event
|
4
|
+
|
5
|
+
attr_reader :id, :section_id, :name, :start, :end, :cost, :location, :notes
|
6
|
+
|
7
|
+
# Initialize a new Event using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
@id = Osm::to_i_or_nil(data['eventid'])
|
11
|
+
@section_id = Osm::to_i_or_nil(data['sectionid'])
|
12
|
+
@name = data['name']
|
13
|
+
@start = Osm::make_datetime(data['startdate'], data['starttime'])
|
14
|
+
@end = Osm::make_datetime(data['enddate'], data['endtime'])
|
15
|
+
@cost = data['cost']
|
16
|
+
@location = data['location']
|
17
|
+
@notes = data['notes']
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/osm/grouping.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class Grouping
|
4
|
+
|
5
|
+
attr_reader :id, :name, :active
|
6
|
+
|
7
|
+
# Initialize a new Grouping using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
@id = Osm::to_i_or_nil(data['patrolid'])
|
11
|
+
@name = data['name']
|
12
|
+
@active = (data['active'] == 1)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/osm/member.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class Member
|
4
|
+
|
5
|
+
attr_reader :id, :section_id, :type, :first_name, :last_name, :email1, :email2, :email3, :email4, :phone1, :phone2, :phone3, :phone4, :address, :address2, :date_of_birth, :started, :joined_in_years, :parents, :notes, :medical, :religion, :school, :ethnicity, :subs, :grouping_id, :grouping_leader, :joined, :age, :joined_years, :patrol
|
6
|
+
|
7
|
+
# Initialize a new Member using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
@id = Osm::to_i_or_nil(data['scoutid'])
|
11
|
+
@section_id = Osm::to_i_or_nil(data['sectionid'])
|
12
|
+
@type = data['type']
|
13
|
+
@first_name = data['firstname']
|
14
|
+
@last_name = data['lastname']
|
15
|
+
@email1 = data['email1']
|
16
|
+
@email2 = data['email2']
|
17
|
+
@email3 = data['email3']
|
18
|
+
@email4 = data['email4']
|
19
|
+
@phone1 = data['phone1']
|
20
|
+
@phone2 = data['phone2']
|
21
|
+
@phone3 = data['phone3']
|
22
|
+
@phone4 = data['phone4']
|
23
|
+
@address = data['address']
|
24
|
+
@address2 = data['address2']
|
25
|
+
@date_of_birth = Osm::parse_date(data['dob'])
|
26
|
+
@started = Osm::parse_date(data['started'])
|
27
|
+
@joined_in_years = data['joining_in_yrs'].to_i
|
28
|
+
@parents = data['parents']
|
29
|
+
@notes = data['notes']
|
30
|
+
@medical = data['medical']
|
31
|
+
@religion = data['religion']
|
32
|
+
@school = data['school']
|
33
|
+
@ethnicity = data['ethnicity']
|
34
|
+
@subs = data['subs']
|
35
|
+
@grouping_id = Osm::to_i_or_nil(data['patrolid'])
|
36
|
+
@grouping_leader = data['patrolleader'] # 0 - No, 1 = seconder, 2 = sixer
|
37
|
+
@joined = Osm::parse_date(data['joined'])
|
38
|
+
@age = data['age'] # 'yy / mm'
|
39
|
+
@joined_years = data['yrs'].to_i
|
40
|
+
@patrol = data['patrol']
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get the years element of this scout's age
|
44
|
+
# @returns the number of years this scout has been alive
|
45
|
+
def age_years
|
46
|
+
return @age[0..1].to_i
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get the months element of this scout's age
|
50
|
+
# @returns the number of months since this scout's last birthday
|
51
|
+
def age_months
|
52
|
+
return @age[-2..-1].to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the full name
|
56
|
+
# @param seperator (optional) what to split the scout's first name and last name with, defaults to a space
|
57
|
+
# @returns this scout's full name seperate by the optional seperator
|
58
|
+
def name(seperator=' ')
|
59
|
+
return "#{@first_name}#{seperator.to_s}#{@last_name}"
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class ProgrammeActivity
|
4
|
+
|
5
|
+
attr_reader :evening_id, :activity_id, :title, :notes
|
6
|
+
|
7
|
+
# Initialize a new EveningActivity using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
@evening_id = Osm::to_i_or_nil(data['eveningid'])
|
11
|
+
@activity_id = Osm::to_i_or_nil(data['activityid'])
|
12
|
+
@title = data['title']
|
13
|
+
@notes = data['notes']
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class ProgrammeItem
|
4
|
+
|
5
|
+
attr_accessor :evening_id, :section_id, :title, :notes_for_parents, :games, :pre_notes, :post_notes, :leaders, :meeting_date, :activities, :google_calendar
|
6
|
+
attr_reader :start_time, :end_time
|
7
|
+
|
8
|
+
# Initialize a new ProgrammeItem using the hash returned by the API call
|
9
|
+
# @param data the hash of data for the object returned by the API
|
10
|
+
# @param activities an array of hashes to generate the list of ProgrammeActivity objects
|
11
|
+
def initialize(data, activities)
|
12
|
+
@evening_id = Osm::to_i_or_nil(data['eveningid'])
|
13
|
+
@section_id = Osm::to_i_or_nil(data['sectionid'])
|
14
|
+
@title = data['title'] || 'Unnamed meeting'
|
15
|
+
@notes_for_parents = data['notesforparents'] || ''
|
16
|
+
@games = data['games'] || ''
|
17
|
+
@pre_notes = data['prenotes'] || ''
|
18
|
+
@post_notes = data['postnotes'] || ''
|
19
|
+
@leaders = data['leaders'] || ''
|
20
|
+
@start_time = data['starttime'].nil? ? nil : data['starttime'][0..4]
|
21
|
+
@end_time = data['endtime'].nil? ? nil : data['endtime'][0..4]
|
22
|
+
@meeting_date = Osm::parse_date(data['meetingdate'])
|
23
|
+
@google_calendar = data['googlecalendar']
|
24
|
+
|
25
|
+
@activities = Array.new
|
26
|
+
unless activities.nil?
|
27
|
+
activities.each do |item|
|
28
|
+
@activities.push Osm::ProgrammeActivity.new(item)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Custom setters for times
|
34
|
+
[:start, :end].each do |attribute|
|
35
|
+
define_method "#{attribute}_time=" do |value|
|
36
|
+
unless value.nil?
|
37
|
+
value = value.strftime('%H:%M') unless value.is_a?(String)
|
38
|
+
raise ArgumentError, 'invalid time' unless /\A(?:[0-1][0-9]|2[0-3]):[0-5][0-9]\Z/.match(value)
|
39
|
+
end
|
40
|
+
instance_variable_set("@#{attribute}_time", value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def activities_for_saving
|
45
|
+
to_save = Array.new
|
46
|
+
@activities.each do |activity|
|
47
|
+
this_activity = {
|
48
|
+
'activityid' => activity.activity_id,
|
49
|
+
'notes' => activity.notes,
|
50
|
+
}
|
51
|
+
to_save.push this_activity
|
52
|
+
end
|
53
|
+
return ActiveSupport::JSON.encode(to_save)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/osm/role.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class Role
|
4
|
+
|
5
|
+
attr_reader :section, :group_name, :group_id, :group_normalized, :default, :permissions
|
6
|
+
|
7
|
+
# Initialize a new UserRole using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
@section = Osm::Section.new(data['sectionid'], data['sectionname'], ActiveSupport::JSON.decode(data['sectionConfig']), self)
|
11
|
+
@group_name = data['groupname']
|
12
|
+
@group_id = Osm::to_i_or_nil(data['groupid'])
|
13
|
+
@group_normalized = Osm::to_i_or_nil(data['groupNormalised'])
|
14
|
+
@default = data['isDefault'].eql?('1') ? true : false
|
15
|
+
@permissions = (data['permissions'] || {}).symbolize_keys
|
16
|
+
|
17
|
+
# Convert permission values to a number
|
18
|
+
@permissions.each_key do |key|
|
19
|
+
@permissions[key] = @permissions[key].to_i
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Determine if this role has read access for the provided permission
|
24
|
+
# @param key - the key for the permission being queried
|
25
|
+
# @returns - true if this role can read the passed permission, false otherwise
|
26
|
+
def can_read?(key)
|
27
|
+
return [10, 20, 100].include?(@permissions[key])
|
28
|
+
end
|
29
|
+
|
30
|
+
# Determine if this role has write access for the provided permission
|
31
|
+
# @param key - the key for the permission being queried
|
32
|
+
# @returns - true if this role can write the passed permission, false otherwise
|
33
|
+
def can_write?(key)
|
34
|
+
return [20, 100].include?(@permissions[key])
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get section's full name in a consistent format
|
38
|
+
# @returns a string e.g. "Scouts (1st Somewhere)"
|
39
|
+
def long_name
|
40
|
+
@group_name.blank? ? @section.name : "#{@section.name} (#{@group_name})"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get section's full name in a consistent format
|
44
|
+
# @returns a string e.g. "1st Somewhere Beavers"
|
45
|
+
def full_name
|
46
|
+
@group_name.blank? ? @section.name : "#{@group_name} #{@section.name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def <=>(another_role)
|
50
|
+
compare_group_name = self.group_name <=> another_role.group_name
|
51
|
+
return compare_group_name unless compare_group_name == 0
|
52
|
+
|
53
|
+
return 0 if self.section.type == another_role.section.type
|
54
|
+
[:beavers, :cubs, :scouts, :explorers, :waiting, :adults].each do |type|
|
55
|
+
return -1 if self.section.type == type
|
56
|
+
return 1 if another_role.section.type == type
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def ==(another_role)
|
61
|
+
self.section == another_role.try(:section)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/osm/section.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class Section
|
4
|
+
|
5
|
+
attr_reader :id, :name, :subscription_level, :subscription_expires, :type, :num_scouts, :has_badge_records, :has_programme, :wizard, :column_names, :fields, :intouch_fields, :mobile_fields, :extra_records, :role
|
6
|
+
|
7
|
+
# Initialize a new SectionConfig using the hash returned by the API call
|
8
|
+
# @param id the section ID used by the API to refer to this section
|
9
|
+
# @param data the hash of data for the object returned by the API
|
10
|
+
def initialize(id, name, data, role)
|
11
|
+
subscription_levels = [:bronze, :silver, :gold]
|
12
|
+
subscription_level = data['subscription_level'].to_i - 1
|
13
|
+
|
14
|
+
@id = Osm::to_i_or_nil(id)
|
15
|
+
@name = name
|
16
|
+
@subscription_level = (subscription_levels[subscription_level] unless subscription_level < 0) || :unknown
|
17
|
+
@subscription_expires = data['subscription_expires'] ? Date.parse(data['subscription_expires'], 'yyyy-mm-dd') : nil
|
18
|
+
@type = !data['sectionType'].nil? ? data['sectionType'].to_sym : :unknown
|
19
|
+
@num_scouts = data['numscouts']
|
20
|
+
@has_badge_records = data['hasUsedBadgeRecords'].eql?('1') ? true : false
|
21
|
+
@has_programme = data['hasProgramme']
|
22
|
+
@wizard = (data['wizard'] || '').downcase.eql?('true') ? true : false
|
23
|
+
@column_names = (data['columnNames'] || {}).symbolize_keys
|
24
|
+
@fields = (data['fields'] || {}).symbolize_keys
|
25
|
+
@intouch_fields = (data['intouch'] || {}).symbolize_keys
|
26
|
+
@mobile_fields = (data['mobFields'] || {}).symbolize_keys
|
27
|
+
@extra_records = data['extraRecords'] || []
|
28
|
+
@role = role
|
29
|
+
|
30
|
+
# Symbolise the keys in each hash of the extra_records array
|
31
|
+
@extra_records.each do |item|
|
32
|
+
# Expect item to be: {:name=>String, :extraid=>FixNum}
|
33
|
+
# Sometimes get item as: [String, {"name"=>String, "extraid"=>FixNum}]
|
34
|
+
if item.is_a?(Array)
|
35
|
+
item = item[1].symbolize_keys
|
36
|
+
else
|
37
|
+
item.symbolize_keys!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def youth_section?
|
43
|
+
[:beavers, :cubs, :scouts, :explorers].include?(@type)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Custom section type checkers
|
47
|
+
[:beavers, :cubs, :scouts, :explorers, :adults, :waiting].each do |attribute|
|
48
|
+
define_method "#{attribute}?" do
|
49
|
+
@type == attribute
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def <=>(another_section)
|
54
|
+
self.role <=> another_section.try(:role)
|
55
|
+
end
|
56
|
+
|
57
|
+
def ==(another_section)
|
58
|
+
self.id == another_section.try(:id)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/lib/osm/term.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class Term
|
4
|
+
|
5
|
+
attr_reader :id, :section_id, :name, :start, :end
|
6
|
+
|
7
|
+
# Initialize a new Term using the hash returned by the API call
|
8
|
+
# @param data the hash of data for the object returned by the API
|
9
|
+
def initialize(data)
|
10
|
+
@id = Osm::to_i_or_nil(data['termid'])
|
11
|
+
@section_id = Osm::to_i_or_nil(data['sectionid'])
|
12
|
+
@name = data['name']
|
13
|
+
@start = Osm::parse_date(data['startdate'])
|
14
|
+
@end = Osm::parse_date(data['enddate'])
|
15
|
+
end
|
16
|
+
|
17
|
+
# Determine if the term is completly before the passed date
|
18
|
+
# @param date
|
19
|
+
# @returns true if the term is completly before the passed date
|
20
|
+
def before?(date)
|
21
|
+
return @end < date.to_date
|
22
|
+
end
|
23
|
+
|
24
|
+
# Determine if the term is completly after the passed date
|
25
|
+
# @param date
|
26
|
+
# @returns true if the term is completly after the passed date
|
27
|
+
def after?(date)
|
28
|
+
return @start > date.to_date
|
29
|
+
end
|
30
|
+
|
31
|
+
# Determine if the term is in the future
|
32
|
+
# @returns true if the term starts after today
|
33
|
+
def future?
|
34
|
+
return @start > Date.today
|
35
|
+
end
|
36
|
+
|
37
|
+
# Determine if the term is in the past
|
38
|
+
# @returns true if the term finished before today
|
39
|
+
def past?
|
40
|
+
return @end < Date.today
|
41
|
+
end
|
42
|
+
|
43
|
+
# Determine if the term is current
|
44
|
+
# @returns true if the term started before today and finishes after today
|
45
|
+
def current?
|
46
|
+
return (@start <= Date.today) && (@end >= Date.today)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Determine if the provided date is within the term
|
50
|
+
# @param date the date to test
|
51
|
+
# @returns true if the term started before the date and finishes after the date
|
52
|
+
def contains_date?(date)
|
53
|
+
return (@start <= date) && (@end >= date)
|
54
|
+
end
|
55
|
+
|
56
|
+
def <=>(another_term)
|
57
|
+
compare = self.section_id <=> another_term.try(:section_id)
|
58
|
+
return compare unless compare == 0
|
59
|
+
|
60
|
+
compare = self.start <=> another_term.try(:start)
|
61
|
+
return compare unless compare == 0
|
62
|
+
|
63
|
+
self.id <=> another_term.try(:id)
|
64
|
+
end
|
65
|
+
|
66
|
+
def ==(another_term)
|
67
|
+
self.id == another_term.try(:id)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|