【问题标题】:Ruby on Rails - Scoping resources by current_accountRuby on Rails - 按 current_account 确定资源范围
【发布时间】:2017-01-25 09:56:05
【问题描述】:

我是 ruby​​ on rails 的新手,对于我正在构建的多租户应用程序中最好的下一步是什么感到有点困惑。

基本上我想通过 account_id 来确定资源的范围,所以我在我的 accounts base_controller 中创建了一个名为 current_account 的方法和助手。

但是,我正在关注的教程按子域划分 current_account 的范围,我不想这样做。所以我需要一种方法来识别当前用户的account_id,这样我就可以拥有一个资源变量@contact = current_account.contacts."all"。

我是否需要在用户和帐户模型之间建立新的关联,以便我可以使用 current_user 帮助器来定义当前帐户 ID,还是有更好的方法?如果是这样,最好的方法是什么?

背景 第一个注册的用户将成为帐户所有者。然后,帐户所有者可以邀请其他用户加入该帐户。我正在使用设计宝石。资源按帐户划分,因此只有与帐户关联的用户才能看到属于该帐户的记录。

基本控制器

module Accounts
  class BaseController < ApplicationController
    def current_account
      @current_account ||= ?????
    end
    helper_method :current_account

    def owner?
      current_account.owner == current_user
    end
    helper_method :owner?
  end
end

联系人(我的资源)控制器

module Accounts
  class ContactsController < Accounts::BaseController
    def index
        @contact = current_account.contacts.all
    end
  end
end

帐户模型

class Account < ActiveRecord::Base
  belongs_to :owner, class_name: "User"
  accepts_nested_attributes_for :owner

  validates :subdomain, presence: true, uniqueness: true

  has_many :contacts
  has_many :invitations
  has_many :memberships
  has_many :users, through: :memberships
end

邀请模型

class Invitation < ActiveRecord::Base
  belongs_to :account
  validates :email, presence: true
end

会员模式

class Membership < ActiveRecord::Base
  belongs_to :account
  belongs_to :user
end

用户模型

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable
end

路线

Rails.application.routes.draw do
  devise_for :users
  scope module: "accounts" do
  resources 'dashboard'
  resources 'contacts'
  resources :invitations, only: [:new, :create] do 
    member do
      get :accept
      patch :accepted
    end
  end
  resources :users, only: [:index, :destroy]
end

架构

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

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

  add_index "accounts", ["subdomain"], name: "index_accounts_on_subdomain"

  create_table "contacts", force: true do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "phone"
    t.string   "email"
    t.text     "comments"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "account_id"
  end

  add_index "contacts", ["account_id"], name: "index_contacts_on_account_id"

  create_table "invitations", force: true do |t|
    t.string   "email"
    t.integer  "account_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "token"
  end

  add_index "invitations", ["account_id"], name: "index_invitations_on_account_id"
  add_index "invitations", ["token"], name: "index_invitations_on_token"

  create_table "memberships", force: true do |t|
    t.integer  "account_id"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "memberships", ["account_id"], name: "index_memberships_on_account_id"
  add_index "memberships", ["user_id"], name: "index_memberships_on_user_id"

  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"
  end

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

end

【问题讨论】:

  • 你看过这颗宝石了吗? github.com/elabs/pundit 它使您能够为您的用户创建策略。我很确定你可以从那里拿走它。
  • 谢谢。看起来它对我有用。我现在要测试一下。

标签: ruby-on-rails rails-activerecord multi-tenant user-accounts


【解决方案1】:

用户和帐户之间有两种可能的关联:

  1. 用户有很多帐户
  2. 用户属于一个帐户

在第一种情况下,无法从 current_user 设置租户,因为不清楚应该将哪个帐户用作当前租户。 schema.rb 中的成员资格表表明这是您提到的教程所采用的方法。按子域加载帐户有助于指定应将哪个帐户用作当前租户。

在第二种情况下,每个用户只有一个帐户。用户获得一个 account_id,成员资格表已过时,您可以像这样加载当前租户:

def current_account
  @current_account ||= current_user.account
end

我是否需要在用户和帐户模型之间建立新的关联 这样我就可以使用 current_user 帮助器来定义当前 账户ID还是有更好的方法?如果是这样,最好的方法是什么 这个?

在我看来,您想采用第二种方法,这需要一个帐户 has_many 用户和一个用户 belongs_to 一个帐户。

【讨论】:

  • 在 Accounts Controller 中进行关联以便将 account_id 保存给每个新用户的最佳方法是什么?因为它还需要保持所有者关联,以便帐户的所有者拥有更高级别的访问权限,并在未来创建更多用户。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-25
  • 2011-04-13
相关资源
最近更新 更多