#model #ruby-on-rails-3.1
#Модель #ruby-on-rails-3.1
Вопрос:
Я пытаюсь создать 3 вложенные модели одновременно, и у меня проблемы с моими проверками.
Это мои модели:
class UserEntity < ActiveRecord::Base
has_many :users, :dependent => :restrict, :autosave => true
end
class User < ActiveRecord::Base
has_many :user_login_services, :dependent => :destroy, :autosave => true
belongs_to :user_entity
end
class UserLoginService < ActiveRecord::Base
belongs_to :user
#validates :user_id, :presence => true
end
(UserEntity может быть компанией со многими пользователями. UserLoginService используется для служб Omniauth, таких как Facebook, OpenID и т. Д.)
Пользователи создаются с
def new_user_login(tokens)
user_entity = UserEntity.new
user = user_entity.users.build(:email => tokens[:email], :password => Devise.friendly_token[0,20], :first_name => tokens[:first_name], :last_name => tokens[:last_name], :has_local_password => false)
user.skip_confirmation!
user.user_login_services.build(:provider => tokens[:provider], :uid => tokens[:uid], :uname => tokens[:name], :uemail => tokens[:email])
user_entity.save!
user.confirm!
Этот код, похоже, работает нормально и создает соответствующие записи во всех 3 таблицах. Проблема возникает, когда я раскомментирую ‘validates :user_id, : presence => true’ в UserLoginService, что приводит меня
ActiveRecord::RecordInvalid (Validation failed: Users user login services user can't be blank):
app/controllers/users/omniauth_callbacks_controller.rb:86:in `new_user_login'
Обратите внимание, что код, похоже, работает нормально без проверки, а user_id в таблице user_login_services установлен в правильное значение.
Почему я получаю эту ошибку и как мне ее решить?
Ответ №1:
В двух словах:
в ваших моделях
class UserEntity < ActiveRecord::Base
has_many :users
accepts_nested_attributes_for :users
end
class User < ActiveRecord::Base
belongs_to :user_entity
has_many :user_login_services, :dependent => :destroy
accepts_nested_attributes_for :user_login_services
end
class UserLoginService < ActiveRecord::Base
belongs_to :user
validates :user_id, :presence => true
end
в ваших контроллерах
def create
@user_entity = UserEntity.new(params[:user_entity])
@user_entity.save
# To Do: handle redirections on error and success
end
и в вашей форме
<%= form_for(@user_entity) do |f| %>
<%= f.fields_for :users do |u| %>
<%= u.fields_for :user_login_services do |ul| %>
<%= ul.select :user_id, @user_entity.users.collect{|u| [u.name, u.id]} %>
<% end %>
<% end %>
<% end %>
Кроме того, я рекомендую вам проверить: http://railscasts.com/episodes/196-nested-model-form-part-1
Ответ №2:
Вам необходимо accepts_nested_attributes_for
inverse_of
определить отношения и.
class UserEntity < ActiveRecord::Base
has_many :users, :dependent => :restrict, :autosave => true, :inverse_of => :users_entity
accepts_nested_attributes_for :users
end
class User < ActiveRecord::Base
has_many :user_login_services, :dependent => :destroy, :autosave => true, :inverse_of => :user
belongs_to :user_entity, :inverse_of => :users
accepts_nested_attributes_for :user_login_services
end
class UserLoginService < ActiveRecord::Base
belongs_to :user, :inverse_of => :users_login_services
validates :user, :presence => true
end
Я также переключился validates :user_id
на validates :user
предположение, что вы хотите проверить существование связанного user
, а не только то, что UserLoginService
у user_id
него есть.
Комментарии:
1. Большое спасибо, указание inverse_of сделало это за меня! В противном случае при сохранении Rails сначала попытается сохранить вложенную модель (с вложенной моделью belongs_to top model), и это приведет к сбою, поскольку верхняя модель еще не создана.