我试图在Rails 4中制作一个应用程序.
我试图用政治家宝石为国家,然后权威的政策.
我的gemfile有:
gem 'statesman','~> 1.3','>= 1.3.1' gem 'pundit'
我有一个文章模型和一个文章转换模型和一个article_state_machine模型.
我的目标是在我的文章政策中定义一个发布政策(使用专家),允许拥有文章的用户发布该文章,如果它处于“已批准”状态.
我在我的专家文章政策中试图这样做:
class ArticlePolicy < ApplicationPolicy def publish? user.present? && user == article.user # if requires approval,then approved # and article.in_state(:approve) - why doesnt this work - see statesman docs? # user && user.article.exists?(article.id) end end
当我尝试检查文章是否处于状态:approve(如上面注释的),我收到一条错误消息,说明未定义的方法’in_state’.
在策略中如何使用状态机?或者是意图该策略允许用户随时发布,但是当文章处于状态批准时,您只会在文章显示页面上显示按钮(尽管我认为这是专家点).
Article.rb
class Article < ActiveRecord::Base include Statesman::Adapters::ActiveRecordQueries has_many :transitions,class_name: "ArticleTransition",autosave: false def state_machine @state_machine ||= ArticleStateMachine.new(self,transition_class: ArticleTransition,association_name: :transitions) end # delegate :can_transition_to?. :trans # def reindex_articles # article.reindex_async # end private def self.transition_name :transitions end def self.transition_class ArticleTransition end def self.initial_state # ArticleTransition.initial_state :draft end end
文章状态机型号:
class ArticleStateMachine include Statesman::Machine state :draft,initial: :true #while author is drafting state :review #while approver comments are being addressed (really still in draft) state :reject # not suitable for publication state :approve # suitable for publication state :publish #published state :remove # destroyed # state :spotlight transition from: :draft,to: [:reject,:approve,:publish,:remove] # transition from: :review,to: [:rejected,:approved,:removed] transition from: :reject,to: [:draft,:remove] transition from: :approve,to: [:publish,:remove] transition from: :publish,to: :remove end
文章转换模式:
class ArticleTransition < ActiveRecord::Base include Statesman::Adapters::ActiveRecordTransition belongs_to :article,inverse_of: :article_transitions end
文章控制人:
def approve article = Article.find(params[:id]) if article.state_machine.transition_to!(:approve) flash[:notice] = "This article has been approved for publication" redirect_to action: :show,id: article_id # add mailer to send message to article owner that article has been approved else flash[:error] = "You're not able to approve this article" redirect_to action: :show,id: article_id end end def publish article = Article.find(params[:id]) authorize @article if article.state_machine.transition_to!(:publish) redirect_to action: :show,id: article_id # how do you catch the date the state became published? else flash[:error] = "You're not able to publish this article" redirect_to action: :show,id: article_id end end
谁能看到我做错了什么?
整篇文章控制器有:
class ArticlesController < ApplicationController before_action :set_article,only: [:show,:edit,:update,:destroy,:reject,:remove] before_action :authenticate_user!,except: [:index,:show,:search,:remove] respond_to :html,:json # GET /articles # GET /articles.json def index @articles = policy_scope(Article) # query = params[:query].presence || "*" # @articles = Article.search(query) end # def index # if params[:query].present? # @books = Book.search(params[:query],page: params[:page]) # else # @books = Book.all.page params[:page] # end # end # GET /articles/1 # GET /articles/1.json def show end # GET /articles/new def new @article = Article.new @article.comments.build end # GET /articles/1/edit def edit authorize @article end # POST /articles # POST /articles.json def create # before_action :authenticate_user! # authorize @article @article = current_user.articles.new(article_params) respond_to do |format| if @article.save format.html { redirect_to(@article) } format.json { render :show,status: :created,location: @article } else format.html { render :new } format.json { render json: @article.errors,status: :unprocessable_entity } end end end def search if params[:search].present? @articless = Article.search(params[:search]) else @articles = Articles.all end end # PATCH/PUT /articles/1 # PATCH/PUT /articles/1.json def update # before_action :authenticate_user! authorize @article respond_to do |format| # if @article.update(article_params) # format.json { render :show,status: :ok,location: @article } # else # format.html { render :edit } # format.json { render json: @article.errors,status: :unprocessable_entity } # end # end if @article.update(article_params) format.html { redirect_to(@article) } format.json { render :show,location: @article } else format.json { render json: @article.errors,status: :unprocessable_entity } end format.html { render :edit } end end # DELETE /articles/1 # DELETE /articles/1.json def destroy before_action :authenticate_user! authorize @article @article.destroy respond_to do |format| format.json { head :no_content } end end # def review # article = Article.find(params[:id]) # if article.state_machine.transition_to!(:review) # flash[:notice] = "Comments on this article have been made for your review" # redirect_to action: :show,id: article_id # else # flash[:error] = "You're not able to review this article" # redirect_to action: :show,id: article_id # end # end def reject end def approve article = Article.find(params[:id]) if article.state_machine.transition_to!(:approve) flash[:notice] = "This article has been approved for publication" redirect_to action: :show,id: article_id end end def publish article = Article.find(params[:id]) if article.state_machine.transition_to!(:publish) redirect_to action: :show,id: article_id end end def remove article = Article.find(params[:id]) if article.state_machine.transition_to!(:remove) redirect_to root_path else flash[:error] = "You're not able to destroy this article" redirect_to action: :show,id: article_id end end private # Use callbacks to share common setup or constraints between actions. def set_article @article = Article.find(params[:id]) authorize @article end # Never trust parameters from the scary internet,only allow the white list through. def article_params params.require(:article).permit(:body,:title,:image,:tag_list,comment_attributes: [:opinion]) end end