updated on 2019-07-30
例えば、tagテーブルとarticlesテーブルが存在し、以下のような構造であったとする
(schema.rb)
ActiveRecord::Schema.define(version: xxxx_xx_xx) do ... create_table "tags", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "articles", force: :cascade do |t| t.string "title" t.text "body" t.datetime "created_at", null: false t.datetime "updated_at", null: false end ... end
(models/tag.rb)
class Tag < ApplicationRecord has_and_belongs_to_many :articles end
(models/article.rb)
class Article < ApplicationRecord has_and_belongs_to_many :tags end
viewのなかで、記事が多い順にタグを取得して表示したい。
そういうときは、こういう長い文になります。
<% Tag.select('tags.*', 'count(articles.id) AS acs').left_joins(:articles).group('tags.id').order('acs desc') do |tag| %> <li><a href=<%= manage_tag_path(id: tag.id) %>><%= tag.name %></a></li> <% end %>
もちろん、コントローラの中で
@tags=Tag.select('tags.*', 'count(articles.id) AS acs').left_joins(:articles).group('tags.id').order('acs desc')
としてから@tagsで渡してもいいですが、それだと他のコントローラで使うときに、また宣言をしないといけなくなります
models/tag.rbにクラスメソッドを追加
(models/tag.rb)
class Tag < ApplicationRecord has_and_belongs_to_many :articles # articleが多い順に全てのtagを取得している def self.popular_sort_tags Tag.select('tags.*', 'count(articles.id) AS acs').left_joins(:articles).group('tags.id').order('acs desc') end end
これで、いつでも
<% Tag.popular_sort_tags.each do |tag| %> <li><a href=<%= manage_tag_path(id: tag.id) %>><%= tag.name %></a></li> <% end %>
てやったり、
コントローラで
@tags=Tag.popular_sort_tags
として
<% @tags.each do |tag| %> <li><a href=<%= manage_tag_path(id: tag.id) %>><%= tag.name %></a></li> <% end %>
で、スマートにまとめることができる。
何回も使うものは定義は1回で済ませる努力をしよう!!