保护方法不会在关系上返回nil

时间:2015-03-07 19:59:40

标签: ruby-on-rails ruby tagging

class Recipe < ActiveRecord::Base
  def self.tagged_with(name)
    recipes = Tag.find_by(name: name).recipes
  end
end

在控制器中

def tag
  @recipes = Recipe.tagged_with(params[:tag])
  render 'index'
end

路线

get 'tag/:tag', to "recipes#tag"

如何保护此方法免受破坏?如果我搜索一个尚未创建的标记,我会得到一个noMethodError'recipes'代表nil:NilClass。我试过把

return false if recipes.nil?

以及

redirect_to(recipes_path) if recipes.nil?

在方法的最后但没有任何工作。

3 个答案:

答案 0 :(得分:1)

它会抛出该错误,因为当Tag#find_by返回的值为nil时,它无法在其上调用方法recipes。换句话说,nil没有recipes方法。

尝试先检查标签是否存在,例如:

class Recipe < ActiveRecord::Base
  def self.tagged_with(name)
    tag = Tag.find_by(name: name)
    recipes = tag.recipes unless tag.nil?
  end
end

我不知道您组织数据的方式,但更好的方法可能就是这样:

class Recipe < ActiveRecord::Base
  def self.tagged_with(name)
    Recipe.find_by(tag: name)
  end
end

答案 1 :(得分:0)

def self.tagged_with(name)
     tag = Tag.find_by(name: name)
     if !tag.nil?
        recipes = tag.recipes 
     else
        return false
     end

end

在控制器中:

def tag
 @recipes = Recipe.tagged_with(params[:tag]) 
 if @recipes != false
  render 'index'
 else
  redirect_to root_path
 end
end

答案 2 :(得分:0)

您看到NoMethodError,因为您在NilClass上调用方法recipiesfind_by方法返回nil如果找不到任何内容(顺便说一句,find会引发异常,{ {1}}返回空关系) 所以,首先你要做的是使用where: `

try

class Recipe < ActiveRecord::Base def self.tagged_with(name) recipes = Tag.find_by(name: name).try(:recipes) end end 将默默返回try 但是,您可以使用nil更好的方法(假设您有scope关系):

`

tags

或许,您可能希望在结果关系上调用class Recipe < ActiveRecord::Base has_many :tags scope :tagged_with, ->(name) { joins(:tags).where(tags: { name: name }) } end 或者不在范围等中使用uniq