2017-11-17 28 views
0

私はRailsの新機能です。Rails 5を使用してDeviseとPunditの宝石を使った簡単な用語集アプリを作成しています。私はDeviseでAdminモデルを生成しました。それはログインする必要がある唯一の役割です。管理者としてログインしていない限り、「Edit」、「Destroy」、「New」ボタンを非表示にするポリシーを作成するためにPunditをインストールしました。 Glossary App IndexRails:管理者としてログインしていない限り、「編集」と「破棄」を非表示にします。

「編集」を隠し、ボタンを「破壊」するために私のindex.html.erbファイルに以下のポリシーコードを追加した後、私は「未定義のメソッド 『CURRENT_USER』」なエラーになっています。

<tbody> 
     <% @terms.each do |term| %> 
     <tr> 
      <td><%= term.name %></td> 
      <td><%= term.category %></td> 
      <td><%= term.definition %></td> 
      <td><%= link_to 'Show', term, class: 'btn btn-mini' %></td> 
      <td> 
      <% if policy(@term).edit? %> 
       <%= link_to 'Edit', edit_term_path(term), class: 'btn btn-mini' %> 
      <% end %> 
      </td> 
      <td> 
      <% if policy(@term).destroy? %> 
       <%= link_to 'Destroy', term, method: :delete, class: 'btn btn-mini', data: { confirm: 'Are you sure?' } %> 
      <% end %> 
      </td> 
     </tr> 
     <% end %> 
    </tbody> 

私が考案し、「ユーザー」モデルを生成し、代わりに「管理者」モデルを生成していなかったので、エラーが私の新しいポリシーで単語「ユーザー」に言及していたことを論理的に思えました。だから私は私のapplication_policy.rbとterms_policy.rbで "user"を "admin"に置き換えました。明らかに、私はまだそれを得ているので、このエラーで「ユーザー」が何を意味するのか理解していません。

私はあなたがそう、ここで、参照する必要が正確にわからないです、私のモデル、コントローラ、およびポリシー:

application_record.rb

class ApplicationRecord < ActiveRecord::Base 
    self.abstract_class = true 
end 

admin.rb

class Admin < ApplicationRecord 
    has_many :terms 
    # Include default devise modules. Others available are: 
    # :confirmable, :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :trackable, :timeoutable, :lockable 
end 

term.rb

class Term < ApplicationRecord 
    belongs_to :admin 

    def self.search(search) 
    if search 
     where(["name LIKE ?","%#{search}%"]) 
    else 
     all 
    end 
    end 

end 

application_controller.rb

class ApplicationController < ActionController::Base 
    include Pundit 
    protect_from_forgery with: :exception 
    before_action :set_current_user 

    def set_current_user 
    Term.current_user = current_user 
    end 
end 

terms_controller.rb

class TermsController < ApplicationController 
    before_action :set_term, only: [:show, :edit, :update, :destroy] 
    before_action :authenticate_admin!, :only => [:new, :edit, :create, :destroy] 

    # GET /terms 
    # GET /terms.json 
    def index 
    @terms = Term.search(params[:search]) 
    end 

    # GET /terms/1 
    # GET /terms/1.json 
    def show 
    end 

    # GET /terms/new 
    def new 
    @term = Term.new 
    end 

    # GET /terms/1/edit 
    def edit 
    @hide_edit_button = true 
    end 

    # POST /terms 
    # POST /terms.json 
    def create 
    @term = Term.new(term_params) 

    respond_to do |format| 
     if @term.save 
     format.html { redirect_to @term, notice: 'Term was successfully created.' } 
     format.json { render :show, status: :created, location: @term } 
     else 
     format.html { render :new } 
     format.json { render json: @term.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # PATCH/PUT /terms/1 
    # PATCH/PUT /terms/1.json 
    def update 
    respond_to do |format| 
     if @term.update(term_params) 
     format.html { redirect_to @term, notice: 'Term was successfully updated.' } 
     format.json { render :show, status: :ok, location: @term } 
     else 
     format.html { render :edit } 
     format.json { render json: @term.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # DELETE /terms/1 
    # DELETE /terms/1.json 
    def destroy 
    @term.destroy 
    respond_to do |format| 
     format.html { redirect_to terms_url, notice: 'Term was successfully destroyed.' } 
     format.json { head :no_content } 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_term 
     @term = Term.find(params[:id]) 
    end 

# Never trust parameters from the scary internet, only allow the white list through. 
def term_params 
    params.require(:term).permit(:name, :category, :definition) 
end 

def verify_is_admin 
     (current_admin.nil?) ? redirect_to(root_path) : 
(redirect_to(root_path) unless current_admin.admin?) 
    end 
end 

application_policy.rb

class ApplicationPolicy 
    attr_reader :admin, :record 

    def initialize(admin, record) 
    @admin = admin 
    @record = record 
    end 

    def index? 
    false 
    end 

    def show? 
    scope.where(:id => record.id).exists? 
    end 

    def create? 
    false 
    end 

    def new? 
    create? 
    end 

    def update? 
    false 
    end 

    def edit? 
    update? 
    end 

    def destroy? 
    false 
    end 

    def scope 
    Pundit.policy_scope!(admin, record.class) 
    end 

    class Scope 
    attr_reader :admin, :scope 

    def initialize(admin, scope) 
     @admin = admin 
     @scope = scope 
    end 

    def resolve 
     scope 
    end 
    end 
end 

terms_policy.rb

class TermPolicy < ApplicationPolicy 
    def index? 
    true 
    end 

    def create? 
    user.present? 
    end 

    def update? 
    return true if user.present? 
    end 

    def edit? 
    user.admin? 
    end 

    def destroy? 
    user.admin? 
    end 
end 

私はAccess to current_user from within a model in Ruby on Railsundefined local variable or method `current_user' using devise & rails 3.2https://code.tutsplus.com/tutorials/authorization-with-pundit--cms-28202からの提案を実装しようとした、および他のソースの片言てきました。これらはすべて素晴らしいリソースであると確信していますが、この段階では、私のプロジェクトとRailsに精通したレベルのものを少しは必要としています。

他に何ができるのか教えてください。ご協力いただきありがとうございます!

+0

[docs](https://github.com/plataformatec/devise#controller-filters-and-helpers)に基づいて 'current_admin'を使用する必要があると思います。あなたのdeviseモデルがUser以外のものであれば、 "_user"と "_yourmodel" _ – inye

+0

ありがとうございます。私はあなたがapplication_controller.rbを参照していると推測しているので、 "_user"を "_admin"に置き換えました。私が今得ているエラーは、 "定義済みメソッド' set_current_admin 'for#意味ですか?set_current_user " 私のterms_controllerでこのメソッドを定義する方法がわかりません。もし私が推測するなら、それは私的な方法でしょう: def set_current_admin end –

+0

あなたは 'aplication_controller.rb'で' set_current_user'を定義します。私はあなたが名前を変更する必要があると思います – inye

答えて

0

こんにちはあなたがそのあなたが助け=>

def ensure_admin 
    if current_user.nil? || current_user.is_at_least?(:manager) == false 
     flash[:notice] = I18n.t('must_be_admin') 
     redirect_to root_path 
     return true 
    end 
    false 
    end 

がホープス方法と

あなたのコントローラにいくつかの

before_action :ensure_admin, except: [:show, :edit, :update] 
    before_action :ensure_admin_or_user, only: [:edit, :update, :account] 

を追加しようとすることができます!

+0

ありがとうジョーダン。私はbefore_actionsを追加し、あなたが提案した方法でensure_adminメソッドを定義しました。そして、 'current_admin'が定義されていないというエラーが返されました。だから、私は_empty_'set_current_admin 'メソッドをapplication_controllerからterms_controller.rbに引き出しました。それは効果がなかったようです。 –

+0

「current_admin」ではなく「> current_user.admin」を試してみましたか? ex => current_user.admin == true?何かをする:他のことをする –

0

Punditはコントローラ内のcurrent_userを見てユーザーレコードを取得します。 pundit_userメソッドでconfigureこれを行うことができます。 application_controller.rbに上書きして管理レコードを返送してください。何が価値があるために

def pundit_user 
    Admin.find_however_you're_doing_that 
end 

あなたは追加のロール(非管理者ユーザー)を追加する場合、あなたはおそらくこれについて痛みを伴う道を進みました。おそらく、属性として定義されたロールを持つ単一のDeviseモデルが必要です。

+0

ダニエルありがとう。それは理にかなっており、あなたが提案したように 'application_controller.rb'を編集しました。私はまだ同じエラーが発生しています。どうやら私は実際にこのレールを外してしまったので、皆さんが提供してくれたこの情報を使って新しいアプリを作成すると、よりクリーンで簡単にトラブルシューティングを行うことができます。ユーザーの役割については、それが良い点です。 –

関連する問題