Модель рельсов: Имя - Первый, Последний - PullRequest
7 голосов
/ 14 октября 2010

Я довольно новичок в rails, работаю над приложением Rails 3 с моделью Profile для пользователей.

В модели профиля я хотел бы иметь запись «имя», и я хотел бы иметь возможность доступа к ее логическим вариантам, используя простой синтаксис, такой как:

user.profile.name = "John Doe"
user.profile.name.first = "John"
user.profile.name.last = "Doe"

Возможно ли это, или мне нужно придерживаться "first_name" и "last_name" в качестве моих полей в этой модели?

Ответы [ 4 ]

16 голосов
/ 14 октября 2010

Это возможно, но я бы не советовал.

Я бы просто использовал first_name и last_name на вашем месте и добавил бы метод fullname:

def fullname
  "#{first_name} #{last_name}"
end

Edit:

Если вы действительно хотите user.profile.name, вы можете создать Name модель, подобную этой:

class Name < ActiveRecord::Base
  belongs_to :profile

  def to_s
    "#{first} #{last}"
  end
end

Это позволяет вам:

user.profile.name.to_s  # John Doe
user.profile.name.first # John
user.profile.name.last  # Doe
8 голосов
/ 14 октября 2010

Все остальные ответы верны, поскольку они игнорируют агрегатор #med_of :

class Name
  attr_reader :first, :last

  def initialize(first_name, last_name)
    @first, @last = first_name, last_name
  end

  def full_name
    [@first, @last].reject(&:blank?).join(" ")
  end

  def to_s
    full_name
  end
end

class Profile < ActiveRecord::Base
  composed_of :name, :mapping => %w(first_name last_name)
end

# Rails console prompt
> profile = Profile.new(:name => Name.new("Francois", "Beausoleil"))
> profile.save!

> profile = Profile.find_by_first_name("Francois")
> profile.name.first
"Francois"

Как указано на странице #composed_of, необходимо назначить новый экземплярагрегатора: вы не можете просто заменить значения в агрегаторе.Класс агрегатора действует как Значение, как простая строка или число.

Вчера я также отправил ответ с очень похожим ответом: Как лучше связать Адрес с несколькими моделями в рельсах?

3 голосов
/ 14 октября 2010

Как сказал капитан Токио, это ужасная идея, но вот как вы это сделаете:

rails g model User full_name:hash

Тогда вы бы хранили в нем данные так:

user = User.new
user.full_name = {:first => "Forrest", :last => "Gump"}

Теперь твои проблемы начинаются.

Для поиска в поле требуются оба имени, и вы не можете выполнять частичный поиск, например, поиск всех людей с одинаковой фамилией. Хуже всего то, что вы можете хранить что угодно в поле! Итак, представьте, что другой программист набирает опечатки одним из имен полей, чтобы на неделю вы вставили в базу данных {: fist => "Name",: last => "Last"}! Noooooooooooooooooo!

Если вы использовали правильные имена полей, вы могли бы сделать это:

user = User.new(:first_name => "First", :last_name => "Last")

Легко читается и не требует хэшей. Теперь, когда вы знаете, как сделать это неправильно, сделайте это правильно. :)

2 голосов
/ 14 октября 2010

К вашему сведению (предположим, у вас есть поле fullname. То есть ваш profile.name = "John Doe")

class Profile
  def name
    @splited_name ||= fullname.split # @splited_name would cache the result so that no need to split the fullname every time
  end
end

Теперь вы можете сделать что-то вроде этого:

user.profile.fullname   # "John Doe"
user.profile.name.first # "John"
user.profile.name.last  # "Doe"

Обратите внимание на следующий случай:

user.profile.fullname = "John Ronald Doe"
user.profile.name.first  # "John"
user.profile.name.second # "Ronald"
user.profile.name.last   # "Doe"

Я согласен с капитаном Токио. Вы не пропустите вторые имена. Также этот метод не предполагает ввода китайских и японских имен. Это потому, что эти имена обычно не содержат пробелов между именем и фамилией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...