Finalmente, esto funcionó utilizando atributos anidados. Como se discutió en los comentarios sobre la respuesta de Kenton, ese ejemplo se invierte. Si desea varios usuarios por cuenta, primero debe crear la Cuenta y luego el Usuario, incluso si solo crea un usuario para comenzar. Luego, escribe su propio controlador y vista de Cuentas, sin pasar por la vista Devise. La funcionalidad Diseñar para enviar correos electrónicos de confirmación, etc. parece funcionar aún si solo crea un usuario directamente, es deciresa funcionalidad debe ser parte de las cosas automági- cas en el modelo ; no requiere el uso del controlador Devise.
extractos de los archivos relevantes:
Modelos en app/modelos
class Account < ActiveRecord::Base
has_many :users, :inverse_of => :account, :dependent => :destroy
accepts_nested_attributes_for :users
attr_accessible :name, :users_attributes
end
class User < ActiveRecord::Base
belongs_to :account, :inverse_of => :users
validates :account, :presence => true
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable
attr_accessible :email, :password, :password_confirmation, :remember_me
end
especificación/modelos/account_spec.rb prueba de modelo RSpec
it "should create account AND user through accepts_nested_attributes_for" do
@AccountWithUser = { :name => "Test Account with User",
:users_attributes => [ { :email => "[email protected]",
:password => "testpass",
:password_confirmation => "testpass" } ] }
au = Account.create!(@AccountWithUser)
au.id.should_not be_nil
au.users[0].id.should_not be_nil
au.users[0].account.should == au
au.users[0].account_id.should == au.id
end
config/routes.rb
resources :accounts, :only => [:index, :new, :create, :destroy]
controladores/accounts_controller.rb
class AccountsController < ApplicationController
def new
@account = Account.new
@account.users.build # build a blank user or the child form won't display
end
def create
@account = Account.new(params[:account])
if @account.save
flash[:success] = "Account created"
redirect_to accounts_path
else
render 'new'
end
end
end
vistas/cuentas/new.html.erb vista
<h2>Create Account</h2>
<%= form_for(@account) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<%= f.fields_for :users do |user_form| %>
<div class="field"><%= user_form.label :email %><br />
<%= user_form.email_field :email %></div>
<div class="field"><%= user_form.label :password %><br />
<%= user_form.password_field :password %></div>
<div class="field"><%= user_form.label :password_confirmation %><br />
<%= user_form.password_field :password_confirmation %></div>
<% end %>
<div class="actions">
<%= f.submit "Create account" %>
</div>
<% end %>
Rails es bastante exigente con plural vs. singular. Como nos dicen los usuarios has_many cuenta:
- que espera users_attributes (no user_attributes) en el modelo y las pruebas
- se espera una matriz de hashes para la prueba, incluso si sólo hay un elemento de la matriz , de ahí el [] alrededor de los {atributos del usuario}.
- espera @ account.users.build en el controlador. No pude obtener la sintaxis f.object.build_users para que funcione directamente en la vista.
es "new.html.erb" una vista de diseño (por ejemplo, app/views/devise/registrations/new.html.erb)? – y0mbo
@ y0mbo, no, new.html.erb está en vistas/cuentas. He agregado caminos a la respuesta para aclararme. Ver también el primer párrafo sobre "pasar por alto la vista de Devise" y cómo funciona eso. Básicamente estoy usando las cuentas # create action para crear tanto una cuenta como un usuario, por lo que no necesito la vista Devise. –
Gracias! Esta es una gran respuesta y una solución clara. – y0mbo