Help us understand the problem. What is going on with this article?

railsで動的にscopeを設定したい

More than 1 year has passed since last update.

初めに

Railsでmodelにスコープを書くことがあるのですがスコープの数が多くなりすぎることがあります。

それで動的にスコープが定義出来たらと思って自分で試してみました。

具体例

具体的な例として記事に言語の設定があるとします。

モデルはこんな感じ

erdplus-diagram.png

そんでこのlangはinteger型でenumを使います

なのでmodels/article.rbには

article.rb
class DataCollect < ApplicationRecord
    enum lang: {ja: 0, en: 1, ar: 2, de: 3,el: 4, eo: 5, es: 6, fr: 7}
end

こんな感じに設定します

これでarticleを作成するときにlangを設定してあげれはその記事の言語がわかるようになります。

scopeを作成

scopeを作成するときに例えば

Article.ja.all

で日本語の記事がとれるようにするためにはmodels/article.rbに

scope :ja, -> {where(lang: :ja)}

とすれば実装できます。

しかし今回の例のように七個も言語があると

models/article.rbは

scope :ja, -> {where(lang: :ja)}
scope :en, -> {where(lang: :en)}
scope :ar, -> {where(lang: :ar)}
scope :de, -> {where(lang: :de)}
scope :el, -> {where(lang: :el)}
scope :eo, -> {where(lang: :eo)}
scope :es, -> {where(lang: :es)}

と書かなくてはいけなくて結構邪魔になります。

もっと増えたらもっと邪魔になるわけでこれをもっと短く書きたい!

class_evalを使ってみた

とりあえずclass_evalを使ってArticleのモデルにscopeを定義してみます。

使い方はこんな感じになりました。

Article.class_eval { scope ja, -> {where(lang: ja)}

これでscopeの設定ができるので後は配列を作ってループしたら出来上がり。

Lang = [ja, en, ar, de, el, eo, es, fr]

Lang.each do |l|
  Article.classs_eval { scope l, -> {where(lang: l)}
end 

これでOK

もう少しいじってみる

もう少しいじってみることにして言語のファイルがconfig/localesにあるのですがそのファイルを見てscopeを定義してみたいと思います。

どういうことかというと

例えばconfig/localesに

en.yml
ja.yml
en.yml

というファイルがあったらそれを見てen,ja,enというスコープを作るということです。

config/localesのファイル名を取得するために

Dir.chdir("/mnt/c/users/owner/desktop/app_name/config/locales")
lang = Dir.glob("*").map {|l| l.match(/../)[0] }

こうすればconfig/localesのファイル名が取得できます。

これでconfig/localesにある言語化ファイルがある言語のスコープを作成できました

完成全体像はこちらです。

class Article < ApplicationRecord
    enum lang: {ja: 0, en: 1, ar: 2, de: 3,el: 4, eo: 5, es: 6, fr: 7}
end




Dir.chdir("/mnt/c/users/owner/desktop/latest_news/config/locales")
lang = Dir.glob("*").map {|l| l.match(/../)[0] }

lang.each do |l|
    Article.class_eval { scope l, -> {where(lang: l)}}
end 

逆にわかりにくいですね(笑)

おわり

メリークリスマス:snowman:

sibakenY
大学卒業後Ruby, Ruby on Railsを勉強しています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away