Accedi a current_user nel modello

Ho 3 tavoli

items (columns are: name , type) history(columns are: date, username, item_id) user(username, password) 

Quando un utente dice “ABC” accede e crea un nuovo elemento, viene creato un record della cronologia con il seguente filtro after_create. Come assegnare questo nome utente “ABC” al campo del nome utente nella tabella della cronologia tramite questo filtro.

 class Item Time.now, username=> ?) end end 

Il mio metodo di accesso in session_controller

 def login if request.post? user=User.authenticate(params[:username]) if user session[:user_id] =user.id redirect_to( :action=>'home') flash[:message] = "Successfully logged in " else flash[:notice] = "Incorrect user/password combination" redirect_to(:action=>"login") end end end 

Non sto usando alcun plugin di autenticazione. Sarei grato se qualcuno potesse dirmi come ottenere questo risultato senza utilizzare plugin (come userstamp ecc.) Se ansible.

Rails 5

Dichiarare un modulo

 module Current thread_mattr_accessor :user end 

Assegna l’utente corrente

 class ApplicationController < ActionController::Base around_action :set_current_user def set_current_user Current.user = current_user yield ensure # to address the thread variable leak issues in Puma/Thin webserver Current.user = nil end end 

Ora puoi fare riferimento all'utente corrente come Current.user

Documentazione su thread_mattr_accessor

Rotaie 3,4

Non è una pratica comune accedere a current_user all'interno di un modello. Detto questo, ecco una soluzione:

 class User < ActiveRecord::Base def self.current Thread.current[:current_user] end def self.current=(usr) Thread.current[:current_user] = usr end end 

Imposta l'attributo current_user in un around_filter di ApplicationController .

 class ApplicationController < ActionController::Base around_filter :set_current_user def set_current_user User.current = User.find_by_id(session[:user_id]) yield ensure # to address the thread variable leak issues in Puma/Thin webserver User.current = nil end end 

Imposta l'utente current_user dopo l'autenticazione riuscita:

 def login if User.current=User.authenticate(params[:username], params[:password]) session[:user_id] = User.current.id flash[:message] = "Successfully logged in " redirect_to( :action=>'home') else flash[:notice] = "Incorrect user/password combination" redirect_to(:action=>"login") end end 

Infine, update_history riferimento a current_user in update_history of Item .

 class Item < ActiveRecord::Base has_many :histories after_create :update_history def update_history histories.create(:date=>Time.now, :username=> User.current.username) end end 

Il controller dovrebbe comunicare l’istanza del modello

Lavorare con il database è il lavoro del modello. La gestione delle richieste Web, inclusa la conoscenza dell’utente per la richiesta corrente, è il lavoro del controllore.

Pertanto, se un’istanza del modello ha bisogno di conoscere l’utente corrente, un controllore dovrebbe dirlo.

 def create @item = Item.new @item.current_user = current_user # or whatever your controller method is ... end 

Questo presuppone che Item abbia un attr_accessor per current_user .

Se l’utente crea un elemento, l’elemento non dovrebbe avere una clausola belongs_to :user ? Questo ti permetterebbe di fare il tuo after_update

 History.create :username => self.user.username 

Puoi scrivere un around_filter in ApplicationController

 around_filter :apply_scope def apply_scope Document.where(:user_id => current_user.id).scoping do yield end 

Questo può essere fatto facilmente in pochi passi implementando Thread.

Passo 1:

 class User < ApplicationRecord def self.current Thread.current[:user] end def self.current=(user) Thread.current[:user] = user end end 

Passo 2:

 class ApplicationController < ActionController::Base before_filter :set_current_user def set_current_user User.current = current_user end end 

Ora puoi facilmente ottenere l'utente corrente come User.current

L’approccio Rails 5.2 per avere accesso globale all’utente e ad altri attributi è CurrentAttributes .

Il trucco del Thread non è infallibile, ironicamente.

La mia soluzione era quella di far marcia indietro la pila cercando un frame che rispondesse a current_user . Se nessuno viene trovato, restituisce zero. Esempio:

 def find_current_user (1..Kernel.caller.length).each do |n| RubyVM::DebugInspector.open do |i| current_user = eval "current_user rescue nil", i.frame_binding(n) return current_user unless current_user.nil? end end return nil end 

Potrebbe essere reso più robusto confermando il tipo di reso previsto e possibilmente confermando che il proprietario del frame è un tipo di controller …