将帐户和用户表与设计一起使用 [英] Use both Account and User tables with Devise

查看:29
本文介绍了将帐户和用户表与设计一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Rails 3.1.0 和 Devise 1.4.8,对这两个版本都是新手.

我想允许多个用户使用一个帐户.第一个注册的用户创建帐户(可能是为他们的公司),然后该用户可以添加更多用户.一个用户始终只与一个帐户相关联.

我有用户和帐户表.缩略模型:

class User :破坏attr_accessible :name, :account_type结尾

问题是,当第一个用户注册时,我该如何创建帐户和用户?

  • 我是否需要修改/覆盖设计注册控制器,类似于此处的答案?我不知道怎么做创建帐户,然后将其传递给 Devise 以创建用户.

  • account_id 已经在用户模型中.我应该添加 account_name和 account_type 到 User 模型,并创建一个新的 Account如果没有传入 account_id 则记录?在这种情况下,我试图从 Devise 隐藏帐户创建,但不确定这是否可行,因为我仍然需要在注册页面上提示输入 account_name 和 account_type.

解决方案

最终使用嵌套属性使其工作.正如对肯顿回答的评论中所讨论的那样,该示例被颠倒了.如果您希望每个帐户有多个用户,则必须先创建帐户,然后再创建用户——即使您一开始只创建一个用户.然后您编写自己的 Accounts 控制器和视图,绕过设计视图.如果您直接创建用户,发送确认电子邮件等的设计功能似乎仍然有效,即该功能必须是设计模型中自动功能的一部分;它不需要使用设计控制器.

摘自相关文件:

模型在应用/模型中

类帐号:account, :dependent =>:破坏accepts_nested_attributes_for :usersattr_accessible :name, :users_attributes结尾类用户:用户验证 :account, :presence =>真的设计 :database_authenticable, :registerable,:recoverable, :rememberable, :trackable, :validatable,:confirmable, :lockable, :timeoutableattr_accessible :email, :password, :password_confirmation, :remember_me结尾

spec/models/account_spec.rb RSpec 模型测试

它应该通过accepts_nested_attributes_for创建帐户和用户"做@AccountWithUser = { :name =>"用户测试帐户",:users_attributes =>[ { :email =>"user@example.com",:密码 =>"测试通过",:password_confirmation =>测试通过"}]}au = Account.create!(@AccountWithUser)au.id.should_not be_nilau.users[0].id.should_not be_nilau.users[0].account.should == auau.users[0].account_id.should == au.id结尾

config/routes.rb

 资源 :accounts, :only =>[:index, :new, :create, :destroy]

controllers/accounts_controller.rb

class AccountsController <应用控制器定义新@account = Account.new@account.users.build # 建立一个空白用户,否则子表单将不显示结尾定义创建@account = Account.new(params[:account])如果@account.saveflash[:success] = "帐户已创建"重定向到accounts_path别的呈现新"结尾结尾结尾

views/accounts/new.html.erb 视图

创建账户

<%= form_for(@account) 做 |f|%><%= 渲染 'shared/error_messages', :object =>f.对象%><div class="field"><%= f.label :name %><br/><%= f.text_field :name %>

<%= 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><%结束%><div class="actions"><%= f.submit "创建账户" %>

<%结束%>

Rails 对复数和单数非常挑剔.由于我们说帐户有_许多用户:

  • 它需要模型和测试中的 users_attributes(而不是 user_attributes)
  • 它需要一个 哈希数组用于测试,即使数组中只有一个元素,因此 {user attributes} 周围有 [].
  • 它期望在控制器中使用@account.users.build.我无法让 f.object.build_users 语法直接在视图中工作.

I'm working with Rails 3.1.0 and Devise 1.4.8, and am new to both.

I want to allow multiple users for an account. The first user to sign up creates the account (probably for their company), then that user can add more users. A user is always linked to exactly one account.

I have Users and Accounts tables. Abbreviated models:

class User < ActiveRecord::Base
  belongs_to :account
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable,
     :confirmable, :lockable, :timeoutable
  attr_accessible :email, :password, :password_confirmation, :remember_me
end

class Account < ActiveRecord::Base
  has_many :users, :dependent => :destroy
  attr_accessible :name, :account_type
end

The question is, when the first user signs up, how do I create both the Account and User?

  • Do I need to modify/override the Devise registrations_controller, something like the answer here? I couldn't figure out how to create the Account then pass it to Devise for creating the User.

  • account_id is already in the User model. Should I add account_name and account_type to the User model, and create a new the Account record if account_id is not passed in? In this case, I'm trying to hide Account creation from Devise, but not sure that will work since I still need to prompt for account_name and account_type on the registration page.

解决方案

Finally got this to work using nested attributes. As discussed in the comments on Kenton's answer, that example is reversed. If you want multiple users per account, you have to create the Account first, then the User--even if you only create one user to start with. Then you write your own Accounts controller and view, bypassing the Devise view. The Devise functionality for sending confirmation emails etc. still seems to work if you just create a user directly, i.e. that functionality must be part of automagical stuff in the Devise model; it doesn't require using the Devise controller.

Excerpts from the relevant files:

Models in app/models

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

spec/models/account_spec.rb RSpec model test

it "should create account AND user through accepts_nested_attributes_for" do
  @AccountWithUser = { :name => "Test Account with User", 
                       :users_attributes => [ { :email => "user@example.com", 
                                                :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]

controllers/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

views/accounts/new.html.erb view

<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 is quite picky about plural vs. singular. Since we say Account has_many Users:

  • it expects users_attributes (not user_attributes) in the model and tests
  • it expects an array of hashes for the test, even if there is only one element in the array, hence the [] around the {user attributes}.
  • it expects @account.users.build in the controller. I was not able to get the f.object.build_users syntax to work directly in the view.

这篇关于将帐户和用户表与设计一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆