私のアプリケーションの主な宝石: rails 4.1.1
、pg
、acts_as_tenant
、devise
およびactiveadmin
.
アプリケーションの説明: サブドメインを持つ saas マルチテナント アプリ (postgresql スキーマを使用しない)。
私は2つのモデルを持っています:Account
そしてUser
:
belongs_to :owner
User の class_name をアカウントに入れる- ユーザー
belongs_to :account
とまたacts_as_tenant(:account)
注:acts_as_tenant を使用している場合、begs_to を宣言する必要があるかどうかわかりません。
パブリック ドメイン (www.myapp.dev) では、ユーザーは新しいアカウントを作成し、独自のサブドメインを選択できます。このユーザーは、この特定のサブドメイン/アカウントの「所有者」のステータスを持っています。アカウントの作成後、ユーザーはサインインのためにカスタム サブドメインにリダイレクトされます。サインインすると、所有者は他のユーザーを作成/招待して自分のアカウントに参加させることができます。
アカウントの作成時に、owner_id がアカウント レコードに正しく保存されます。ActiveAdmin では、アカウントを所有者別にフィルターできます。
問題は、account_id がユーザー レコードに保存されていないことです。また、ActiveAdmin で、ユーザー レコードを編集してアカウントを追加しようとすると、データが保存されません…</p>
私は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