[英]Rails model to_s method
In my Rails application there is a relationship defined between Products and Categories. 在我的Rails应用程序中,在“产品”和“类别”之间定义了一种关系。 Each product can have different categories.
每个产品可以具有不同的类别。
I am displaying the product's category this way: 我以这种方式显示产品的类别:
<p>
<strong>Categories:</strong>
<%= @product.categories.join(", ") unless @product.categories.nil? %>
</p>
And my Category
model: 和我的
Category
模型:
class Category < ActiveRecord::Base
def to_s
@name
end
end
However, in the show page, the categories are displayed like this: 但是,在显示页面中,类别显示如下:
Categories: #<Category:0x007f2bf515b148>, #<Category:0x007f2bf515aef0>, #<Category:0x007f2bf515ac98>
Why is the to_s
method not working? 为什么
to_s
方法不起作用? How can I solve this? 我该如何解决?
The result of @product.categories
is an ActiveRecord::Relation
, not an array. @product.categories
的结果是ActiveRecord::Relation
,而不是数组。 Therefore the method join
is the one implemented inside the relation class, not the Array#join
. 因此,
join
方法是在关系类内部实现的方法,而不是Array#join
。
You should implicitly cast the list to array 您应该将列表隐式转换为数组
<%= @product.categories.to_a.join(", ") unless @product.categories.nil? %>
or you should pay a little bit more attention of what you really need, avoid loading the entire objects and obtain a more efficient result. 否则您应该更加注意自己的实际需求,避免加载整个对象并获得更有效的结果。
<%= @product.categories.pluck(:name).join(", ") unless @product.categories.nil? %>
It is worth mentioning you can use the to_sentence
method. 值得一提的是您可以使用
to_sentence
方法。
<%= @product.categories.pluck(:name).to_sentence unless @product.categories.nil? %>
Moreover, the .nil?
此外,
.nil?
check is completely useless because @product.categories
is a relation and will never be nil. 检查是完全没有用的,因为
@product.categories
是一个关系,永远不会为零。
And if you really want to write better code, you avoid implementing your logic in the view and you rely on helpers and models. 而且,如果您确实想编写更好的代码,则可以避免在视图中实现逻辑,而要依赖于助手和模型。
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) %>
try do define method like: 尝试做如下定义方法:
class Category < ActiveRecord::Base
def to_s
self.name
end
end
To access your attribute, if it is a column in your table, you should not use the @attr_name, as they are not stored as instance variables. 要访问属性(如果它是表中的一列),则不应使用@attr_name,因为它们不会存储为实例变量。
Try just to redefine your to_s
method like following: 尝试仅重新定义您的
to_s
方法,如下所示:
class Category < ActiveRecord::Base
def to_s
name
end
end
It is really interesting the way this behaves: 这种行为的方式非常有趣:
class Role < ActiveRecord::Base
def to_s
nil
end
end
Then 然后
"#{Role.first}"
=> "#<Role:0x00000007a39f88>"
But: 但:
Role.first.to_s
=> nil
I have conducted an experiment to locate the problem and I suggest you look at results. 我已经进行了一项实验来找出问题所在,建议您查看结果。
This is output of a pry
REPL. 这是
pry
REPL的输出。 It's not quite a Rails model but it points out the issue. 它不是一个Rails模型,但指出了这个问题。
What I did: I defined a new class and instructed it to output the names af any non-existent methods that are called on it. 我做了什么:我定义了一个新类,并指示它在所有不存在的方法上输出名称。 This is a handy trick to determine implicit calls on your classes.
这是确定类上隐式调用的便捷技巧。
[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>"
It's not to_s
. 不是
to_s
。 It's to_str
, apparently, that is called. 显然是
to_str
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.