creating name helper, to split first and last name

2020-04-04 12:57发布

I'm looking for some help on how to take an attribute and process it through a method to return something different. But I've never done this before and I' not sure where to start. I thought trying to change a name:string attribute from "George Washington" or "John Quincy Adams" into first names only "George" and "John".

I thought maybe a helper method would be best, such as

users_helper.rb

def first_name

end

and then call @user.name.first_name, would this be initially how it would work? Can someone explain where I'd go next to be able to pass @user.name into the method? I've seen things like this but don't quite understand it the parenthesis...

def first_name(name)
  puts name
end

Could someone breakdown how rails/ruby does this type of thing? Thanks a lot!

8条回答
爷的心禁止访问
2楼-- · 2020-04-04 13:23

In case you are looking to split only once and provide both parts this one liner will work:

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

Makes the last word the last name and everything else the first name. So if there is a prefix, "Dr.", or a middle name that will be included with the first name. Obviously for last names that have separate words, "Charles de Gaulle" it won't work but handling that is much harder (if not impossible).

查看更多
我欲成王,谁敢阻挡
3楼-- · 2020-04-04 13:25

The parentheses (which are optional) enclose the parameter list.

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

This assumes the parameter is not nil.

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

But this is not a string method, as your assumption is now:

@user.full_name.first_name # Bzzt.

Instead:

first_name @user.name

This could be wrapped up in the model class itself:

class User < ActiveRecord
  # Extra stuff elided

  def first_name
    self.full_name.blank? ? "" : self.full_name.split(" ")[0]
  end
end

The extra code checks to see if the name is nil or whitespace (blank? comes from Rails). If it is, it returns an empty string. If it isn't, it splits it on spaces and returns the first item in the resulting array.

查看更多
▲ chillily
4楼-- · 2020-04-04 13:25

making it simple

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"

Thanks

查看更多
Emotional °昔
5楼-- · 2020-04-04 13:33
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

Output:

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"
查看更多
你好瞎i
6楼-- · 2020-04-04 13:34

Some people have more than two names, such as "John Clark Smith". You can choose to treat them as:

(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

The above examples assume that if the name contains less than 2 words then it is a first name.

查看更多
迷人小祖宗
7楼-- · 2020-04-04 13:48

Use Ruby's Array#pop

For my needs I needed to take full names that had 1, 2, 3 or more "names" in them, like "AUSTIN" or "AUSTIN J GILLEY".

The Helper Method

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

Using It

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]

And you can easily assign the first_name and last_name with:

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

first_name
# => "AUSTIN J"

last_name
# => "GILLEY"

You can modify from there based on what you need or want to do with it.

查看更多
登录 后发表回答