3
\$\begingroup\$

In our applications we have a version file that has three variables that are then joined to create a string that can be used for the semantic version.

The file looks like:

# frozen_string_literal: true

major = 0
minor = 1
patch = 0

PORTAL_VERSION = [major, minor, patch].join('.')

And then we update it using the following from our CI server:

@version = '0.1.1' # this is passed from somewhere

puts 'updating version'
version_file = File.open("version.rb").read
version = @version.split('.')
version_file = version_file.gsub(/(major = \w)/, "major = #{version[0]}")
version_file = version_file.gsub(/(minor = \w)/, "minor = #{version[1]}")
version_file = version_file.gsub(/(patch = \w)/, "patch = #{version[2]}")
File.open('version.rb', 'wb') { |file| file.write(version_file) }
puts "updated version to #{@version}"

Is there a better way to do the replacement using the regex? As by having to find each line and then replace it feels a little dirty, plus if there was or wasn't spaces between the variable name and value it wouldn't work. So it feels a little fragile.

\$\endgroup\$
  • \$\begingroup\$ Why not generate a new version.rb from scratch instead of trying to edit it? \$\endgroup\$ – 200_success May 8 '18 at 20:44
2
\$\begingroup\$

There might be two easier options:

  • Generate the file using a template file something like the following

    major = {{major}}
    minor = {{minor}}
    patch = {{patch}}
    

that has strings that are easy to search for. You could also use ERB to generate the file.

  • Put the logic in your version.rb file something like:

    PORTAL_VERSION = '1.2.3'
    major, minor, path = PORTAL_VERSION.split('.').map(&:to_i)
    

This way you would just have to replace the first line.

  • If you want to do it using your logic I would change the regex from /(patch = \w)/ to /(patch\s*=\s*\w+)/ this would handle extra whitespace and version numbers bigger than 9

  • Note you can also do variable substitution in Regexes so you could write your code as:

    ['major', 'minor', 'patch'].each.with_index do |key, i|
      version_file.sub!(/(#{key}\s*=\s*\w+)/, "#{key} = #{version[i]}")
    end
    

Note that gsub isn't necessary as you only expect one occurrence.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.