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.
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
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
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 …