2011-11-29 32 views
19

Tôi đang làm việc với Rails 3.1.0 và Devise 1.4.8 và mới sử dụng cả hai.Sử dụng cả bảng Tài khoản và Người dùng với Devise

Tôi muốn cho phép nhiều người dùng cho một tài khoản. Người dùng đầu tiên đăng ký tạo tài khoản (có thể là cho công ty của họ), sau đó người dùng đó có thể thêm nhiều người dùng hơn. Người dùng luôn được liên kết với chính xác một tài khoản.

Tôi có bảng Người dùng và tài khoản. Các kiểu viết tắt:

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 

Câu hỏi đặt ra là khi người dùng đầu tiên đăng ký, làm cách nào để tạo cả Tài khoản và Người dùng?

  • Tôi có cần phải sửa đổi/ghi đè registrations_controller lập mưu, một cái gì đó giống như câu trả lời here? Tôi không thể tìm ra cách để tạo Tài khoản rồi chuyển nó cho Devise để tạo Người dùng.

  • account_id đã có trong Mô hình người dùng. Tôi có nên thêm account_name và account_type vào mô hình Người dùng và tạo một bản ghi Tài khoản mới nếu account_id không được chuyển vào? Trong trường hợp này, tôi đang cố gắng ẩn Tạo tài khoản từ Devise, nhưng không chắc chắn rằng nó sẽ làm việc vì tôi vẫn cần phải nhắc cho account_name và account_type trên trang đăng ký.

Trả lời

23

Cuối cùng, hãy làm việc này bằng cách sử dụng các thuộc tính lồng nhau. Như đã thảo luận trong các ý kiến ​​về câu trả lời của Kenton, ví dụ đó được đảo ngược. Nếu bạn muốn nhiều người dùng cho mỗi tài khoản, trước tiên bạn phải tạo Tài khoản, sau đó là Người dùng - ngay cả khi bạn chỉ tạo một người dùng để bắt đầu. Sau đó, bạn viết trình điều khiển và chế độ xem Tài khoản của riêng mình, bỏ qua chế độ xem Devise. Chức năng Devise để gửi email xác nhận, v.v. dường như vẫn hoạt động nếu bạn chỉ tạo trực tiếp người dùng, tức làchức năng đó phải là một phần của công cụ tự động hóa trong mô hình Devise; nó không yêu cầu sử dụng bộ điều khiển Devise.

Trích từ các tập tin liên quan:

Models trong ứng dụng/mô hình

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 

đặc tả/mô hình/account_spec.rb RSpec mô hình thử nghiệm

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] 

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/tài khoản/new.html.erb xem

<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 là khá kén chọn về số nhiều so với số ít. Kể từ khi chúng ta nói Người dùng has_many tài khoản:

  • dự kiến ​​users_attributes (không user_attributes) trong mô hình và thử nghiệm
  • nó hy vọng một mảng của băm cho kỳ thi này, ngay cả khi chỉ có một phần tử trong mảng , do đó [] xung quanh {thuộc tính người dùng}.
  • dự kiến ​​@ account.users.build trong bộ điều khiển. Tôi đã không thể nhận được cú pháp f.object.build_users để làm việc trực tiếp trong khung nhìn.
+0

là chế độ xem "new.html.erb" (ví dụ: app/views/devise/registrations/new.html.erb)? – y0mbo

+0

@ y0mbo, no, new.html.erb đang ở chế độ xem/tài khoản. Tôi đã thêm đường dẫn vào câu trả lời để làm rõ. Xem thêm đoạn đầu tiên về "bỏ qua chế độ xem Devise" và cách hoạt động. Về cơ bản tôi đang sử dụng tài khoản # tạo hành động để tạo cả tài khoản và người dùng, vì vậy tôi không cần chế độ xem Devise. –

+0

Cảm ơn! Đây là một câu trả lời tuyệt vời và giải pháp rõ ràng. – y0mbo

1

Không thể bạn sử dụng một cái gì đó giống như những gì được đề cập trong những RailsCasts ?:

http://railscasts.com/episodes/196-nested-model-form-part-1

http://railscasts.com/episodes/197-nested-model-form-part-2

Bạn có thể thiết lập mô hình của bạn như được mô tả trong những Screencasts, sử dụng accepts_nested_attributes_for.

Sau đó, biểu mẫu/lượt xem/đăng ký/new.html.erb của bạn sẽ dành cho: người dùng như bình thường và có thể bao gồm biểu mẫu lồng nhau cho: tài khoản.

Vì vậy, một cái gì đó như thế này trong đó hình thức mặc định:

<%= f.fields_for :account do |account_form| %> 
<div> 
    <p> 
    <%= account_form.label :name, "Account Name", :class => "label" %> 
    <%= account_form.text_field :name, :class => "text_field" %> 
    <span class="description">(e.g., enter your account name here)</span> 
    </p> 
</div> 

<div> 
    <p> 
    <%= account_form.label :company, "Company Name", :class => "label" %> 
    <%= account_form.text_field :company, :class => "text_field" %> 
    </p> 
</div> 
<% end %> 

này được mẫu mã từ một ứng dụng tôi đang làm việc trên và tôi đang sử dụng viên ngọc simple_form, vì vậy những người giúp đỡ sử dụng trong ứng dụng của bạn có thể khác nhau, nhưng có thể bạn sẽ có ý tưởng.

Vì vậy, khi người dùng được tạo (khi họ đăng ký), họ cũng có thể điền thông tin sẽ được mô hình Tài khoản sử dụng để tạo tài khoản của họ sau khi họ nhấn nút "Đăng ký".

Và bạn có thể muốn đặt thuộc tính trên người dùng đó như "quản trị viên" ... âm thanh như người dùng ban đầu này sẽ là người dùng "quản trị" cho công ty, mặc dù người dùng khác cũng có thể có quyền truy cập.

Hy vọng điều đó sẽ hữu ích.

+0

Cảm ơn Kenton, rất hữu ích. Có vẻ như điều này vẫn sẽ yêu cầu ghi đè hành động 'create' trong Devise registrations_controller để xây dựng bản ghi Tài khoản. Cf. '@ survey.questions.build' khoảng 5 phút vào màn hình đầu tiên. Hoặc có thể mẫu đăng ký phải dành cho Tài khoản, nhưng cũng gọi hành động 'Tạo' của người dùng Devise. Re. một thuộc tính admin, bạn nói đúng, nhưng tôi nghĩ tôi nên làm việc này trước khi tôi lo lắng về vai trò. –

+0

Đánh dấu, vui vì điều đó đã giúp ích. Có vẻ như chúng tôi đang làm một cái gì đó tương tự. Ứng dụng của tôi có chức năng tương tự. Khi xem lại mã của tôi, tôi đã có một tài khoản # hành động mới và chế độ xem được liên kết nơi biểu mẫu đăng ký. Trong biểu mẫu đó, tôi tạo một tài khoản bằng form_for và trong biểu mẫu đó, có các thiết lập cho: website và: user, tương tự như những gì được hiển thị trong railscast. Tôi đoán là khi người dùng lồng nhau đó được tạo ra, nó sẽ được tạo ra và đó là biểu mẫu đăng ký, nhưng tôi thực sự không chắc chắn 100% về điều đó. –

+0

Vì vậy, để làm rõ, bạn có 'accept_nested_attributes_for: user' trong mô hình Tài khoản và tài khoản của bạn # new view gọi' f.fields_for: user do | user_form | '? Nói cách khác, bạn đang tạo tài khoản trước, sau đó người dùng là cấp dưới. Tôi đã thử nó theo cách khác mà không thành công - có vẻ như accept_nested_attributes_for phải nằm trên bảng _parent_.Một tài khoản có thể nói, "thêm tôi, sau đó thêm một số người dùng cho tôi"; người dùng không thể nói "thêm tài khoản chính trước khi thêm tôi". Thảo luận có liên quan trong nhóm Google Devise: https://groups.google.com/d/topic/plataformatec-devise/7J3XB_RiHYs/discussion. –

Các vấn đề liên quan