specify_cli 0.0.5

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.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +17 -0
  5. data/Gemfile.lock +117 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.rdoc +43 -0
  8. data/Rakefile +15 -0
  9. data/bin/specify_cli +248 -0
  10. data/lib/specify.rb +45 -0
  11. data/lib/specify/branch_parser.rb +85 -0
  12. data/lib/specify/cli.rb +11 -0
  13. data/lib/specify/cli/database_setup.rb +46 -0
  14. data/lib/specify/cli/stubs.rb +63 -0
  15. data/lib/specify/cli/viewset.rb +21 -0
  16. data/lib/specify/configuration.rb +12 -0
  17. data/lib/specify/configuration/config.rb +120 -0
  18. data/lib/specify/configuration/db_config.rb +162 -0
  19. data/lib/specify/configuration/host_config.rb +37 -0
  20. data/lib/specify/database.rb +140 -0
  21. data/lib/specify/models.rb +43 -0
  22. data/lib/specify/models/accession.rb +33 -0
  23. data/lib/specify/models/agent.rb +138 -0
  24. data/lib/specify/models/app_resource_data.rb +32 -0
  25. data/lib/specify/models/app_resource_dir.rb +43 -0
  26. data/lib/specify/models/auto_numbering_scheme.rb +94 -0
  27. data/lib/specify/models/collecting_event.rb +38 -0
  28. data/lib/specify/models/collection.rb +67 -0
  29. data/lib/specify/models/collection_object.rb +127 -0
  30. data/lib/specify/models/createable.rb +21 -0
  31. data/lib/specify/models/determination.rb +63 -0
  32. data/lib/specify/models/discipline.rb +61 -0
  33. data/lib/specify/models/division.rb +26 -0
  34. data/lib/specify/models/geography.rb +5 -0
  35. data/lib/specify/models/geography/administrative_division.rb +32 -0
  36. data/lib/specify/models/geography/geographic_name.rb +66 -0
  37. data/lib/specify/models/geography/geography.rb +23 -0
  38. data/lib/specify/models/institution.rb +13 -0
  39. data/lib/specify/models/locality.rb +50 -0
  40. data/lib/specify/models/preparation.rb +53 -0
  41. data/lib/specify/models/preparation_type.rb +30 -0
  42. data/lib/specify/models/record_set.rb +55 -0
  43. data/lib/specify/models/record_set_item.rb +29 -0
  44. data/lib/specify/models/taxonomy.rb +6 -0
  45. data/lib/specify/models/taxonomy/common_name.rb +14 -0
  46. data/lib/specify/models/taxonomy/rank.rb +31 -0
  47. data/lib/specify/models/taxonomy/taxon.rb +54 -0
  48. data/lib/specify/models/taxonomy/taxonomy.rb +21 -0
  49. data/lib/specify/models/tree_queryable.rb +55 -0
  50. data/lib/specify/models/updateable.rb +20 -0
  51. data/lib/specify/models/user.rb +104 -0
  52. data/lib/specify/models/view_set_object.rb +32 -0
  53. data/lib/specify/number_format.rb +60 -0
  54. data/lib/specify/services.rb +18 -0
  55. data/lib/specify/services/service.rb +51 -0
  56. data/lib/specify/services/stub_generator.rb +291 -0
  57. data/lib/specify/services/view_loader.rb +177 -0
  58. data/lib/specify/session.rb +77 -0
  59. data/lib/specify/user_type.rb +61 -0
  60. data/lib/specify/version.rb +19 -0
  61. data/man/specify_cli-database.1 +60 -0
  62. data/man/specify_cli-database.1.html +137 -0
  63. data/man/specify_cli-database.1.ronn +53 -0
  64. data/man/specify_cli-repository.1 +55 -0
  65. data/man/specify_cli-repository.1.html +128 -0
  66. data/man/specify_cli-repository.1.ronn +42 -0
  67. data/man/specify_cli-stubs.1 +177 -0
  68. data/man/specify_cli-stubs.1.html +239 -0
  69. data/man/specify_cli-stubs.1.ronn +147 -0
  70. data/man/specify_cli-viewset.1 +92 -0
  71. data/man/specify_cli-viewset.1.html +154 -0
  72. data/man/specify_cli-viewset.1.ronn +72 -0
  73. data/man/specify_cli.1 +213 -0
  74. data/man/specify_cli.1.html +252 -0
  75. data/man/specify_cli.1.ronn +157 -0
  76. data/spec/branch_parser_spec.rb +94 -0
  77. data/spec/cli/stubs_spec.rb +44 -0
  78. data/spec/configuration/config_spec.rb +269 -0
  79. data/spec/configuration/db_config_spec.rb +299 -0
  80. data/spec/configuration/host_config_spec.rb +64 -0
  81. data/spec/database_spec.rb +83 -0
  82. data/spec/examples.txt +217 -0
  83. data/spec/helpers.rb +15 -0
  84. data/spec/models/app_resource_data_spec.rb +38 -0
  85. data/spec/models/app_resource_dir_spec.rb +8 -0
  86. data/spec/models/auto_numbering_scheme_spec.rb +78 -0
  87. data/spec/models/collection_object_spec.rb +92 -0
  88. data/spec/models/collection_spec.rb +32 -0
  89. data/spec/models/discipline_spec.rb +31 -0
  90. data/spec/models/record_set_spec.rb +18 -0
  91. data/spec/models/user_spec.rb +182 -0
  92. data/spec/models/view_set_object_spec.rb +70 -0
  93. data/spec/number_format_spec.rb +43 -0
  94. data/spec/services/stub_generator_spec.rb +635 -0
  95. data/spec/services/view_loader_spec.rb +436 -0
  96. data/spec/session_spec.rb +105 -0
  97. data/spec/spec_helper.rb +116 -0
  98. data/spec/support/db.yml +12 -0
  99. data/spec/support/stub.yaml +17 -0
  100. data/spec/support/stub_locality.yaml +19 -0
  101. data/spec/support/viewsets/paleo.views.xml +30 -0
  102. data/spec/support/viewsets/paleo.xml +30 -0
  103. data/spec/user_type_spec.rb +79 -0
  104. data/specify_cli.gemspec +27 -0
  105. data/specify_cli.rdoc +1 -0
  106. metadata +246 -0
data/spec/helpers.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'English'
4
+
5
+ # RSpec helpers
6
+ module Helpers
7
+ def set_branch
8
+ branch = `git branch --list #{TEST_BRANCH}`.chomp
9
+ `git branch #{TEST_BRANCH}` if branch.empty?
10
+ system("git checkout #{TEST_BRANCH}")
11
+ e = "Error checking out #{TEST_BRANCH}
12
+ there are probably uncommited changes on #{@origin}"
13
+ raise e unless $CHILD_STATUS == 0
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe AppResourceData do
6
+ let :file do
7
+ Pathname.new(Dir.pwd).join('spec', 'support',
8
+ 'viewsets', 'paleo.views.xml')
9
+ end
10
+
11
+ let :app_resource_data do
12
+ Collection.first(CollectionName: 'Test Collection')
13
+ .view_set.app_resource_data
14
+ end
15
+
16
+ context 'when uploading a file' do
17
+ it 'increments the version number' do
18
+ v = app_resource_data.Version
19
+ expect { app_resource_data.import(file) }
20
+ .to change { app_resource_data.Version }
21
+ .from(v).to(v + 1)
22
+ end
23
+
24
+ it 'updates the modification timestamp' do
25
+ expect { app_resource_data.import(file) }
26
+ .to change(app_resource_data, :TimestampModified)
27
+ end
28
+
29
+ it 'uploads the files content as a Sequel Blob' do
30
+ app_resource_data.data = nil
31
+ expect { app_resource_data.import(file) }
32
+ .to change { app_resource_data.data }
33
+ .from(nil).to(Sequel.blob(File.read(file)))
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe AppResourceDir do
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe AutoNumberingScheme do
6
+ # FIXME: move to shared context
7
+ before :all do
8
+ cataloger = Agent.first(FirstName: 'John', LastName: 'Specman')
9
+ collection_a = Collection.first Code: 'SIP'
10
+ collection_b = Collection.first Code: 'NECE'
11
+
12
+ collection_a.add_collection_object(cataloger: cataloger,
13
+ CatalogNumber: '000000011')
14
+ collection_a.add_collection_object(cataloger: cataloger,
15
+ CatalogNumber: '000000012')
16
+ collection_b.add_collection_object(cataloger: cataloger,
17
+ CatalogNumber: '000000013')
18
+ end
19
+
20
+ let :auto_numbering_scheme do
21
+ Collection.first(CollectionName: 'Test Collection')
22
+ .auto_numbering_scheme
23
+ end
24
+
25
+ describe '#catalog_number?' do
26
+ context 'when the scheme is a catalog number' do
27
+ subject { auto_numbering_scheme.catalog_number? }
28
+
29
+ it { is_expected.to be true }
30
+ end
31
+ end
32
+
33
+ describe '#increment' do
34
+ subject { auto_numbering_scheme.increment }
35
+
36
+ it { is_expected.to eq '000000014' }
37
+ end
38
+
39
+ describe '#max' do
40
+ subject { auto_numbering_scheme.max }
41
+
42
+ it { is_expected.to eq '000000013' }
43
+ end
44
+
45
+ describe '#number_format' do
46
+ context 'when the scheme is a numeric catalog number format' do
47
+ subject { auto_numbering_scheme.number_format }
48
+
49
+ it do
50
+ is_expected.to have_attributes incrementer_length: 9
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#scheme_model' do
56
+ context 'when the scheme is defined for collection objects' do
57
+ subject { auto_numbering_scheme.scheme_model }
58
+
59
+ it { is_expected.to be CollectionObject }
60
+ end
61
+ end
62
+
63
+ describe '#scheme_type' do
64
+ context 'when the scheme is a catalog number' do
65
+ subject { auto_numbering_scheme.scheme_type }
66
+
67
+ it { is_expected.to be :catalog_number }
68
+ end
69
+ end
70
+
71
+ # FIXME: move to shared context
72
+ after :all do
73
+ CollectionObject.dataset.delete
74
+ CollectingEvent.dataset.delete
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe CollectionObject do
6
+ # FIXME: move to shared context
7
+ before :all do
8
+ cataloger = Agent.first(FirstName: 'John', LastName: 'Specman')
9
+ collection_a = Collection.first Code: 'SIP'
10
+ collection_b = Collection.first Code: 'NECE'
11
+
12
+ collection_a.add_collection_object(cataloger: cataloger,
13
+ CatalogNumber: '000000011')
14
+ collection_a.add_collection_object(cataloger: cataloger,
15
+ CatalogNumber: '000000012')
16
+ collection_b.add_collection_object(cataloger: cataloger,
17
+ CatalogNumber: '000000013')
18
+ end
19
+
20
+ let :collection do
21
+ Collection.first CollectionName: 'Test Collection'
22
+ end
23
+
24
+ context 'when adding to collection' do
25
+ let :cataloger do
26
+ Agent.first(FirstName: 'John', LastName: 'Specman')
27
+ end
28
+
29
+ context 'when passing the catalog number' do
30
+ subject do
31
+ collection.add_collection_object(cataloger: cataloger,
32
+ CatalogNumber: '000000009')
33
+ end
34
+
35
+ it do
36
+ is_expected.to have_attributes Version: 0,
37
+ TimestampCreated: an_instance_of(Time),
38
+ collection_member: collection,
39
+ CatalogedDate: an_instance_of(Date),
40
+ CatalogedDatePrecision: 1,
41
+ GUID: an_instance_of(String),
42
+ CatalogNumber: '000000009'
43
+ end
44
+ end
45
+
46
+ context 'when passing no catalog number' do
47
+ subject do
48
+ collection.add_collection_object(cataloger: cataloger)
49
+ end
50
+
51
+ it do
52
+ is_expected.to have_attributes Version: 0,
53
+ TimestampCreated: an_instance_of(Time),
54
+ collection_member: collection,
55
+ CatalogedDate: an_instance_of(Date),
56
+ CatalogedDatePrecision: 1,
57
+ GUID: an_instance_of(String),
58
+ CatalogNumber: '000000014'
59
+ end
60
+ end
61
+
62
+ context 'when collecting event is emebedded' do
63
+ subject do
64
+ collection.add_collection_object(cataloger: cataloger)
65
+ end
66
+
67
+ it do
68
+ ce = an_instance_of(CollectingEvent)
69
+ is_expected.to have_attributes collecting_event: ce
70
+ end
71
+ end
72
+
73
+ context 'when collecting event is not embedded' do
74
+ subject do
75
+ Collection.first(Code: 'NECE')
76
+ .add_collection_object(CatalogNumber: '2')
77
+ end
78
+
79
+ it do
80
+ is_expected.to have_attributes collecting_event: nil
81
+ end
82
+ end
83
+ end
84
+
85
+ # FIXME: move to shared context
86
+ after :all do
87
+ CollectionObject.dataset.delete
88
+ CollectingEvent.dataset.delete
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe Collection do
6
+ let :collection do
7
+ described_class.first CollectionName: 'Test Collection'
8
+ end
9
+
10
+ describe '#view_set_dir' do
11
+ subject { collection.view_set_dir }
12
+
13
+ it do
14
+ is_expected
15
+ .to have_attributes DisciplineType: 'Invertebrate Paleontology',
16
+ IsPersonal: false,
17
+ UserType: nil,
18
+ collection: collection,
19
+ discipline: collection.discipline
20
+ end
21
+ end
22
+
23
+ describe '#view_set' do
24
+ subject { collection.view_set }
25
+
26
+ it do
27
+ is_expected.to have_attributes Name: 'paleo.views'
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe Discipline do
6
+ let :discipline do
7
+ described_class.first Name: 'Test Discipline'
8
+ end
9
+
10
+ describe '#view_set_dir' do
11
+ subject { discipline.view_set_dir }
12
+
13
+ it do
14
+ is_expected
15
+ .to have_attributes DisciplineType: 'Invertebrate Paleontology',
16
+ IsPersonal: false,
17
+ UserType: nil,
18
+ collection: nil
19
+ end
20
+ end
21
+
22
+ describe '#view_set' do
23
+ subject { discipline.view_set }
24
+
25
+ it 'returns the ViewSetObject for the given collection' do
26
+ is_expected.to have_attributes Name: 'Paleo Views'
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe RecordSet do
6
+ subject do
7
+ described_class.create Name: 'Test Record Set',
8
+ user: user,
9
+ collection: collection
10
+ end
11
+
12
+ let(:collection) { Collection.first Code: 'SIP' }
13
+ let(:user) { User.first Name: 'specuser' }
14
+
15
+ it { p subject.highest_order_number }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specify
4
+ module Model
5
+ RSpec.describe User do
6
+ let(:collection) { Collection.first CollectionName: 'Test Collection' }
7
+ let(:user) { described_class.first Name: 'specuser' }
8
+
9
+ describe '#collection_valid?' do
10
+ before { user.log_out }
11
+
12
+ context 'when logged in to the collection passed as argument' do
13
+ subject { user.collection_valid? collection }
14
+
15
+ before { user.log_in collection }
16
+
17
+ it { is_expected.to be_truthy }
18
+ end
19
+
20
+ context 'when logged in to another collection' do
21
+ subject { user.collection_valid? collection }
22
+
23
+ before { user.log_in(Collection.first(Code: 'NECE')) }
24
+
25
+ it { is_expected.to be_falsey }
26
+ end
27
+ end
28
+
29
+ describe '#log_in' do
30
+ context 'when not logged in' do
31
+ before { user.log_out }
32
+
33
+ it do
34
+ just_before = Time.now
35
+ expect(user.log_in(collection))
36
+ .to include collection => a_value >= just_before
37
+ end
38
+
39
+ it do
40
+ just_before = Time.now
41
+ expect { user.log_in(collection) }
42
+ .to change(user, :values)
43
+ .from(including(IsLoggedIn: false,
44
+ LoginCollectionName: nil,
45
+ LoginDisciplineName: nil,
46
+ LoginOutTime: a_value <= just_before))
47
+ .to(including(IsLoggedIn: true,
48
+ LoginCollectionName: collection[:CollectionName],
49
+ LoginDisciplineName: collection.discipline[:Name],
50
+ LoginOutTime: a_value >= just_before))
51
+ end
52
+ end
53
+
54
+ context 'when already logged in' do
55
+ before { user.log_in(collection) }
56
+
57
+ it do
58
+ just_before = Time.now
59
+ expect(user.log_in(collection))
60
+ .to include collection => a_value <= just_before
61
+ end
62
+
63
+ it do
64
+ expect { user.log_in(collection) }
65
+ .not_to change(user, :values)
66
+ end
67
+ end
68
+
69
+ context 'when already logged in to a different collection' do
70
+ before { user.log_in(Collection.first(Code: 'NECE')) }
71
+
72
+ it do
73
+ expect { user.log_in collection }
74
+ .to raise_error LoginError::INCONSISTENT_LOGIN
75
+ end
76
+ end
77
+ end
78
+
79
+ describe '#log_out' do
80
+ before { user.log_in collection }
81
+
82
+ it do
83
+ just_before = Time.now
84
+ expect(user.log_out)
85
+ .to be >= just_before
86
+ end
87
+
88
+ it do
89
+ just_before = Time.now
90
+ expect { user.log_out }
91
+ .to change(user, :values)
92
+ .from(including(IsLoggedIn: true,
93
+ LoginCollectionName: collection[:CollectionName],
94
+ LoginDisciplineName: collection.discipline[:Name],
95
+ LoginOutTime: a_value <= just_before))
96
+ .to(including(IsLoggedIn: false,
97
+ LoginCollectionName: nil,
98
+ LoginDisciplineName: nil,
99
+ LoginOutTime: a_value >= just_before))
100
+ end
101
+ end
102
+
103
+ describe '#logged_in?' do
104
+ before { user.log_out }
105
+
106
+ context 'when logged in to the collection passed as argument' do
107
+ subject { user.logged_in? collection }
108
+
109
+ before { user.log_in collection }
110
+
111
+ it { is_expected.to include collection => a_value <= Time.now }
112
+ end
113
+
114
+ context 'when logged in to another collection' do
115
+ before { user.log_in(Collection.first(Code: 'NECE')) }
116
+
117
+ it do
118
+ expect { user.log_in collection }
119
+ .to raise_error LoginError::INCONSISTENT_LOGIN
120
+ end
121
+ end
122
+ end
123
+
124
+ describe '#logged_in_agent' do
125
+ subject { user.logged_in_agent }
126
+
127
+ before { user.log_in collection }
128
+
129
+ it do
130
+ is_expected
131
+ .to have_attributes FirstName: 'John', LastName: 'Doe'
132
+ end
133
+ end
134
+
135
+ describe '#new_login' do
136
+ before { user.log_out }
137
+
138
+ it do
139
+ just_before = Time.now
140
+ expect(user.new_login(collection))
141
+ .to include collection => a_value >= just_before
142
+ end
143
+
144
+ it do
145
+ just_before = Time.now
146
+ expect { user.new_login(collection) }
147
+ .to change(user, :values)
148
+ .from(including(IsLoggedIn: false,
149
+ LoginCollectionName: nil,
150
+ LoginDisciplineName: nil,
151
+ LoginOutTime: a_value <= just_before))
152
+ .to(including(IsLoggedIn: true,
153
+ LoginCollectionName: collection[:CollectionName],
154
+ LoginDisciplineName: collection.discipline[:Name],
155
+ LoginOutTime: a_value >= just_before))
156
+ end
157
+ end
158
+
159
+ describe '#view_set_dir' do
160
+ subject { user.view_set_dir(collection) }
161
+
162
+ it do
163
+ is_expected
164
+ .to have_attributes DisciplineType: 'Invertebrate Paleontology',
165
+ IsPersonal: true,
166
+ UserType: 'manager',
167
+ collection: collection,
168
+ user: user,
169
+ discipline: collection.discipline
170
+ end
171
+ end
172
+
173
+ describe '#view_set' do
174
+ subject { user.view_set(collection) }
175
+
176
+ it do
177
+ is_expected.to have_attributes Name: 'paleo.views'
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end