我正在开发Rails 3中的应用程序,并且在注册时我需要用户输入他们的电子邮件地址,我需要它是唯一且区分大小写的。即当MyEmail@yahoo.com已经存在于数据库中时,没有人能够使用myEmail@yahoo.com注册。
这是我的代码,它崩溃了应用程序:
validates :email, :presence => true, :uniqueness => true, :case_sensitive => true,
:format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}
它出了什么问题?
答案 0 :(得分:39)
请不要使用区分大小写!!!它将获取所有用户!所以如果你有100.000个用户。首先,它将使用LOWER(电子邮件)获取所有内容。这可能非常慢,并且不会在电子邮件中使用您的索引。
这是我刚刚在这个主题上发现的一篇文章:http://techblog.floorplanner.com/post/20528527222/case-insensitive-validates-uniqueness-of-slowness
我的建议是:运行查询以使所有电子邮件降级,并使之前的验证过滤器对邮件属性进行包装,这样您就不会在该列中包含任何大写字符。
User.update_all('email = LOWER(email)')
过滤前:
before_validation :downcase_email
private
def downcase_email
self.email = email.downcase if email.present?
end
答案 1 :(得分:32)
对于Rails 3类型的验证,您需要嵌套不区分大小写的块,如此
validates :email, :uniqueness => { :case_sensitive => false }
答案 2 :(得分:3)
我没有对已接受的答案发表评论的声誉,但是@medBo询问了Rails 4中的行为。作为参考,当使用Rails 4.2 + MySQL时,如果我指定
validates :username, uniqueness: { case_sensitive: false }
ActiveRecord执行此查询:
SELECT 1 AS one FROM `users` WHERE `users`.`username` = 'TEST_USER' LIMIT 1
在这种情况下,搜索不区分大小写。但是当我设置:
validates :username, uniqueness: { case_sensitive: false }
执行:
SELECT 1 AS one FROM `users` WHERE `users`.`username` = BINARY 'TEST_USER'
BINARY
运算符ensures the search is case sensitive 没有获取所有用户,至少对于我的设置而言,case_sensitive标志不会遇到@Michael的性能问题Koper注意到早期版本的Rails。我无法评论ActiveRecord如何为其他数据库设置执行。
答案 3 :(得分:1)
我不确定是否可以使用该语法进行不区分大小写的验证(至少,我没有找到任何文档)。
你应该能够像这样验证不区分大小写的唯一性:
validates_uniqueness_of :email, :case_sensitive => false
如果没有关于崩溃的更多详细信息,我无能为力。
答案 4 :(得分:0)
你可以在你的模型中使用一个回调,比如 email 属性上的“before_validation”,让它像这样小写:
import math
import functools
import matplotlib.pyplot as plt
import numpy as np
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
bgcolor = '#252525'
slider_moved = 0
def moved_event(n, key):
global slider_moved
slider_moved = n
class Interface(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg=bgcolor)
# Framing of the window
self.l_frame = tk.Frame(self, bg=bgcolor)
self.l_frame.grid(column=0)
self.r_frame = tk.Frame(self, bg=bgcolor)
self.r_frame.grid(column=1)
self.graph1 = tk.Frame(self.r_frame, bg=bgcolor)
self.graph2 = tk.Frame(self.r_frame, bg=bgcolor)
self.slider_frame = []
self.label = []
self.entry = []
self.slider = []
self.elements = {"text": ["The initial body's semi-major axis", "The target body's semi-major axis", "The target body's period",
"The parent's gravitational parameter", "Delta-v to perform the transfer"],
"color": ["green", "#1f77b4", "white", "white", "orange"]}
for n in range(len(self.elements["text"])):
slider_frame = tk.Frame(self.l_frame, bg=bgcolor)
self.slider_frame.append(slider_frame)
slider_frame.grid(pady=5)
label = tk.Label(self.slider_frame[n], bg=bgcolor, text=self.elements["text"][n], font=("Arial", 10), fg='white')
self.label.append(label)
label.pack(anchor=tk.W)
entry = tk.Entry(self.slider_frame[n], relief='flat', bg='grey', fg='black', validate="key")
self.entry.append(entry)
entry.pack(fill=tk.X)
self.entry[n].bind("<Return>", functools.partial(self.set_slider, n))
slider = tk.Scale(self.slider_frame[n], sliderrelief='flat', length=600, from_=1E-5, to=20, resolution=1E-5, orient=tk.HORIZONTAL,
bd=0, highlightbackground=bgcolor, troughcolor=bgcolor, bg=self.elements["color"][n], sliderlength=40, showvalue=0,
activebackground=self.elements["color"][n], command=functools.partial(self.write, n))
self.slider.append(slider)
slider.pack()
self.slider[n].bind("<Button>", functools.partial(moved_event, n))
self.slider[0].set(10)
self.slider[1].set(5)
self.slider[2].set(2)
self.slider[1].config(to=40)
self.slider[2].config(to=4)
def write(self, slider_updated, value):
self.entry[slider_updated].delete(0, tk.END)
self.entry[slider_updated].insert(0, value)
if slider_updated == slider_moved:
if slider_updated == 0 or slider_updated == 2:
self.slider[1].config(to=self.slider[0].get() * 4)
self.slider[1].set(self.slider[0].get() / self.slider[2].get())
if slider_updated == 1:
self.slider[2].set(self.slider[0].get() / self.slider[1].get())
def set_slider(self, n, key):
self.slider[n].set(self.entry[n].get())
moved_event(n, key)
if __name__ == "__main__":
root = tk.Tk()
root.title("Transfer orbit calculator")
root.geometry("1280x720")
root.config(bg=bgcolor)
root.iconbitmap("956255-200.ico")
Interface(root).pack(expand=True)
root.mainloop()
这将使电子邮件输入小写,然后尝试不区分大小写的唯一性验证:
before_validation { self.email = email.downcase }
有关回调的更多信息:这里是 ruby 指南 https://guides.rubyonrails.org/active_record_callbacks.html