class CFF::File

File provides direct access to a CFF Model, 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, model) → File

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

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

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

  @filename = filename
  @model = 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 85
def self.open(file)
  if ::File.exist?(file)
    content = ::File.read(file)
    comment = File.parse_comment(content)
    yaml = YAML.safe_load(content, permitted_classes: [Date, Time])
  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 65
def self.read(file)
  content = ::File.read(file)
  comment = File.parse_comment(content)

  new(
    file, YAML.safe_load(content, permitted_classes: [Date, Time]), 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 116
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 129
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, Model)
write(filename, yaml)

Write the supplied File, Model or yaml string to `file`.

# File lib/cff/file.rb, line 139
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 215
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 158
def validate(fail_fast: false, fail_on_filename: true)
  valid_filename = (::File.basename(@filename) == CFF_VALID_FILENAME)
  result = (@model.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 175
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 191
def write(save_as: nil)
  unless save_as.nil?
    @filename = save_as
    @dirty = true
  end

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