【发布时间】:2016-07-08 16:17:31
【问题描述】:
我有一个项目和一个关系模型来在用户和项目之间建立“跟随”关系。我在关系模型中使用枚举为“关系”建立了三个角色……它们是管理员、协作者和访问者。但是,我需要根据建立用户和项目之间关系的方式来设置默认角色。需要以下简单场景:
(a) 创建项目的用户会自动关注该项目...在创建项目时,应将关系角色设置为“管理员”
(b) 如果网站的访问者只是导航到项目资料页面,他们可以单击“关注”按钮建立关注关系...但是这应该将关系角色设置为“访问者”
关系模型:
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "Project"
validates :follower_id, presence: true
validates :followed_id, presence: true
enum role: [:admin, :collaborator, :visitor]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :admin
end
end
关系控制器:
class RelationshipsController < ApplicationController
before_filter :authenticate_user!
def create
@project = Project.find(params[:relationship][:followed_id])
current_user.follow!(@project)
# relationship.visitor! View railsapps documentation for devise pundit#roles
redirect_to @project
end
def destroy
@project = Project.find(params[:id]).followed
current_user.unfollow!(@project)
redirect_to @project
end
private
def relationship_params
params.require(:relationship).permit(:followed_id, :follower_id)
end
项目控制器
class ProjectsController < ApplicationController
before_filter :authenticate_user!, only: [:create, :new, :edit, :update, :delete, :followers]
def create
@project = current_user.own_projects.build(project_params)
if @project.save
if params[:project][:projectimage].present?
render :crop
else
flash[:success] = "You've successfully created a project..."
redirect_to @project
end
else
render 'new'
end
end
def update
@project = Project.find(params[:id])
if @project.update_attributes(project_params)
if params[:project][:projectimage].present?
render :crop
else
flash[:success] = "Project Created"
redirect_to @project
@project.followers << current_user #this establishes the following relationship as soon as a new project is created between user/project
end
else
render 'edit'
end
end
end
用户模型:
class User < ActiveRecord::Base
has_many :own_projects, :class_name=>'Project'
has_many :projects
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_projects, through: :relationships, source: :followed
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
def following?(some_project)
relationships.find_by_followed_id(some_project.id)
end
def follow!(some_project)
self.relationships.create!(followed_id: some_project.id)
relationship.visitor!
end
end
为了根据上述两种情况将默认角色设置为“管理员”或“访客”,我需要在代码中进行哪些更改?
【问题讨论】:
-
在创建新的
Relationship时为什么不简单地指定role?如果在不同条件下(关系外部)不同,为什么还要使用默认值? -
是的,我就是这个意思。您基本上可以在创建关系的任何位置设置相关的
role,例如在User中的follow!方法中:self.relationships.create!(followed_id: some_project.id, role: :visitor),或在控制器中。 -
一个原因可能是
role的基础表列不是整数。它不能是字符串列,而是整数,因为枚举值会自动从符号(字符串)映射到整数。 -
嗯,我不知道这里...我只是测试了我自己的简单枚举,它按我上面所说的那样工作。您能否将类似的
validatespresence添加到role的关系模型中,然后查看是否创建了记录? -
啊哈,我想我开始看到导致您在关系模型中使用默认值的问题。
Project和User之间实际上存在has_many :through关系!并且 AFAIK,您不能通过简单地使用<<添加到集合来设置其他属性。您必须手动创建关系,参见例如this post 了解如何做到这一点。
标签: ruby-on-rails ruby-on-rails-4 enums roles pundit