Rails模型to_s方法

时间:2014-10-24 13:22:58

标签: ruby-on-rails ruby-on-rails-4

在我的Rails应用程序中,产品和类别之间定义了关系。每种产品可以有不同的类别。

我正在以这种方式展示产品类别:

<p>
    <strong>Categories:</strong>
    <%= @product.categories.join(", ") unless @product.categories.nil? %>
</p>

我的Category型号:

class Category < ActiveRecord::Base
    def to_s
        @name
    end
end

但是,在展示页面中,类别显示如下:

Categories: #<Category:0x007f2bf515b148>, #<Category:0x007f2bf515aef0>, #<Category:0x007f2bf515ac98>

为什么to_s方法不起作用?我该如何解决这个问题?

4 个答案:

答案 0 :(得分:1)

@product.categories的结果是ActiveRecord::Relation,而不是数组。因此,方法join是在关系类中实现的方法,而不是Array#join

您应该隐式地将列表转换为数组

<%= @product.categories.to_a.join(", ") unless @product.categories.nil? %>

或者您应该多关注一下您真正需要的东西,避免加载整个对象并获得更有效的结果。

<%= @product.categories.pluck(:name).join(", ") unless @product.categories.nil? %>

值得一提的是,您可以使用to_sentence方法。

<%= @product.categories.pluck(:name).to_sentence unless @product.categories.nil? %>

此外,.nil?检查完全没用,因为@product.categories是一种关系,永远不会是零。

如果你真的想编写更好的代码,你就可以避免在视图中实现你的逻辑,而你依赖于帮助者和模型。

class Product
  def category_names
    categories.pluck(:name)
  end
end

module ProductsHelper
  def product_categories_list(product)
    product.category_names.to_sentence
  end
end

<%= product_categories_list(@product) %>

答案 1 :(得分:0)

尝试定义类似的方法:

class Category < ActiveRecord::Base
    def to_s
        self.name
    end
end

答案 2 :(得分:0)

要访问您的属性,如果它是表中的列,则不应使用@attr_name,因为它们不会存储为实例变量。

尝试重新定义您的to_s方法,如下所示:

class Category < ActiveRecord::Base
  def to_s
    name
  end
end

这种行为非常有趣:

class Role < ActiveRecord::Base
  def to_s
    nil
  end
end

然后

"#{Role.first}"
 => "#<Role:0x00000007a39f88>"

可是:

Role.first.to_s
=> nil

答案 3 :(得分:0)

我已经进行了一项实验来找出问题,我建议您查看结果。

这是pry REPL的输出。它不是一个Rails模型,但它指出了问题。

我做了什么:我定义了一个新类,并指示它输出任何在其上调用的不存在的方法的名称。这是确定类的隐式调用的一个方便技巧。

[1] pry(main)> class Hi
[1] pry(main)*   def method_missing(sym)
[1] pry(main)*     puts sym
[1] pry(main)*   end  
[1] pry(main)* end  
=> :method_missing
[2] pry(main)> a = [Hi.new, Hi.new]
=> [#<Hi:0x0000000405b028>, #<Hi:0x0000000405afd8>]
[3] pry(main)> a.join
to_str
to_str
to_ary
to_str
to_ary
=> "#<Hi:0x0000000405b028>#<Hi:0x0000000405afd8>"

不是to_s。显然,to_str被称为。{/ p>