2014-10-24 4 views
0

В приложении Rails есть отношения между Продуктами и Категориими. Каждый продукт может иметь разные категории.Модель рельсов to_s

Я отображая категория продукта таким образом:

<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

Что вы хотите показать? Название продукта? –

+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

попытка сделать определить метод, как:

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

Нет никакой разницы между прохождением 'self' или нет. 'self' для читателей является неявным и избыточным в Ruby. –

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>" 

Но:

0

Я провел эксперимент, чтобы найти проблему, и я предлагаю вам посмотреть на результаты.

Это выход pry REPL.Это не совсем модель Rails, но она указывает на проблему.

Что я сделал: я определил новый класс и дал ему указание вывести имена af любых несуществующих методов, которые вызывают на нем. Это удобный трюк для определения неявных вызовов ваших классов.

[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, по-видимому, это называется.

Смежные вопросы