cff 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 330c0177c6b7fed7915ddeddbc8ba68a9eb9f9e3
4
- data.tar.gz: '089cd1ad45d23af25bc1ccbac3b0ffffceedb570'
2
+ SHA256:
3
+ metadata.gz: 32661be9e23147731575824f34df12b82dfb6f0560af3fd4d8081958f633cac6
4
+ data.tar.gz: 5b525849ff1e6ff1829d70e657852377c88bf0b6e83dffff96dd6cd660fc029b
5
5
  SHA512:
6
- metadata.gz: 290ee6b5066a2f5d016ceff0416faf00f8f12df42c72e62b4642efa2a4d5afa64b32fc1a8e7843d3aec8a4165359445e7a2fd940e523a069a6f6509b181797d3
7
- data.tar.gz: 0a99851ff3c46441be5fc86d3317bb2bc1828c5f4e5d15dbb8e507541feb9a73e4ff751a7fbd9355a8097ae42db3ac9bfb38428bd28aa5b981b8cb42a74b4cb9
6
+ metadata.gz: c1df6fd36b30cdd828d9d80ae183795f9eea5a3691684ed0769bbe75b8bca026ed540611f671341bca8880352f396c727931ceb55865086b8613c016af5a7769
7
+ data.tar.gz: 0f3afd7def478528b073c4a9454c804731fe6c50cde9acbcdafa0fdc0d6bfba577ca812fcc34fe0b36732f5b1dafebde2b90940f81c6ddf882ac22754b01b419
data/CHANGES.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changes log for the Ruby CFF Library
2
2
 
3
+ ## Version 0.4.0
4
+
5
+ * Remove unused Util#expand_field method.
6
+ * Changed Model#keywords to be a field type.
7
+ * Model is now a subclass of ModelPart.
8
+ * Document ModelPart and Util just enough.
9
+ * Add Util::normalize_modelpart_array! method.
10
+ * Tighten up checking for empty collections in model.
11
+ * Move the references into the Model fields.
12
+ * Add an in-place actor collection builder method.
13
+ * Move authors and contact to Model fields.
14
+ * Refactor Reference so the actor lists are fields.
15
+ * Remove unused method: Util::build_actor_collection.
16
+ * Remove unused method: Util::expand_array_field.
17
+ * Add rubocop to the development dependencies.
18
+ * Add rubocop configuration files.
19
+ * Add rubocop rake tasks.
20
+ * Many rubocop fixes.
21
+ * Compact ALLOWED_FIELDS lists for consistency.
22
+ * Allow creation of a Reference without a type.
23
+ * Remove unused method: Util.delete_from_hash.
24
+ * Refactor duplicated code into Util.fields_to_hash.
25
+ * Add File#write (instance method).
26
+ * Ensure a model always returns '' for missing fields.
27
+ * Test reading short and minimal CFF files.
28
+ * Cleanup duplicated tests.
29
+ * Don't store dotfiles in the gemfile.
30
+ * Add a CITATION.cff file!
31
+
3
32
  ## Version 0.3.0
4
33
 
5
34
  * Update badges for new repo location.
@@ -0,0 +1,21 @@
1
+ cff-version: 1.0.3
2
+ message: If you use ruby-cff in your work, please cite it using the following metadata
3
+ title: Ruby CFF Library
4
+ abstract: This library provides a Ruby interface to manipulate CITATION.cff files
5
+ authors:
6
+ - family-names: Haines
7
+ given-names: Robert
8
+ orcid: https://orcid.org/0000-0002-9538-7919
9
+ affiliation: The University of Manchester, UK
10
+ keywords:
11
+ - ruby
12
+ - credit
13
+ - citation
14
+ - metadata
15
+ - cff
16
+ version: 0.4.0
17
+ doi: 10.5281/zenodo.1184077
18
+ date-released: 2018-07-29
19
+ license: Apache-2.0
20
+ repository-artifact: https://rubygems.org/gems/cff
21
+ repository-code: https://github.com/citation-file-format/ruby-cff
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
data/Rakefile CHANGED
@@ -12,22 +12,25 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require "bundler/gem_tasks"
16
- require "rake/testtask"
17
- require "rdoc/task"
15
+ require 'bundler/gem_tasks'
16
+ require 'rake/testtask'
17
+ require 'rdoc/task'
18
+ require 'rubocop/rake_task'
18
19
 
19
- task :default => :test
20
+ task default: :test
20
21
 
21
22
  Rake::TestTask.new(:test) do |t|
22
- t.libs << "test"
23
- t.libs << "lib"
24
- t.test_files = FileList["test/**/*_test.rb"]
23
+ t.libs << 'test'
24
+ t.libs << 'lib'
25
+ t.test_files = FileList['test/**/*_test.rb']
25
26
  end
26
27
 
27
28
  RDoc::Task.new do |r|
28
- r.main = "README.md"
29
- r.rdoc_files.include("README.md", "LICENCE", "CHANGES.md", "lib/**/*.rb")
30
- r.options << "--markup=markdown"
31
- r.options << "--tab-width=2"
29
+ r.main = 'README.md'
30
+ r.rdoc_files.include('README.md', 'LICENCE', 'CHANGES.md', 'lib/**/*.rb')
31
+ r.options << '--markup=markdown'
32
+ r.options << '--tab-width=2'
32
33
  r.options << "-t Ruby CFF Library version #{::CFF::VERSION}"
33
34
  end
35
+
36
+ RuboCop::RakeTask.new
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "cff"
3
+ require 'bundler/setup'
4
+ require 'cff'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "cff"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
@@ -12,37 +12,39 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- lib = File.expand_path("../lib", __FILE__)
15
+ lib = File.expand_path('lib', __dir__)
16
16
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
17
- require "cff/version"
17
+ require 'cff/version'
18
18
 
19
19
  Gem::Specification.new do |spec|
20
- spec.name = "cff"
20
+ spec.name = 'cff'
21
21
  spec.version = CFF::VERSION
22
- spec.authors = ["Robert Haines"]
23
- spec.email = ["robert.haines@manchester.ac.uk"]
22
+ spec.authors = ['Robert Haines']
23
+ spec.email = ['robert.haines@manchester.ac.uk']
24
24
 
25
- spec.summary = "A Ruby library for manipulating CITATION.cff files."
26
- spec.description = "See https://citation-file-format.github.io/ for more info."
27
- spec.homepage = "https://github.com/citation-file-format/ruby-cff"
28
- spec.license = "Apache-2.0"
25
+ spec.summary = 'A Ruby library for manipulating CITATION.cff files.'
26
+ spec.description = 'See https://citation-file-format.github.io/ ' \
27
+ 'for more info.'
28
+ spec.homepage = 'https://github.com/citation-file-format/ruby-cff'
29
+ spec.license = 'Apache-2.0'
29
30
 
30
31
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
31
- f.match(%r{^(test|spec|features)/})
32
+ f.match(%r{^((test|spec|features)/|\.)})
32
33
  end
33
- spec.bindir = "exe"
34
+ spec.bindir = 'exe'
34
35
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
- spec.require_paths = ["lib"]
36
+ spec.require_paths = ['lib']
36
37
 
37
- spec.required_ruby_version = ">= 2.2.0"
38
+ spec.required_ruby_version = '>= 2.2.0'
38
39
 
39
- spec.add_runtime_dependency "language_list", "~> 1.2"
40
- spec.add_runtime_dependency "spdx-licenses", "~> 1.1"
40
+ spec.add_runtime_dependency 'language_list', '~> 1.2'
41
+ spec.add_runtime_dependency 'spdx-licenses', '~> 1.1'
41
42
 
42
- spec.add_development_dependency "bundler", "~> 1.16"
43
- spec.add_development_dependency "rake", "~> 10.0"
44
- spec.add_development_dependency "minitest", "~> 5.0"
45
- spec.add_development_dependency "coveralls", "~> 0.8"
46
- spec.add_development_dependency "test_construct", "~> 2.0"
47
- spec.add_development_dependency "rdoc", "~> 6.0"
43
+ spec.add_development_dependency 'bundler', '~> 1.16'
44
+ spec.add_development_dependency 'coveralls', '~> 0.8'
45
+ spec.add_development_dependency 'minitest', '~> 5.0'
46
+ spec.add_development_dependency 'rake', '~> 10.0'
47
+ spec.add_development_dependency 'rdoc', '~> 6.0'
48
+ spec.add_development_dependency 'rubocop', '~> 0.54'
49
+ spec.add_development_dependency 'test_construct', '~> 2.0'
48
50
  end
data/lib/cff.rb CHANGED
@@ -12,19 +12,19 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require "date"
16
- require "yaml"
17
- require "language_list"
18
- require "spdx-licenses"
15
+ require 'date'
16
+ require 'yaml'
17
+ require 'language_list'
18
+ require 'spdx-licenses'
19
19
 
20
- require "cff/version"
21
- require "cff/util"
22
- require "cff/model-part"
23
- require "cff/person"
24
- require "cff/entity"
25
- require "cff/reference"
26
- require "cff/model"
27
- require "cff/file"
20
+ require 'cff/version'
21
+ require 'cff/util'
22
+ require 'cff/model_part'
23
+ require 'cff/person'
24
+ require 'cff/entity'
25
+ require 'cff/reference'
26
+ require 'cff/model'
27
+ require 'cff/file'
28
28
 
29
29
  # This library provides a Ruby interface to manipulate CITATION.cff files. The
30
30
  # primary entry points are Model and File.
@@ -32,5 +32,4 @@ require "cff/file"
32
32
  # See the [CITATION.cff documentation](https://citation-file-format.github.io/)
33
33
  # for more details.
34
34
  module CFF
35
-
36
35
  end
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- #
15
+ ##
16
16
  module CFF
17
17
 
18
18
  # An Entity can represent different types of entities, e.g., a publishing
@@ -21,20 +21,8 @@ module CFF
21
21
  class Entity < ModelPart
22
22
 
23
23
  ALLOWED_FIELDS = [
24
- 'address',
25
- 'city',
26
- 'country',
27
- 'email',
28
- 'date-end',
29
- 'date-start',
30
- 'fax',
31
- 'location',
32
- 'name',
33
- 'orcid',
34
- 'post-code',
35
- 'region',
36
- 'tel',
37
- 'website'
24
+ 'address', 'city', 'country', 'email', 'date-end', 'date-start', 'fax',
25
+ 'location', 'name', 'orcid', 'post-code', 'region', 'tel', 'website'
38
26
  ].freeze # :nodoc:
39
27
 
40
28
  # :call-seq:
@@ -42,7 +30,7 @@ module CFF
42
30
  #
43
31
  # Create a new Entity with the supplied name.
44
32
  def initialize(param)
45
- if Hash === param
33
+ if param.is_a?(Hash)
46
34
  @fields = param
47
35
  else
48
36
  @fields = Hash.new('')
@@ -56,9 +44,7 @@ module CFF
56
44
  # Set the `date-end` field. If a non-Date object is passed in it will
57
45
  # be parsed into a Date.
58
46
  def date_end=(date)
59
- unless Date === date
60
- date = Date.parse(date)
61
- end
47
+ date = Date.parse(date) unless date.is_a?(Date)
62
48
 
63
49
  @fields['date-end'] = date
64
50
  end
@@ -69,12 +55,9 @@ module CFF
69
55
  # Set the `date-start` field. If a non-Date object is passed in it will
70
56
  # be parsed into a Date.
71
57
  def date_start=(date)
72
- unless Date === date
73
- date = Date.parse(date)
74
- end
58
+ date = Date.parse(date) unless date.is_a?(Date)
75
59
 
76
60
  @fields['date-start'] = date
77
61
  end
78
-
79
62
  end
80
63
  end
@@ -12,14 +12,14 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- #
15
+ ##
16
16
  module CFF
17
17
 
18
18
  # File provides direct access to a CFF Model, with the addition of some
19
19
  # filesystem utilities.
20
20
  class File
21
21
 
22
- YAML_HEADER = "---\n" # :nodoc:
22
+ YAML_HEADER = "---\n".freeze # :nodoc:
23
23
 
24
24
  # :call-seq:
25
25
  # new(title) -> File
@@ -31,9 +31,7 @@ module CFF
31
31
  # All methods provided by Model are also available directly on File
32
32
  # objects.
33
33
  def initialize(param)
34
- unless Model === param
35
- param = Model.new(param)
36
- end
34
+ param = Model.new(param) unless param.is_a?(Model)
37
35
 
38
36
  @model = param
39
37
  end
@@ -43,7 +41,7 @@ module CFF
43
41
  #
44
42
  # Read a file and parse it for subsequent manipulation.
45
43
  def self.read(file)
46
- new(YAML::load_file(file))
44
+ new(YAML.load_file(file))
47
45
  end
48
46
 
49
47
  # :call-seq:
@@ -52,16 +50,25 @@ module CFF
52
50
  #
53
51
  # Write the supplied model or yaml string to `file`.
54
52
  def self.write(file, cff)
55
- unless String === cff
56
- cff = cff.to_yaml
57
- end
53
+ cff = cff.to_yaml unless cff.is_a?(String)
58
54
 
59
55
  ::File.write(file, cff[YAML_HEADER.length...-1])
60
56
  end
61
57
 
58
+ # :call-seq:
59
+ # write(file)
60
+ #
61
+ # Write this CFF File to `file`.
62
+ def write(file)
63
+ File.write(file, @model)
64
+ end
65
+
62
66
  def method_missing(name, *args) # :nodoc:
63
- @model.send name, *args
67
+ @model.respond_to?(name) ? @model.send(name, *args) : super
64
68
  end
65
69
 
70
+ def respond_to_missing?(name, *all) # :nodoc:
71
+ @model.respond_to?(name, *all)
72
+ end
66
73
  end
67
74
  end
@@ -12,55 +12,94 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- #
15
+ ##
16
16
  module CFF
17
17
 
18
18
  # Model is the core data structure for a CITATION.cff file. It can be
19
19
  # accessed direcly, or via File.
20
- class Model
21
-
22
- include Util
20
+ class Model < ModelPart
23
21
 
24
22
  ALLOWED_FIELDS = [
25
- 'abstract',
26
- 'cff-version',
27
- 'commit',
28
- 'date-released',
29
- 'doi',
30
- 'license',
31
- 'license-url',
32
- 'message',
33
- 'repository',
34
- 'repository-artifact',
35
- 'repository-code',
36
- 'title',
37
- 'url',
38
- 'version'
39
- ].freeze # :nodoc:
23
+ 'abstract', 'authors', 'cff-version', 'contact', 'commit',
24
+ 'date-released', 'doi', 'keywords', 'license', 'license-url', 'message',
25
+ 'references', 'repository', 'repository-artifact', 'repository-code',
26
+ 'title', 'url', 'version'
27
+ ].freeze # :nodoc:
40
28
 
41
29
  # The default message to use if none is explicitly set.
42
- DEFAULT_MESSAGE = "If you use this software in your work, please cite it using the following metadata"
30
+ DEFAULT_MESSAGE = 'If you use this software in your work, please cite ' \
31
+ 'it using the following metadata'.freeze
43
32
 
44
33
  # :call-seq:
45
34
  # new(title) -> Model
46
35
  #
47
36
  # Initialize a new Model with the supplied title.
48
37
  def initialize(param)
49
- @authors = []
50
- @contact = []
51
- @keywords = []
52
- @references = []
53
-
54
- if Hash === param
55
- build_model(param)
38
+ if param.is_a?(Hash)
39
+ @fields = build_model(param)
40
+ @fields.default = ''
56
41
  else
57
42
  @fields = Hash.new('')
58
43
  @fields['cff-version'] = DEFAULT_SPEC_VERSION
59
44
  @fields['message'] = DEFAULT_MESSAGE
60
45
  @fields['title'] = param
61
46
  end
47
+
48
+ %w[authors contact keywords references].each do |field|
49
+ @fields[field] = [] if @fields[field].empty?
50
+ end
62
51
  end
63
52
 
53
+ # :call-seq:
54
+ # date_released = date
55
+ #
56
+ # Set the `date-released` field. If a non-Date object is passed in it will
57
+ # be parsed into a Date.
58
+ def date_released=(date)
59
+ date = Date.parse(date) unless date.is_a?(Date)
60
+
61
+ @fields['date-released'] = date
62
+ end
63
+
64
+ # :call-seq:
65
+ # version = version
66
+ #
67
+ # Set the `version` field.
68
+ def version=(version)
69
+ @fields['version'] = version.to_s
70
+ end
71
+
72
+ def to_yaml # :nodoc:
73
+ YAML.dump fields, line_width: -1, indentation: 2
74
+ end
75
+
76
+ private
77
+
78
+ def fields
79
+ %w[authors contact references].each do |field|
80
+ normalize_modelpart_array!(@fields[field])
81
+ end
82
+
83
+ fields_to_hash(@fields)
84
+ end
85
+
86
+ def build_model(fields)
87
+ build_actor_collection!(fields['authors'] || [])
88
+ build_actor_collection!(fields['contact'] || [])
89
+ (fields['references'] || []).map! do |r|
90
+ Reference.new(r)
91
+ end
92
+
93
+ fields
94
+ end
95
+
96
+ public
97
+
98
+ # Some documentation of "hidden" methods is provided here, out of the
99
+ # way of the main class code.
100
+
101
+ ##
102
+ # :method: authors
64
103
  # :call-seq:
65
104
  # authors -> Array
66
105
  #
@@ -72,10 +111,18 @@ module CFF
72
111
  # ```
73
112
  #
74
113
  # Authors can be a Person or Entity.
75
- def authors
76
- @authors
77
- end
78
114
 
115
+ ##
116
+ # :method: authors=
117
+ # :call-seq:
118
+ # authors = array_of_authors -> Array
119
+ #
120
+ # Replace the list of authors for this citation.
121
+ #
122
+ # Authors can be a Person or Entity.
123
+
124
+ ##
125
+ # :method: contact
79
126
  # :call-seq:
80
127
  # contact -> Array
81
128
  #
@@ -87,23 +134,18 @@ module CFF
87
134
  # ```
88
135
  #
89
136
  # Contacts can be a Person or Entity.
90
- def contact
91
- @contact
92
- end
93
137
 
138
+ ##
139
+ # :method: contact=
94
140
  # :call-seq:
95
- # date_released = date
141
+ # contact = array_of_contacts -> Array
96
142
  #
97
- # Set the `date-released` field. If a non-Date object is passed in it will
98
- # be parsed into a Date.
99
- def date_released=(date)
100
- unless Date === date
101
- date = Date.parse(date)
102
- end
103
-
104
- @fields['date-released'] = date
105
- end
143
+ # Replace the list of contacts for this citation.
144
+ #
145
+ # Contacts can be a Person or Entity.
106
146
 
147
+ ##
148
+ # :method: keywords
107
149
  # :call-seq:
108
150
  # keywords -> Array
109
151
  #
@@ -114,11 +156,19 @@ module CFF
114
156
  # model.keywords << keyword
115
157
  # ```
116
158
  #
117
- # Keywords will be converted to Strings on output to a CFF file.
118
- def keywords
119
- @keywords
120
- end
159
+ # Keywords will be converted to Strings on output.
160
+
161
+ ##
162
+ # :method: keywords=
163
+ # :call-seq:
164
+ # keywords = array_of_keywords -> Array
165
+ #
166
+ # Replace the list of keywords for this citation.
167
+ #
168
+ # Keywords will be converted to Strings on output.
121
169
 
170
+ ##
171
+ # :method: references
122
172
  # :call-seq:
123
173
  # references -> Array
124
174
  #
@@ -128,59 +178,12 @@ module CFF
128
178
  # ```
129
179
  # model.references << reference
130
180
  # ```
131
- def references
132
- @references
133
- end
134
181
 
182
+ ##
183
+ # :method: references=
135
184
  # :call-seq:
136
- # version = version
185
+ # references = array_of_references -> Array
137
186
  #
138
- # Set the `version` field.
139
- def version=(version)
140
- @fields['version'] = version.to_s
141
- end
142
-
143
- def to_yaml # :nodoc:
144
- YAML.dump fields, :line_width => -1, :indentation => 2
145
- end
146
-
147
- def method_missing(name, *args) # :nodoc:
148
- n = method_to_field(name.id2name)
149
- super unless ALLOWED_FIELDS.include?(n.chomp('='))
150
-
151
- if n.end_with?('=')
152
- @fields[n.chomp('=')] = args[0] || ''
153
- else
154
- @fields[n]
155
- end
156
- end
157
-
158
- private
159
-
160
- def fields
161
- model = @fields.dup
162
- [
163
- ['authors', @authors],
164
- ['contact', @contact],
165
- ['references', @references]
166
- ].each do |field, var|
167
- model[field] = expand_array_field(var) unless var.empty?
168
- end
169
- model['keywords'] = @keywords.map { |k| k.to_s } unless @keywords.empty?
170
-
171
- model
172
- end
173
-
174
- def build_model(fields)
175
- build_actor_collection(@authors, fields['authors'])
176
- build_actor_collection(@contact, fields['contact'])
177
- @keywords = fields['keywords']
178
- fields['references'].each do |r|
179
- @references << Reference.new(r)
180
- end
181
-
182
- @fields = delete_from_hash(fields, 'authors', 'contact', 'keywords', 'references')
183
- end
184
-
187
+ # Replace the list of references for this citation.
185
188
  end
186
189
  end