Эта проблема является хорошим кандидатом для виртуальных атрибутов.
Вместо того, чтобы пытаться определить имя пользователя, позвольте модели профиля работать за вас.
class Profile
belongs_to :user
# ...
def username
user.try(:username)
end
def username=(value)
self.user = User.find_by_username(value)
end
end
Тогда в твоей форме
<% form_for @profile do |f| %>
<%= f.text_field :username %>
<% end %>
При отправке значение для поля имени пользователя автоматически передается со всеми другими действительными атрибутами activerecord. ActiveRecord будет искать имя пользователя = setter и разрешит ассоциацию.
Если ассоциация возвращает nil (записи с данным именем пользователя не существует), тогда для текущего user_id будет установлено значение nil, и проверка завершится неудачно, как ожидалось.
Возможно, вы захотите настроить код ошибки, чтобы сделать его более значимым.
РЕДАКТИРОВАТЬ: Добавлен пример.
validate :ensure_username_exists
def username=(value)
self.user_id = User.find_by_username(value) || 0
end
protected
def ensure_username_exists
if user_id == 0 # nil is allowed
errors.add(:user_id, "Username doesn't exists")
return false
end
end