将参数传递给函数的正确方法是什么?
例如:
def self.find_by_example(username, email)
user = User.find_by_username(username) || User.find_by_email(email)
end
我想通过他的username
或email
找到用户,但是如果创建一个传递2个参数Rails的函数显示
(错误的参数数量(给定1,预期2))
当我致电User.find_by_example('example')
我仍然没有得到它,传入的参数不能是属性? 为什么它会说"给出1"?
答案 0 :(得分:1)
您必须调用函数,如`User.find_by_example(" name to find"),函数需要两个参数(名称和电子邮件)。您可以将函数定义为:
def self.find_by_example(term)
user = User.find_by_username(term) || User.find_by_email(term)
end
并将其称为User.find_by_example("Name to find")
或User.find_by_example("email@to_find.com")
如果您的用户拥有类似电子邮件的用户名,则无效。如果您希望搜索其他字段,效率不高。所以你也可以:
def self.find_by_example(terms)
if terms[:email]
user = User.find_by_email(terms[:email])
elsif terms[:username]
user = User.find_by_username(terms[:username])
elsif terms[:id]
user = User.find_by_id(terms[:id])
elsif terms[:document]
user = User.find_by_document(terms[:document])
end
end
并调用方法User.find_by_example(:email => "email@example.com")
。这类似于Active Record已经提供的find_by
方法(但允许许多参数),因此无需实现它。
答案 1 :(得分:0)
建议和接受的答案实际上并不等同于问题中提到的代码。它被接受了,所以人们可能会认为它正确地猜测了OP的意图。但我认为(尤其是初级)程序员更深入地思考问题会很有用。
(不仅如果它立即给你你希望看到的结果,在边缘情况下会有惊喜)
原始代码
def self.find_by_example(username, email)
user = User.find_by_username(username) || User.find_by_email(email)
end
可以这样使用x.find_by_example(nil, 'test@example.com')
。
如果我们假设不存在具有NULL username
的用户(IMO是合理的假设),则调用将导致严格按email
查找用户。
建议的解决方案并没有给你这种可能性:
def self.find_by_example(term)
user = User.find_by_username(term) || User.find_by_email(term)
end
如果存在, x.find_by_example('test@example.com')
将返回具有此用户名的用户,否则将返回(可能是其他)具有此类电子邮件的用户。
换句话说 - 您控制哪个字段用于查找用户(这可能是正确的,如果这真的是您需要的那样)
所以这取决于OP意图。
如果想要保留原始方法的工作原理,但要改进界面,可以这样做:
def self.find_by_example2(username: nil, email: nil)
user = User.find_by_username(username) || User.find_by_email(email)
end
调用x.find_by_example2(email: 'test@example.com')
相当于x.find_by_example(nil, 'test@example.com')
,但看起来更好。
建议的解决方案
def self.find_by_example(term)
user = User.find_by_username(term) || User.find_by_email(term)
end
在username
找不到用户时进行第二次查询。如果你想使用一些sql魔法,你也可以改进它:
def self.find_by_example(term)
user = User.where("username = ? OR (username IS NULL and email = ?)", term, term).first
end
还有另一种可能性(尽管不是100%等同于已接受的解决方案):
def self.find_by_example(term)
user = User.where("username = ? OR email = ?", term, term).first
end
(我将把这些不同的答案留给练习,以保持这篇文章的简短......是的)
此
def self.find_by_example(terms)
if terms[:email]
user = User.find_by_email(terms[:email])
elsif terms[:username]
user = User.find_by_username(terms[:username])
elsif terms[:id]
user = User.find_by_id(terms[:id])
elsif terms[:document]
user = User.find_by_document(terms[:document])
end
end
浪费你的时间,因为rails为你提供了更好的界面。
而不是打电话
x.find_by_example(document: 'foo')
你可以做到
User.find_by(document: 'foo')
实际上没有必要以这种方式实现它,它基本上是ActiveRecord接口的残缺版本,您必须在向User
模型添加新字段时进行维护。