require 'ipaddr'
class User < ApplicationRecord
validates :ip_address, presence: true, format: { with: Resolv::IPv4::Regex, message: "must be a valid IP address" }
scope :from_same_network, ->(ip) {
where("ip_address <<= ?", IPAddr.new(ip).mask(24).to_s)
}
def update_ip(request)
update(ip_address: request.remote_ip)
end
end
class SessionsController < ApplicationController
def create
user = User.find_by(email: params[:email])
if user&.authenticate(params[:password])
user.update_ip(request) # Save the user's IP on login
session[:user_id] = user.id
redirect_to dashboard_path, notice: "Welcome back!"
else
flash.now[:alert] = "Invalid email or password"
render :new
end
end
end
class AddIpAddressToUsers < ActiveRecord::Migration[7.0]
def change
enable_extension 'citext' unless extension_enabled?('citext')
enable_extension 'inet' unless extension_enabled?('inet')
add_column :users, :ip_address, :inet, null: false, default: "0.0.0.0"
end
end
This snippet stores user IPs efficiently using the PostgreSQL inet
type, which optimizes space and lookup speed. The from_same_network
scope allows querying users within the same /24 subnet, useful for analytics or security checks. The update_ip method
simplifies updating the IP when users log in.
Martin Sojka, Maker of CodeSnips