class CFF::File

File provides direct access to a CFF Index, with the addition of some filesystem utilities.

To be a fully compliant and valid CFF file its filename should be ‘CITATION.cff’. This class allows you to create files with any filename, and to validate the contents of those files independently of the preferred filename.

Attributes

comment[R]

A comment to be inserted at the top of the resultant CFF file.

filename[R]

The filename of this CFF file.

Public Class Methods

new(filename, title) → File click to toggle source
new(filename, index) → File

Create a new File. Either a pre-existing Index can be passed in or, as with Index itself, a title can be supplied to initalize a new File.

All methods provided by Index are also available directly on File objects.

# File lib/cff/file.rb, line 56
def initialize(filename, param, comment = CFF_COMMENT, create: false)
  param = Index.new(param) unless param.is_a?(Index)

  @filename = filename
  @index = param
  @comment = comment
  @dirty = create
end
open(filename) → File click to toggle source
open(filename) { |cff| block }

With no associated block, File.open is a synonym for ::read. If the optional code block is given, it will be passed the opened file as an argument and the File object will automatically be written (if edited) and closed when the block terminates.

File.open will create a new file if one does not already exist with the provided file name.

# File lib/cff/file.rb, line 87
def self.open(file)
  if ::File.exist?(file)
    content = ::File.read(file)
    comment = File.parse_comment(content)
    yaml = Util.parse_yaml(content)
  else
    comment = CFF_COMMENT
    yaml = ''
  end

  cff = new(file, yaml, comment, create: (yaml == ''))
  return cff unless block_given?

  begin
    yield cff
  ensure
    cff.write
  end
end
read(filename) → File click to toggle source

Read a file and parse it for subsequent manipulation.

# File lib/cff/file.rb, line 69
def self.read(file)
  content = ::File.read(file)
  comment = File.parse_comment(content)

  new(file, Util.parse_yaml(content), comment)
end
validate(filename, fail_on_filename: true) → Array click to toggle source

Read a file and return an array with the result. The result array is a three-element array, with true/false at index 0 to indicate pass/fail, an array of schema validation errors at index 1 (if any), and true/false at index 2 to indicate whether the filename passed/failed validation.

You can choose whether filename validation failure should cause overall validation failure with the fail_on_filename parameter (default: true).

# File lib/cff/file.rb, line 118
def self.validate(file, fail_on_filename: true)
  File.read(file).validate(fail_on_filename: fail_on_filename)
end
validate!(filename, fail_on_filename: true) click to toggle source

Read a file and raise a ValidationError upon failure. If an error is raised it will contain the detected validation failures for further inspection.

You can choose whether filename validation failure should cause overall validation failure with the fail_on_filename parameter (default: true).

# File lib/cff/file.rb, line 131
def self.validate!(file, fail_on_filename: true)
  File.read(file).validate!(fail_on_filename: fail_on_filename)
end
write(filename, File) click to toggle source
write(filename, Index)
write(filename, yaml)

Write the supplied File, Index or yaml string to file.

# File lib/cff/file.rb, line 141
def self.write(file, cff, comment = '')
  comment = cff.comment if cff.respond_to?(:comment)
  cff = cff.to_yaml unless cff.is_a?(String)
  content = File.format_comment(comment) + cff[YAML_HEADER.length...-1]

  ::File.write(file, content)
end

Public Instance Methods

comment = string or array click to toggle source

A comment to be inserted at the top of the resultant CFF file. This can be supplied as a simple string or an array of strings. When the file is saved this comment is formatted as follows:

  • a simple string is split into 75 character lines and '# ' is prepended to each line;

  • an array of strings is joined into a single string with '\n' and '# ' is prepended to each line;

If you care about formatting, use an array of strings for your comment, if not, use a single string.

# File lib/cff/file.rb, line 217
def comment=(comment)
  @dirty = true
  @comment = comment
end
validate(fail_fast: false, fail_on_filename: true) → Array click to toggle source

Validate this file and return an array with the result. The result array is a three-element array, with true/false at index 0 to indicate pass/fail, an array of schema validation errors at index 1 (if any), and true/false at index 2 to indicate whether the filename passed/failed validation.

You can choose whether filename validation failure should cause overall validation failure with the fail_on_filename parameter (default: true).

# File lib/cff/file.rb, line 160
def validate(fail_fast: false, fail_on_filename: true)
  valid_filename = (::File.basename(@filename) == CFF_VALID_FILENAME)
  result = (@index.validate(fail_fast: fail_fast) << valid_filename)
  result[0] &&= valid_filename if fail_on_filename

  result
end
validate!(fail_fast: false, fail_on_filename: true) click to toggle source

Validate this file and raise a ValidationError upon failure. If an error is raised it will contain the detected validation failures for further inspection.

You can choose whether filename validation failure should cause overall validation failure with the fail_on_filename parameter (default: true).

# File lib/cff/file.rb, line 177
def validate!(fail_fast: false, fail_on_filename: true)
  result = validate(
    fail_fast: fail_fast, fail_on_filename: fail_on_filename
  )
  return if result[0]

  raise ValidationError.new(result[1], invalid_filename: !result[2])
end
write(save_as: filename) click to toggle source

Write this CFF File. The save_as parameter can be used to save a new copy of this CFF File under a different filename, leaving the original file untouched. If save_as is used then the internal filename of the File will be updated to the supplied filename.

# File lib/cff/file.rb, line 193
def write(save_as: nil)
  unless save_as.nil?
    @filename = save_as
    @dirty = true
  end

  File.write(@filename, @index, @comment) if @dirty
  @dirty = false
end