class Grepo

grepo find config/locales/hr.yml app/ grepo compare config/locales/hr.yml config/locales/en.yml grepo duplicates config/locales/hr.yml

Public Instance Methods

compare(file_one, file_two='config/locales/en.yml', options={}) click to toggle source
# File lib/grepo.rb, line 48
def compare(file_one, file_two='config/locales/en.yml', options={})
  @for_compare_one = []
  @for_compare_two = []
  # for rails it is 1 bc 0 would compare hr.profile.errors.title and en.profile.errors.title - there are not same
  # profile.errors.title and profile.errors.title without en and hr are the same
  @depth = options[:depth] || 1    

  make_file(file_one, @for_compare_one)
  make_file(file_two, @for_compare_two)

  # what IS NOT in the other but in en
  difference1 = @for_compare_two - @for_compare_one
  # what IS NOT in en.yml but in the other
  difference2 = @for_compare_one  - @for_compare_two

  difference = difference1 + difference2
  if difference.count > 0
    puts "Differences between #{file_two} and #{file_one} :"
    difference.each do |dif|
      puts "  #{dif}"
    end
  else
    puts "Same in #{file_one} and #{file_two}"
  end
end
find(str_located_in='config/locales/en.yml', search_in='app/', options={}) click to toggle source
# File lib/grepo.rb, line 12
def find(str_located_in='config/locales/en.yml', search_in='app/', options={})
  @target = search_in
  file = str_located_in
  @text = File.read(file)
  @type = str_located_in.split(".").last || "yml"

  # for rails it is 1 bc 0 would search hr.profile.errors.title, depth = 2 would search for errors.title
  @depth = options[:depth] || 1    

  # for example profile.new_post.title - this will be used to grep
  @grep_for = []

  if @type == "yml"
    whole_file = YAML.load(@text)
  elsif @type == "json"
    whole_file = JSON.parse(@text)
  end

  whole_file.each do |key, value|
    if value.is_a? String
      @grep_for << "#{key}"
    else
      value.each do |k, v|
        go_deeper(1, key, {key: k, value: v})
      end 
    end
  end

  puts "In #{@target} there are no:"
  @grep_for.each do |l|
    if `grep -r "t('#{l}')" #{@target}`.length == 0 and `grep -r 't(\"#{l}\")' #{@target}`.length == 0 
      puts "  #{l}"
    end
  end
end
find_duplicates(file='config/locales/en.yml') click to toggle source
# File lib/grepo.rb, line 74
def find_duplicates(file='config/locales/en.yml')
  @type = file.split(".").last || "yml"
  if @type == "yml"
    formated_lines = []
    current_yaml_keys = {}
    line_number = 0;
    previous_indentation_level = -1

    # go through each line of the file
    File.readlines(file).map do |line|
      line_number += 1
      # letters without strings that come after ':'
      letters = line.split(":")[0].split("") # =~ /\A\s*\Z/

      indentation_level=0
      letters.each do |letter| 
        # if letter is an empty string count the indentation
        if letter =~ /\A\s*\Z/
          indentation_level += 1 
        else
          # break if there is an error in key - an empty space in key
          break
        end
      end

      # check if there are any indentation errors - all keys are even
      if indentation_level % 2 != 0
        puts "There is an indentation error on line #{line_number} "
        break
      end

      # if the previous indentation level is bigger than current than it is a new key that is NOT nested in the last one
      # if it is smaller then it is a new key but nested in the last
      if previous_indentation_level > indentation_level 
        # remove key in that the new key is not nested
        current_yaml_keys.delete_if{ |key, value| key.to_i >= indentation_level }
      end

      # add the key to and his indentation_level
      current_yaml_keys["#{indentation_level}"] = letters.delete_if{|l| l == " "}.join("")

      # formated line is for example hr.our_homepage.title
      formated_line = ""
      current_yaml_keys.each do |key, value|
        formated_line += "." unless key=="0"
        formated_line += value
      end
      formated_lines << formated_line

      # indentation_level will be previous_indentation_level in next iterration
      previous_indentation_level=indentation_level
    end

    # report duplicated
    duplicated_lines = formated_lines.find_all { |x| formated_lines.count(x) > 1 }.uniq
    if duplicated_lines.count > 0
      puts "There are some duplicated: "
      duplicated_lines.each do |line|
        puts "  #{line}"
      end
    else
      puts "There are no duplicates!"
    end
  elsif @type == "json"
    JSON.parser = JSON::Ext::Parser
    text = File.read(file)
    whole_file = JSON.parse(text)

    # DuplicateKeyChecker will find double keys and values while json is parsing
    duplicated_keys = JSON.parse(text, { object_class:DuplicateKeyChecker }).get_duplicates

    # now find keys in format: hr.form.something
    @grep_for = []
    @depth = 0
    whole_file.each do |key, value|
      if value.is_a? String
        @grep_for << "#{key}"
      else
        value.each do |k, v|
          go_deeper(1, key, {key: k, value: v, add_value: true})
        end 
      end
    end

    # now find out which keys are repeating and print them out like: hr.form.whatever
    if duplicated_keys.count > 0
      duplicated_keys.map do |dk|
        puts "There are some duplicated:" 
        if dk[:value].is_a? String 
          # print double keys that haw no more nested keys
          look_for = @grep_for.find{|str| str.include? "#{dk[:key]}:#{dk[:value].delete(" ")}"}

          puts "  #{look_for.split(":")[0]}" if look_for
        else
          # print double keys that have nested keys
          dk[:value].keys.map{|v| "#{dk[:key]}.#{v}"}.each do |sub_str|
            look_for = @grep_for.find{|str| str.include? sub_str}
            puts "  #{look_for.split(":")[0]}" if look_for
          end
        end
      end
    else
      puts "There are no duplicates!"
    end
  end
end

Private Instance Methods

go_deeper(level, parents, options = {}, push_to=@grep_for) click to toggle source
# File lib/grepo.rb, line 183
def go_deeper(level, parents, options = {}, push_to=@grep_for)
  if options[:value].is_a? String
    # value is needed for comparing json duplicates - must be without white spaces
    value = ":#{options[:value].delete(" ")}"
    push_to << "#{parents}.#{options[:key]}#{options[:add_value] ? value : "" }".split(".")[@depth..-1].join(".")
  else 
    level += 1
    options[:value].each do |k, v|
      new_parents = "#{parents}.#{options[:key]}"
      go_deeper(level, new_parents, {key: k, value: v, add_value: options[:add_value]}, push_to)
    end
  end
end
make_file(file, compare) click to toggle source
# File lib/grepo.rb, line 197
def make_file(file, compare)
  text = File.read(file)
  type = file.split(".").last || "yml"
  if type == "yml"
    whole_file = YAML.load(text)
  elsif type == "json"
    whole_file = JSON.parse(text)
  end

  whole_file.each do |key, value|
    if value.is_a? String
      compare << "#{key}"
    else
      value.each do |k, v|
        go_deeper(1, key, {key: k, value: v}, compare)
      end 
    end
  end
end