【问题标题】:creating name helper, to split first and last names apart创建名称助手,将名字和姓氏分开
【发布时间】:2011-11-05 22:52:45
【问题描述】:

我正在寻求有关如何获取属性并通过方法处理它以返回不同内容的帮助。但我以前从未这样做过,我不知道从哪里开始。我想尝试将 name:string 属性从“George Washington”或“John Quincy Adams”更改为只有名字的“George”和“John”。

我认为也许一个辅助方法会是最好的,例如

users_helper.rb

def first_name

end

然后调用@user.name.first_name,这会是最初的工作方式吗?有人可以解释我接下来要去哪里才能将@user.name 传递给方法吗?我见过这样的事情,但不太明白括号...

def first_name(name)
  puts name
end

有人能分解一下 rails/ruby 是如何做这种事情的吗?非常感谢!

【问题讨论】:

  • 看过电视节目“The Beverly Hillbillies”中的 Ellie Mae Clampett 吗?

标签: ruby-on-rails ruby-on-rails-3


【解决方案1】:

有些人有两个以上的名字,例如“John Clark Smith”。您可以选择将它们视为:

(1) 名:“约翰”,姓:“史密斯”

  def first_name
    if name.split.count > 1
      name.split.first
    else
      name
    end
  end

  def last_name
    if name.split.count > 1
      name.split.last
    end
  end

(2) 名字:“约翰·克拉克”,姓氏:“史密斯”

  def first_name
    if name.split.count > 1
      name.split[0..-2].join(' ')
    else
      name
    end
  end

  def last_name
    if name.split.count > 1
      name.split.last
    end
  end

(3) 名:“约翰”,姓:“克拉克·史密斯”

  def first_name
    name.split.first
  end

  def last_name
    if name.split.count > 1
      name.split[1..-1].join(' ')
    end
  end

上面的例子假设如果名字包含少于 2 个单词,那么它就是名字。

【讨论】:

    【解决方案2】:

    括号(可选)包含参数列表。

    def first_name(full_name)
      full_name.split(" ")[0]
    end
    

    这假设参数不为零。

    > puts first_name "Jimmy McKickems"
    Jimmy
    > puts first_name "Jeezy"
    Jeezy
    

    但这不是字符串方法,因为您现在的假设是:

    @user.full_name.first_name # Bzzt.
    

    改为:

    first_name @user.name
    

    这可以封装在模型类本身中:

    class User < ActiveRecord
      # Extra stuff elided
    
      def first_name
        self.full_name.blank? ? "" : self.full_name.split(" ")[0]
      end
    end
    

    额外的代码检查名称是 nil 还是空格(blank? 来自 Rails)。如果是,则返回一个空字符串。如果不是,则将其拆分为空格并返回结果数组中的第一项。

    【讨论】:

    • 请注意,如果人们输入“Jimmy Jeezy 博士”作为他们的名字,这可能会影响您。您最终将 first_name 为“博士”。
    • @DaveBryand 当然。它还提出了其他几个假设,都符合 OP 的问题。
    【解决方案3】:

    如果您只希望拆分一次并提供两个部分,则此衬里将起作用:

    last_name, first_name = *name.reverse.split(/\s+/, 2).collect(&:reverse)
    

    将最后一个单词设为姓氏,将其他所有单词设为名字。因此,如果有前缀“Dr.”或中间名将包含在名字中。显然,对于有单独单词的姓氏,“戴高乐”是行不通的,但处理起来要困难得多(如果不是不可能的话)。

    【讨论】:

      【解决方案4】:

      使用 Ruby 的Array#pop

      出于我的需要,我需要取包含 1、2、3 个或更多“名字”的全名,例如“AUSTIN”或“AUSTIN J GILLEY”。

      辅助方法

      def split_full_name_into_first_name_and_last_name( full_name )
        name_array = full_name.split(' ')   # ["AUSTIN", "J", "GILLEY"]
        
        if name_array.count > 1                   
          last_name  = name_array.pop       # "GILLEY"
          first_name = name_array.join(' ') # "AUSTIN J"
      
        else                                      
          first_name = name_array.first           
          last_name  = nil
        end
      
        return [ first_name, last_name ]    # ["AUSTIN J", "GILLEY"]
      end
      

      使用它

      split_full_name_into_first_name_and_last_name( "AUSTIN J GILLEY" )
      # => ["AUSTIN J", "GILLEY"]
      
      split_full_name_into_first_name_and_last_name( "AUSTIN" )
      # => ["AUSTIN", nil]
      

      您可以轻松地将first_namelast_name 分配给:

      first_name, last_name = split_full_name_into_first_name_and_last_name( "AUSTIN J GILLEY" )
      
      first_name
      # => "AUSTIN J"
      
      last_name
      # => "GILLEY"
      

      您可以从那里根据您的需要或想要对其进行修改。

      【讨论】:

        【解决方案5】:

        对于您要求的语法 (@user.name.first_name),Rails 通过向基类型添加方法来进行大量此类扩展,在您的示例中,您可以通过在 String 类上定义方法来做到这一点。

        class String
          def given; self.split(' ').first end
          def surname; self.split(' ').last end
        end
        
        "Phileas Fog".surname # 'fog'
        

        做这样的事情的另一种方法是包装你想扩展的类型,这样你就可以添加你想要的所有疯狂的语法,而不会污染更多的基本类型,比如字符串。

        class ProperName < String
          def given; self.split(' ').first end
          def surname; self.split(' ').last end
        end
        
        class User
          def name
            ProperName.new(self.read_attribute(:name))
          end
        end
        
        u = User.new(:name => 'Phileas Fog')
        u.name # 'Phileas Fog'
        u.name.given # 'Phileas'
        u.name.surname # 'Fog'
        

        【讨论】:

        • 如果 name 是“John”则不起作用,因为它会产生“John John”而且它会丢弃第一个词和最后一个词之间的所有内容。
        【解决方案6】:

        正如伟大的戴夫牛顿回答的补充,这里是“姓氏”版本:

          def last_name
            self.full_name.blank? ? "" : self.full_name.split(" ")[-1]
          end
        

        【讨论】:

          【解决方案7】:

          简单

          class User < ActiveRecord::Base
          
            def first_name
              self.name.split(" ")[0..-2].join(" ")
            end
          
            def last_name
              self.name.split(" ").last
            end
          end
          
          User.create name: "John M. Smith"
          User.first.first_name
          # => "John M."
          User.first.last_name
          # => "Smith"
          

          谢谢

          【讨论】:

            【解决方案8】:
            def test_one(name)
              puts "#{name.inspect} => #{yield(name).inspect}"
            end
            
            def tests(&block)
              test_one nil, &block
              test_one "", &block
              test_one "First", &block
              test_one "First Last", &block
              test_one "First Middle Last", &block
              test_one "First Middle Middle2 Last", &block
            end
            
            puts "First name tests"
            tests do |name|
              name.blank? ? "" : name.split(" ").tap{|a| a.pop if a.length > 1 }.join(" ")
            end
            
            puts "Last name tests"
            tests do |name|
              name.blank? ? "" : (name.split(" ").tap{|a| a.shift }.last || "")
            end
            

            输出:

            First name tests
            nil => ""
            "" => ""
            "First" => "First"
            "First Last" => "First"
            "First Middle Last" => "First Middle"
            "First Middle Middle2 Last" => "First Middle Middle2"
            
            Last name tests
            
            nil => ""
            "" => ""
            "First" => ""
            "First Last" => "Last"
            "First Middle Last" => "Last"
            "First Middle Middle2 Last" => "Last"
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-05-08
              • 2019-05-19
              • 1970-01-01
              • 2016-02-22
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多