update tutorial simple signup rails password learn ruby-on-rails

ruby on rails - tutorial - Acceda a current_user en el modelo



simple login ruby (6)

Tengo 3 tablas

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

Cuando un usuario dice "ABC" inicia sesión y crea un nuevo elemento, se crea un registro de historial con el siguiente filtro after_create. Cómo asignar este nombre de usuario ''ABC'' al campo de nombre de usuario en la tabla de historial a través de este filtro.

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

Mi método de inicio de sesión en 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

No estoy usando ningún plugin de autenticación. Agradecería que alguien me dijera cómo lograr esto sin usar un complemento (como userstamp, etc.) si es posible.


El controlador debe indicar la instancia del modelo

Trabajar con la base de datos es el trabajo del modelo. La gestión de las solicitudes web, incluido conocer al usuario para la solicitud actual, es el trabajo del controlador.

Por lo tanto, si una instancia modelo necesita conocer al usuario actual, un controlador debe contarla.

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

Esto supone que Item tiene un attr_accessor para current_user .


Carriles 5

Declarar un módulo

module Current thread_mattr_accessor :user end

Asignar el usuario actual

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

Ahora puede referirse al usuario actual como Current.user

Documentación sobre thread_mattr_accessor

Carriles 3,4

No es una práctica común acceder al current_user dentro de un modelo. Dicho esto, aquí hay una solución:

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

Establezca el atributo current_user en un around_filter de 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

Establezca el current_user después de la autenticación exitosa:

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

Por último, consulte current_user en 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


El truco del Thread no es seguro para los hilos, irónicamente.

Mi solución fue hacer retroceder la pila buscando un marco que responda a current_user . Si no se encuentra ninguno, devuelve nil. Ejemplo:

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

Podría hacerse más robusto confirmando el tipo de retorno esperado, y posiblemente confirmando que el propietario del marco es un tipo de controlador ...


Esto se puede hacer fácilmente en pocos pasos implementando Thread.

Paso 1:

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

Paso 2:

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

Ahora puede obtener fácilmente al usuario actual como User.current


Podrías escribir un filtro around_ en ApplicationController

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


Si el usuario crea un artículo, ¿no debería el artículo tener una cláusula belongs_to :user ? Esto le permitiría en su after_update hacer

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