Rails:如何通过模型中的 id 通过关系创建 has_many?

Rails: How to create has_many through relationships via the ids in the model?

我有三个模型:CustomerBranchCustomerBranch

在客户模型中:

has_many :customer_branches, inverse_of: :customer
has_many :branches, through: :customer_branches

在分支模型中:

has_many :customer_branches, inverse_of: :branch, dependent: :restrict_with_exception
has_many :customers, through: :customer_branches

在 CustomerBranch 模型中:

belongs_to :customer, inverse_of: :customer_branches
belongs_to :branch, inverse_of: :customer_branches

这是一个仅 api 的应用程序,我将获得一组分支 ID。现在我想 assign/remove 根据收到的 ID 从客户那里分支。

我有一个解决方案来处理这个问题,但我认为这不是最好的方法。这是我目前的解决方案:

attr_accessor :branches_ids
after_save :assign_branches

def assign_branches
  return if self.branches_ids.nil?
  old_branch_ids = self.branch_ids

  remove_branch_ids = old_branch_ids - self.branches_ids

  self.customer_branches.where(id: remove_branch_ids).delete_all if remove_branch_ids.present?

  self.branches << Branch.where(id: self.branches_ids)
end

有没有更好的方法来处理这个问题?提前致谢!!

好了,回答问题。您可以直接在客户上设置 ID:

customer = Customer.find(1)
customer.branches_ids = [1,2,3]

Rails 将处理所有的添加和删除。

也适用于新客户:

customer = Customer.new
customer.name = "blabla"
customer.branches_ids = [1,2,3]
customer.save

您可以在控制器中执行此操作:

def assign_branches
  customer = Customer.find(params[:id]) // however you gonna get custome whom we gonna assign branches
  customer.branches = Branch.where(id: params[:branch_ids]) //however way you want to get ids
end

collection= 方法通过适当地添加和删除使集合仅包含提供的对象。修改持久化到database.For更多关于关联,可以通过:https://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference

Ubuntu 20.04[=29= 上构建 Rails 应用程序 时,我也有同样的担忧]

模型和控制器被命名为一个名为 Userbase 的模块:

用户模型

module Userbase
  class User < ApplicationRecord

    # Allow a user to have multiple permissions
    has_many :user_permissions, class_name: Userbase::UserPermission, dependent: :nullify
    has_many :permissions, through: :user_permissions

    # Allow a user to have multiple roles
    has_many :user_roles, class_name: Userbase::UserRole, dependent: :nullify
    has_many :roles, through: :user_roles
  end
end

榜样

module Userbase
  class Role < ApplicationRecord

    # Allow a role to have multiple users
    has_many :user_roles, class_name: Userbase::UserRole, dependent: :nullify
    has_many :users, through: :user_roles

    # Allow a role to have multiple permissions
    has_many :role_permissions, class_name: Userbase::Role, dependent: :nullify
    has_many :permissions, through: :role_permissions
  end
end

权限模型

module Userbase
  class Permission < ApplicationRecord

    # Allow a permission to have multiple users
    has_many :user_permissions, class_name: Userbase::UserPermission, dependent: :nullify
    has_many :users, through: :user_permissions

    # Allow a permission to have multiple roles
    has_many :role_permissions, class_name: Userbase::Role, dependent: :nullify
    has_many :roles, through: :role_permissions
  end
end

角色权限模型

module Userbase
  class RolePermission < ApplicationRecord
    belongs_to :role, class_name: Userbase::Role
    belongs_to :permission, class_name: Userbase::Permission
  end
end

用户权限模型

module Userbase
  class UserPermission < ApplicationRecord
    belongs_to :user, class_name: Userbase::User
    belongs_to :permission, class_name: Userbase::Permission
  end
end

用户角色模型

module Userbase
  class UserRole < ApplicationRecord
    belongs_to :user, class_name: Userbase::User
    belongs_to :role, class_name: Userbase::Role
  end
end

这是我的做法:

我在相应控制器的允许参数中添加了role_ids: []permission_ids: []user_ids: []

角色控制器

module Userbase
  module Api
    module V1
      class RolesController < ApplicationController
        before_action :set_role, only: %i[show update destroy]
        .
        .
        .
        private

        # Use callbacks to share common setup or constraints between actions.
        def set_role
          @role = Userbase::Role.find(params[:id])
        end

        # Only allow a trusted parameter "white list" through.
        def role_params
          params.require(:role).permit(:name, :description, user_ids: [], permission_ids: [] )
        end
      end
    end
  end
end

用户控制器

module Userbase
  module Api
    module V1
      class UsersController < ApplicationController
        before_action :set_user, only: %i[show update destroy]
        .
        .
        .
        private

        # Use callbacks to share common setup or constraints between actions.
        def set_user
          @role = Userbase::User.find(params[:id])
        end

        # Only allow a trusted parameter "white list" through.
        def role_params
          params.require(:user).permit(:name, :description, role_ids: [], permission_ids: [] )
        end
      end
    end
  end
end

权限控制器

module Userbase
  module Api
    module V1
      class PermissionsController < ApplicationController
        before_action :set_permission, only: %i[show update destroy]
        .
        .
        .
        private

        # Use callbacks to share common setup or constraints between actions.
        def set_permission
          @role = Userbase::Permission.find(params[:id])
        end

        # Only allow a trusted parameter "white list" through.
        def role_params
          params.require(:permission).permit(:name, :description, role_ids: [], user_ids: [] )
        end
      end
    end
  end
end

所以我现在可以创建权限 使用:

{
    "permission": {
        "name": "create_school",
        "description": "This is the permission to create schools"
    }
}

我们还可以创建角色 使用:

{
    "role": {
        "name": "Student",
        "description": "This is the role for students",
        "permission_ids": [1,2]
    }
}

我们还可以创建用户 使用:

{
    "user": {
        "first_name": "Kelvin",
        "middle_name": "Daniel",
        "last_name": "Wale",
        "email": "kelvin-wale@gmail.com",
        "password": "123456",
        "password_confirmation": "123456",
        "username": "kelvin-wale",
        "role_ids": [1],
        "permission_ids": [1,2]
    }
}

我还想在每次创建用户时创建一个默认角色,所以我向用户模型添加了以下方法和before_save回调:

用户模型

module Userbase
  class User < ApplicationRecord
    before_save :assign_default_role

    # Allow a user to have multiple permissions
    has_many :user_permissions, class_name: Userbase::UserPermission, dependent: :nullify
    has_many :permissions, through: :user_permissions

    # Allow a user to have multiple roles
    has_many :user_roles, class_name: Userbase::UserRole, dependent: :nullify
    has_many :roles, through: :user_roles
  end

  # Assign the student role by default to users
  def assign_default_role
    role = Userbase::Role.find_by(name: 'Student')
    self.role_ids = role.id
  end
end

注意:应先创建角色,或使用以下方法将其植入数据库:

Userbase::Role.delete_all

# Default role
puts 'Creating default role'
Userbase::Role.create([{ name: 'Student',
                         description: 'This is the role for students',
                         permission_ids: [1, 2] }])

就这些了。

希望对您有所帮助