Ruby传递参数

时间:2018-02-21 22:36:12

标签: ruby-on-rails ruby

将参数传递给函数的正确方法是什么?

例如:

 def self.find_by_example(username, email)
   user = User.find_by_username(username) || User.find_by_email(email)
 end

我想通过他的usernameemail找到用户,但是如果创建一个传递2个参数Rails的函数显示

  

(错误的参数数量(给定1,预期2))

当我致电User.find_by_example('example')

我仍然没有得到它,传入的参数不能是属性? 为什么它会说"给出1"?

2 个答案:

答案 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

(我将把这些不同的答案留给练习,以保持这篇文章的简短......是的)

奖金2:灵活性

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模型添加新字段时进行维护。