创建名称助手,将名字和姓氏分开

时间:2011-11-05 22:52:45

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

我正在寻找一些关于如何获取属性并通过方法处理它以返回不同内容的帮助。但我以前从未这样做过,我不确定从哪里开始。我想改变一个名字:字符串属性从“乔治华盛顿”或“约翰昆西亚当斯”变成名字只有“乔治”和“约翰”。

我认为帮助方法可能最好,例如

users_helper.rb

def first_name

end

然后调用@ user.name.first_name,这最初是如何工作的?有人可以解释我下一步可以将@ user.name传递给方法吗?我已经看过这样的事情,但不太明白括号......

def first_name(name)
  puts name
end

有人可能会破坏rails / ruby​​这种类型的东西吗?非常感谢!

8 个答案:

答案 0 :(得分:13)

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

(1)first_name:“John”,last_name:“Smith”

  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)first_name:“John Clark”,last_name:“Smith”

  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)first_name:“John”,last_name:“Clark Smith”

  def first_name
    name.split.first
  end

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

以上示例假设如果名称包含少于2个单词,则它是名字。

答案 1 :(得分:6)

括号(可选)括起参数列表。

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

这假定参数不是nil。

> 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

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

答案 2 :(得分:4)

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

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

将最后一个单词作为姓氏,将其他所有内容作为名字。因此,如果有一个前缀,“Dr.”或将包含在名字中的中间名。显然,对于具有单独词语的姓氏,“Charles de Gaulle”它不起作用,但处理更难(如果不是不可能的话)。

答案 3 :(得分:1)

对于你要求的语法(@user.name.first_name),Rails通过向基类型添加方法来做很多这种扩展,在你的例子中,你可以通过在String类上定义方法来做到这一点。 / p>

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'

答案 4 :(得分:1)

正如Dave Newton的回答一样,这就是“姓氏”版本:

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

答案 5 :(得分:1)

简化

> str(chars)
 chr [1:40] "R" "'" "s" " " "i" "n" "t" "e" "r" "n" ...

由于

答案 6 :(得分:1)

使用Ruby Array#pop

根据我的需要,我需要使用包含1,2,3或更多名称的完整名称&#34;在他们中间,像#A; AUSTIN&#34;或者&#34; AUSTIN J GILLEY&#34;。

助手方法

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"

您可以根据需要或想要的内容进行修改。

答案 7 :(得分:0)

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"