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

rewhereによるwhere条件の上書き(Railsガイド写経)

More than 3 years have passed since last update.

 Railsガイド書写による小ネタが続いております。本日は、8.5 rewhere です。

Article(記事)モデルを作ります。

Railsガイドとは異なるカラムですが、author(投稿者)とlikes_count(いいねの数)
というカラムを作っておきます。

[ykt68@macbook testapp]$ rails g model article author likes_count:integer
Running via Spring preloader in process 74847
Expected string default value for '--jbuilder'; got true (boolean)
      invoke  active_record
      create    db/migrate/20170225110425_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml
[ykt68@macbook testapp]$ rails db:migrate
== 20170225110425 CreateArticles: migrating ===================================
-- create_table(:articles)
   -> 0.0127s
== 20170225110425 CreateArticles: migrated (0.0128s) ==========================

rails console を立ち上げます。

[ykt68@macbook testapp]$ rails c
Running via Spring preloader in process 74971
Loading development environment (Rails 5.0.1)

100個のレコードを作成します。

likes_countには、1以上100以下の乱数を入れます。

irb(main):001:0> 100.times do |n|
irb(main):002:1*   Article.create author:sprintf('著者-%03d',n), likes_count:rand(0..100)
irb(main):003:1> end
   (0.2ms)  BEGIN
  SQL (0.5ms)  INSERT INTO `articles` (`author`, `likes_count`, `created_at`, `updated_at`) VALUES ('著者-000', 0, '2017-02-25 20:06:19', '2017-02-25 20:06:19')
   (0.6ms)  COMMIT
   (0.2ms)  BEGIN ・・・
・・・
  SQL (0.2ms)  INSERT INTO `articles` (`author`, `likes_count`, `created_at`, `updated_at`) VALUES ('著者-099', 48, '2017-02-25 20:06:20', '2017-02-25 20:06:20')
   (0.3ms)  COMMIT
=> 100

whereとrewhereを使ってみます。

likes_countが50のものを取得

irb(main):004:0> Article.where(likes_count: 50)
  Article Load (9.6ms)  SELECT `articles`.* FROM `articles` WHERE `articles`.`likes_count` = 50
=> #<ActiveRecord::Relation [#<Article id: 42, author: "著者-041", likes_count: 50, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 68, author: "著者-067", likes_count: 50, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 75, author: "著者-074", likes_count: 50, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">]>

で、クエリに rewhere(likes_count: 80)を付加してみると、

irb(main):005:0> Article.where(likes_count: 50).rewhere(likes_count: 80)
  Article Load (3.8ms)  SELECT `articles`.* FROM `articles` WHERE `articles`.`likes_count` = 80
=> #<ActiveRecord::Relation [#<Article id: 72, author: "著者-071", likes_count: 80, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">]>

なるほど。
articles.likes_count = 50が、articles.likes_count = 80
上書きされています。

では、次に、whereの条件を likes_count > 50 にして、

irb(main):006:0> Article.where('likes_count > 50')
  Article Load (11.4ms)  SELECT `articles`.* FROM `articles` WHERE (likes_count > 50)
=> #<ActiveRecord::Relation [#<Article id: 2, author: "著者-001", likes_count: 92, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 3, author: "著者-002", likes_count: 68, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 4, author: "著者-003", likes_count: 57, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 9, author: "著者-008", likes_count: 87, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 13, author: "著者-012", likes_count: 69, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 16, author: "著者-015", likes_count: 56, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 18, author: "著者-017", likes_count: 52, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 19, author: "著者-018", likes_count: 78, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 25, author: "著者-024", likes_count: 86, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, #<Article id: 26, author: "著者-025", likes_count: 98, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">, ...]>

としてから、
「きっと、likes_count > 50が、likes_count > 80になってくれるのだろう」
という想定のもと、rewhere('likes_count > 80')を付加して

irb(main):007:0> Article.where('likes_count > 50').rewhere('likes_count > 80')

としてみると、残念

NoMethodError: undefined method `keys' for "likes_count > 80":String
    from /Users/ykt68/.rbenv/versions/2.2.6/lib/ruby/gems/2.2.0/gems/activerecord-5.0.1/lib/active_record/relation/query_methods.rb:650:in `rewhere'
・・・

となりました。
エラーメッセージに、
「"likes_count > 80"は文字列で、keysメソッドが無いよ」
と怒られています。
それでは、rewhere('likes_count > 80') をrewhere(likes_count: 80)に戻してやれば、
WHERE句の中で、likes_count = 80 によって likes_count > 50 が上書きされるかと思きや、

irb(main):008:0> Article.where('likes_count > 50').rewhere(likes_count: 80)
  Article Load (7.2ms)  SELECT `articles`.* FROM `articles` WHERE (likes_count > 50) AND `articles`.`likes_count` = 80
=> #<ActiveRecord::Relation [#<Article id: 72, author: "著者-071", likes_count: 80, created_at: "2017-02-25 11:06:19", updated_at: "2017-02-25 11:06:19">]>
irb(main):009:0> 

と、エラーにはなりませんが、

WHERE (likes_count > 50) AND `articles`.`likes_count` = 80

というWHERE句が生成されています。
ムムッ(←川平慈英のモノマネをする博多華丸口調で)

そこで Rails APIで、rewhereを調べると、

This is short-hand for unscope(where: conditions.keys).where(conditions).

Note that unlike reorder, we're only unscoping the named conditions – not the entire where statement.

ということで、

only unscoping the named conditions – not the entire where statement.

だそうです。

が、全然ノープロですわ。
rewhere('likes_count > 80')でもいけちゃうrewhere欲しければ
自分で書けよって話だと思いますし、こちとら、ActiveRecord様のような
スゴイもの、タダで使わせてもらってる身空でございますしおすし。

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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした