Stimulus 1.x to 2.0 conversion helper

Well I bit the bullet and updated to stimulus 2.0. Everything seems to work, it’s just that you get all these warning to rename your targets (as advertised)

I looked around to see if there was any info or suggestions to help the conversion but could not find any. After a few painful attempts of using sublime text replace options I figured there had to be a better way.

I could pretty much find all the files containing data-target and then go through 2 find and replaces, one for the html data-target="" and one for the rails data:{} helper. This became boring and error prone, So I spend probably more time than it would have taken me the continue with sublime to write a little conversion class.

class Stimulus1to2
  attr_accessor  :slim_targets, :data_targets, :gsub_targets, :slimfile
  
  def initialize(filepath = nil)
    filepath = "/users/salex/work/rf/ptgolf/app/views/games/pending/score_teams.html.slim" if file path.blank?
    in_file = filepath
    out_file = filepath + '.conv'
    @slimfile = File.read(in_file)

    @gsub_targets = {}  # the final hash which will replace old target with new target
    # target are either in an html element or rails data hash, get both
    @slim_targets = slimfile.scan(/(data-target=["'][^"']+["'])/).flatten
    @data_targets = slimfile.scan(/(target:["'][^"']+["'])/).flatten
    # since both may have multiple targets, convert them to new format
    convert_data_targets
    convert_slim_targets
    # the conversion returns an array of strings for each target, join them
    gsub_targets.each{ |node,arr| gsub_targets[node] = arr.join(', ') }
    # replace targets in slimfile
    gsub_targets.each do |node,new_target| 
      slimfile.gsub!(node,new_target)
    end
    # write out the file or get view it
    #File.write(out_file,slimfile)
    puts slimfile
  end

  def convert_data_targets
    data_targets.each do |obj|
      # get all the controller.target strings using old method
      targets = get_targets(obj)
      #split the controller.target strings and build the new format
      targets.each do |cdott|
        controller,target = cdott.split('.')
        gsub_stuff = "#{controller}_target:\"#{target}\""
        gsub_targets[obj] << gsub_stuff
      end
    end
  end

  def convert_slim_targets
    # get all the controller.target strings using old method
    slim_targets.each do |obj|
      targets = get_targets(obj)
      #split the controller.target strings and build the new format
      targets.each do |cdott|
        controller,target = cdott.split('.')
        gsub_stuff = "data-#{controller}-target=\"#{target}\""
        gsub_targets[obj] << gsub_stuff
      end
    end
  end

  def get_targets(obj)
    # there can be multiple targets that will end up in a nested array
    gsub_targets[obj] = []
    multi_targets = obj.scan(/["']([^"']+)['"]/)
    # get the controller.target strings for each target
    targets = multi_targets[0][0].split
  end

end

Now I’m not a ruby expert and probably still write code like I did in Apple II basic, but it worked for me. I’m sure it could be improved.

The process is basically

  • call Stimulus1to2.new with a file path to a template (I use slim, but erb should work)
  • Read the file/template
  • Find all the html/slim targets
  • Find all the rails data targets.
  • Convert the old way to the new way and store in the gsub_targets hash
    • key is the original node/target and value is an array of replacements
  • Iterate through the hash and replace the old targets with the new.

I does handle multiple targets, which you can’t do anymore :slight_smile:

My files were fairly consistent on how i wrote the targets, but if you use `=>’ to define rails data attributes, you might have to tweak the to regex that find the targets,

1 Like