Why does Rails titlecase add a space to a name?

前端 未结 10 1167
我在风中等你
我在风中等你 2021-02-05 10:28

Why does the titlecase mess up the name? I have:

John Mark McMillan

and it turns it into:

>> \"john mark McM         


        
相关标签:
10条回答
  • 2021-02-05 10:48

    You're trying to use a generic method for converting Rail's internal strings into more human readable names. It's not designed to handle "Mc" and "Mac" and "Van Der" and any number of other compound spellings.

    You can use it as a starting point, then special case the results looking for the places it breaks and do some fix-ups, or you can write your own method that includes special-casing those edge cases. I've had to do that several times in different apps over the years.

    0 讨论(0)
  • 2021-02-05 10:50

    If you want to handle the case where someone has entered JOHN CAPSLOCK JOE as well as the others, I combined this one:

    class String
      def proper_titlecase
        if self.titleize.split.length == self.split.length
          self.titleize
        else
          self.split(" ").collect{|word| word[0] = word[0].upcase; word}.join(" ")
        end
      end
    end
    

    Depends if you want that kinda logic on a String method ;)

    0 讨论(0)
  • 2021-02-05 10:51

    The "Why" question has already been answered...but as evidenced by the selected answer and upvotes, I think what most of us are ACTUALLY wanting is a silver bullet to deal with the hell that is name-formatting...While multiple capitals trigger that behavior, I've found that hyphenated names do the same.

    These cases and many more have already been handled in the gem, NameCase.

    In version 2.0 it only converts a string if the string is all uppercase or all lowercase, based on a defined ruleset as a best guess. I like this, because I'm sure the ruleset can never be 100% correct. Example, Ian McDonald (from Scotland) has a different capitalization from Ian Mcdonald (from Ireland)...however those names will be handled correctly at the time of input if the user is particular and if not, the name can be corrected if needed and retain its formatting.

    My Solution:

    # If desired, add string method once NameCase gem is added
    class String
    
      def namecase
        NameCase(self)
      end
    
    end
    

    Tests: (name.namecase)

    test_names = ["john mark McMillan", "JOHN CAPSLOCK JOE", "test name", "test name-name", "test McName-name", "John w McHENRY", "ian mcdonald", "Ian McDonald", "Ian Mcdonald"]
    
    test_names.each { |name| puts '# "' + name + '" => "' + name.namecase + '"' }
      # "john mark McMillan" => "John Mark McMillan"
      # "JOHN CAPSLOCK JOE" => "John Capslock Joe"
      # "test name" => "Test Name"
      # "test name-name" => "Test Name-Name"
      # "test McName-name" => "Test McName-Name"
      # "John w McHENRY" => "John w McHENRY" -FAIL
      # "ian mcdonald" => "Ian McDonald"
      # "Ian McDonald" => "Ian McDonald"
      # "Ian Mcdonald" => "Ian Mcdonald"
    

    If you feel you need to handle all of the corner cases on this page and don't care about losing names that may have been formatted at the start, eg. Ian Mcdonald (from Ireland)...you could use upcase first:

    Tests: (name.upcase.namecase)

    test_names.each { |name| puts '# "' + name + '" => "' + name.upcase.namecase + '"' }
      # "john mark McMillan" => "John Mark McMillan"
      # "JOHN CAPSLOCK JOE" => "John Capslock Joe"
      # "test name" => "Test Name"
      # "test name-name" => "Test Name-Name"
      # "test McName-name" => "Test McName-Name"
      # "John w McHENRY" => "John W McHenry"
      # "ian mcdonald" => "Ian McDonald"
      # "Ian McDonald" => "Ian McDonald"
      # "Ian Mcdonald" => "Ian McDonald"
    

    The only silver bullet is to go old school...ALL CAPS. But who wants that eyesore in their modern web app?

    0 讨论(0)
  • 2021-02-05 10:57

    You can always do it yourself if Rails isn't good enough:

    class String
        def another_titlecase
            self.split(" ").collect{|word| word[0] = word[0].upcase; word}.join(" ")
        end
    end
    
    "john mark McMillan".another_titlecase
     => "John Mark McMillan" 
    

    This method is a small fraction of a second faster than the regex solution:

    My solution:

    ruby-1.9.2-p136 :034 > Benchmark.ms do
    ruby-1.9.2-p136 :035 >     "john mark McMillan".split(" ").collect{|word|word[0] = word[0].upcase; word}.join(" ")
    ruby-1.9.2-p136 :036?>   end
     =>  0.019311904907226562 
    

    Regex solution:

    ruby-1.9.2-p136 :042 > Benchmark.ms do
    ruby-1.9.2-p136 :043 >     "john mark McMillan".gsub(/\b\w/) { |w| w.upcase }
    ruby-1.9.2-p136 :044?>   end
     => 0.04482269287109375 
    
    0 讨论(0)
提交回复
热议问题