2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-02-25

 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様のような
スゴイもの、タダで使わせてもらってる身空でございますしおすし。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?