在我的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
方法不起作用?我该如何解决这个问题?
答案 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>