多租户rails应用程序用户 - 帐户关系问题

时间:2014-06-20 07:36:00

标签: ruby-on-rails acts-as-tenant

我的应用主要宝石:rails 4.1.1pgacts_as_tenantdeviseactiveadmin

应用程序描述:具有子域的saas多租户应用程序(不使用postgresql架构) 我有2个模型:AccountUser

  • 帐户belongs_to :owner用户的class_name
  • 用户belongs_to :account以及acts_as_tenant(:account)

注意:如果使用acts_as_tenant,我不确定是否需要声明belongs_to?

在公共域(www.myapp.dev)上,用户可以创建一个新帐户并选择自己的子域。此用户具有此特定子域/帐户的“所有者”状态。创建帐户后,用户将被重定向到自定义子域以进行登录。登录后,所有者可以创建/邀请其他用户加入其帐户。

在创建帐户时,owner_id已正确保存到帐户记录中。在ActiveAdmin中,我可以按所有者过滤我的帐户。

问题是account_id未保存在用户记录中。同样在ActiveAdmin中,当我尝试编辑用户记录以添加帐户时,数据不会保存...

我正在学习Rails所以请轻松一下:)

我的帐户模型:

class Account < ActiveRecord::Base
  RESTRICTED_SUBDOMAINS = %w(www)
  belongs_to :owner, class_name: 'User'
  validates :owner, presence: true
  validates :name, presence: true
  validates :subdomain, presence: true,
                   uniqueness: { case_sensitive: false },
                   format: { with: /\A[\w\-]+\Z/i, message: 'contains invalid characters' },
                   exclusion: { in: RESTRICTED_SUBDOMAINS, message: 'restricted' }
  accepts_nested_attributes_for :owner
  before_validation :downcase_subdomain

  def self.current_id=(id)
    Thread.current[:account_id] = id
  end

  def self.current_id
    Thread.current[:account_id]
  end

  private
  def downcase_subdomain
    self.subdomain = subdomain.try(:downcase)
  end
end

我的用户模型:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable
  belongs_to :account       
  acts_as_tenant(:account)
  validates :lastname, presence: true, allow_nil: false
  validates :firstname, presence: true, allow_nil: false
  validates :password, presence: true, allow_nil: false
  validates :email, presence: true, allow_nil: false #uniqueness: true,

  def to_s
    "#{firstname} #{lastname} (#{email})"
  end       
end

应用程序控制器:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_filter :authenticate_user! #, :set_mailer_host
  before_filter :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:accept_invitation).concat([:firstname])
  end

  private
  def current_account
    @current_account ||= Account.find_by(subdomain: request.subdomain)
  end
  helper_method :current_account

  def after_sign_out_path_for(resource_or_scope)
    new_user_session_path
  end

  def after_invite_path_for(resource)
    users_path
  end
end

帐户管理员:

class AccountsController < ApplicationController
  skip_before_filter :authenticate_user!, only: [:new, :create]
  def new
    @account = Account.new
    @account.build_owner
  end

  def create
    @account = Account.new(account_params)
    if @account.valid?
      @account.save
      redirect_to new_user_session_url(subdomain: @account.subdomain)
    else
      render action: 'new'
    end
  end

private
  def account_params
    params.require(:account).permit(:subdomain, :name, owner_attributes: [:lastname, :firstname, :email, :password, :password_confirmation, :account_id])
  end
end

用户控制器:

class UsersController < ApplicationController
  def index
    @users = User.all
  end
end

我的数据库架构:

ActiveRecord::Schema.define(version: 20140619202210) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "accounts", force: true do |t|
    t.string   "name"
    t.string   "subdomain"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "owner_id"
  end

  create_table "active_admin_comments", force: true do |t|
    t.string   "namespace"
    t.text     "body"
    t.string   "resource_id",   null: false
    t.string   "resource_type", null: false
    t.integer  "author_id"
    t.string   "author_type"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "active_admin_comments", ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id", using: :btree
  add_index "active_admin_comments", ["namespace"], name: "index_active_admin_comments_on_namespace", using: :btree
  add_index "active_admin_comments", ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id", using: :btree

  create_table "admin_users", force: true do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "admin_users", ["email"], name: "index_admin_users_on_email", unique: true, using: :btree
  add_index "admin_users", ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true, using: :btree

  create_table "users", force: true do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "account_id"
    t.string   "lastname"
    t.string   "firstname"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree

end

1 个答案:

答案 0 :(得分:0)

尝试:

class Account < ActiveRecord::Base
  has_one :account
...

class User < ActiveRecord::Base
  acts_as_tenant(:account)
...

belongs_to模型没有User