質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

4回答

1978閲覧

SQL文をメソッドとして定義したい。

Naon

総合スコア6

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2019/10/31 00:58

SQL文をメソッドとして定義したい

SQL文をメソッドとして定義したいです。
そもそもそれが可能なのかわかりませんが、よろしくお願いいたします。
以下は、いいねのついた記事を多い順にデータベースから取り出す処理になります。
コントローラーに定義しています。

@like_trend_posts = Post.joins("left join likes on posts.id = likes.post_id") .group("posts.id").order(Arel.sql("count(likes.id) desc"))

上記の、次のSQL文をメソッドとして定義し、繰り返し使えるようにしたいです。

joins("left join likes on posts.id = likes.post_id") .group("posts.id").order(Arel.sql("count(likes.id) desc"))

試したこと

Postモデルに以下のように定義してみました。

def like_trend_sql joins("left join likes on posts.id = likes.post_id") .group("posts.id").order(Arel.sql("count(likes.id) desc")) end

コントローラーにも以下のように定義してみました。

private def like_trend_sql joins("left join likes on posts.id = likes.post_id") .group("posts.id").order(Arel.sql("count(likes.id) desc")) end

そして、コントローラーにて、下記のように書き換えて使用してみました。

@like_trend_posts = Post.like_trend_sql

結果、「like_trend_sql」メソッドは定義されていないとのエラーが出ました。
定義の仕方がそもそも合っているのかわかりません。
お分かりになられる方がいらっしゃるのであれば、ぜひご教授願います。よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

まずこの2点を理解する必要があります。

  • オブエジェクト志向におけるクラスメソッド、インスタンスメソッドの概念について理解する
  • Rubyにおいて、具体的なクラスメソッド、インスタンスメソッドの定義の仕方を理解する

細かくは説明しませんが、ざっくり言えば
Post.joinsは当然クラスメソッドを呼び出しているので、これと同じ事をしたいのであれば、
クラスメソッドとして定義しなければなりません。

インスタンスメソッド、クラスメソッドのざっくりした定義方法

とりあえずこういう風に単にモデルにメソッドを定義したら、インスタンスメソッドですよね。
なので、これはPost.new.method1という使い方になります。
もしくは、Post.find(1).method1など。

ruby

1class Post 2 3 def method1 4 end 5 6end

クラスメソッドは、こう書きます。

ruby

1class Post 2 3 def self.method1 4 end 5 6end

このようにすると、Post.method1と使うことができます。
つまり、Rubyにおいてクラスメソッドを定義するには、def self.メソッド名 ~ endと書きます。

本題

さて、これを踏まえて「試したこと」で書いてもらったコードを見れば、インスタンスメソッドだから
Post.like_trend_sqlという使い方が出来ない事が分かります。

ruby

1class Post 2 3 def like_trend_sql 4 joins("left join likes on posts.id = likes.post_id") 5 .group("posts.id").order(Arel.sql("count(likes.id) desc")) 6 end 7 8end

これをクラスメソッドにするには、self.をメソッド名の前に付けてやれば良いですね。

ruby

1class Post 2 3 def self.like_trend_sql 4 joins("left join likes on posts.id = likes.post_id") 5 .group("posts.id").order(Arel.sql("count(likes.id) desc")) 6 end 7 8end

これで、Post.like_trend_sqlという使い方ができるはずです。

投稿2019/10/31 01:11

mingos

総合スコア4025

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Naon

2019/10/31 01:22

ご回答ありがとうございます! とても丁寧な説明もありがとうございます。言われてみれば、selfがないとダメだなと感じました。 今一度、その部分について調べ直してみたいと思います。 問題も解決することができました! ベストアンサーにさせていただきたいと思います!
guest

0

メソッドを作る場合は、module として切り出すか、maisumakunさんが仰る通りselfを使ってclassメソッドにすれば良いと思います。

投稿2019/10/31 01:08

Yuinyan

総合スコア312

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

railsのバージョンとエラー内容がわからないので、間違っているかもしれませんが、
Postモデルに記載するだけでほかのところでも使用できるようになると思います。
記載方法ですが、

def like_trend_sql self.joins("left join likes on posts.id = likes.post_id") .group("posts.id").order(Arel.sql("count(likes.id) desc")) end

もしくは、

scope :like_trend_sql, ->{ joins("left join likes on posts.id = likes.post_id") .group("posts.id").order(Arel.sql("count(likes.id) desc")) }

こんな感じで
Post.like_trend_sql
で使えるかと。

投稿2019/10/31 01:07

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Naon

2019/10/31 01:17

コントローラーには記載しなくて良いのですね、、、。 勉強になります。ご回答ありがとうございます! 問題も解決することができました!
guest

0

Postモデルに以下のように定義してみました。

Post.like_trend_sqlの形で使いたいのであれば、クラスメソッドとして定義してください。

投稿2019/10/31 01:01

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Naon

2019/10/31 01:08 編集

ご回答ありがとうございます。 Postモデルに以下のように定義すれば良いということでしょうか? def self.like_trend_sql   joins("left join likes on posts.id = likes.post_id")  .group("posts.id").order(Arel.sql("count(likes.id) desc")) end
maisumakun

2019/10/31 01:10

そうですね、そんな感じです。
Naon

2019/10/31 01:16

ご教授ありがとうございます! 問題も解決することができました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問