前提
複数の条件に一致した時のデータを取得したいと考えています
検索条件は日付(date) AND グループid(group_id) AND 製品id(product_id)の三つです。
検索条件の三つの値をフォームに入力して検索しようとすると、
wrong number of arguments (given 0, expected 3)
という、エラーが出てしまいます。
これは、引数が渡せていないというエラーだということはわかっているのですが、検索の条件を満たす、引数を3つ渡した時だけ、given 0、となってしまいます。
試しに、渡す引数の数を一つや二つにすると、given 1,given 2となるので、引数は渡せていて、メソッドも呼び出されていると思うのですが(もちろんエラーは出ます)、引数を三つ渡した時だけエラーメッセージがgiven 0となり、検索できません。
searchメソッドの記述などを間違えているのでしょうか。それとも、引数の渡し方がおかしいのでしょうか。
DBには該当するデータは存在しています。
よろしくお願い致します。
発生している問題・エラーメッセージ
ArgumentError in Productions::SearchesController#search
wrong number of arguments (given 0, expected 3)
Extracted source (around line #8):
8 def self.search(date,line_id,product_id)
9 if search
10 Production.where
("(date = ?) AND (line_id = ?) AND (product_id = ?)", "%#{date}%", "%# {group_id}%", "%#{product_id}%")
11 redirect_to productions_searches_path
該当のソースコード
#route.rb
Rails.application.routes.draw do
root 'groups#index'
namespace :productions do
resources :searches, only: :index do
collection do
get 'search'
end
end
end
resources :groups do
resources :productions
end
end
#/controllers/productions/searches_controller.rb
class Productions::SearchesController < ApplicationController
def index
@production = Production.new
end
def search
#Productモデルのcodeカラムに情報を取りにいってます
product_id = Product.find_by(code: params[:production][:product_id]).id
@production = Production.search(params[:production][:date], params[:production][:group_id], product_id)
redirect_to search_productions_searches_path
end
end
#models/production.rb
class Production < ApplicationRecord
belongs_to :product
belongs_to :group
validates :date, presence: true
validates :product_id, presence: true
def self.search(date,group_id,product_id)
if search
Production.where
("(date = ?) AND (group_id = ?) AND (product_id = ?)", "%#{date}%", "%#{group_id}%", "%#{product_id}%")
else
redirect_to productions_searches_path
end
end
-# views/productions/searches/index.html
<%= form_for [@production], url: search_productions_searches_path do |f| %>
<div class="form__info__date">
<%= f.date_field :date %> #日付の入力
<%= f.number_field :products_id %> #productsのid(数字)を入力
<%= f.select :group_id, [["グループ1", 1],["グループ2", 2]] %> #グループidの入力
<%= f.submit '検索', class: "btn" %>
</div>
<% end %>
-# views/productions/searches/search.html
-# 検索結果の出力画面は仮です
<%= @production.date %>
<%= @production.group_id %>
<%= @production.product_id %>
試したこと
SearchesControllerのsearchメソッドを呼ぶ前でbinding pryして検索条件がきちんと入力されているか、確かめました。
#/controllers/productions/searches_controller.rb
def search
#Productモデルのcodeカラムに情報を取りにいってます
product_id = Product.find_by(code: params[:production][:product_id]).id
binding pry
@production = Production.search
(params[:production][:date], params[:production][:group_id], product_id)
end
[1] pry(#<Productions::SearchesController>)> product_id
=> 1
[2] pry(#<Productions::SearchesController>)> params[:production][:group_id]
=> "1"
[3] pry(#<Productions::SearchesController>)> params[:production][:date]
=> "2019-12-13"
この内容を見ると、値がnilにはなっていないとは思います。しかし、product_idがint型、group_idがstr型なのが気になりますが。
また、仮で、下記のようにsearchメソッドに直接数字などを渡してもやはり、三つ渡した時だけ、given 0となってしまいエラーになってしまいます。
#/controllers/productions/searches_controller.rb
@production = Production.search("2019-12-13", "1", "1")
@production = Production.search("2019-12-13", 1, 1)
実現したいこと
三つの条件を入力して、該当するデータを取得する
補足情報(FW/ツールのバージョンなど)
rails 5.0.7
ruby 2.5.1
追記
コメントで指摘を受けた部分を変更しました。
それに加えて、resultアクションを追加して、@production_resultに検索結果を挿入し、resultアクションで検索結果を表示させるようにしました。
しかし、@production_resultがnilになってしまい検索結果が表示されません。
どうもsearchメソッドを使用すると、@production_resultがから([])となってしまいます。
これは、検索結果がないということなのでしょうか?配列の中の値がnilとして返ってくるのならわかるのですが、配列自体が空になってしまいます。まだ、searchメソッドの記述がおかしいのでしょうか。
下記はsearchメソッドを使用した後、binding pryで確かめた結果です。
[1] pry(Production)> @production_result
=> nil
#route.rb
Rails.application.routes.draw do
root 'groups#index'
namespace :productions do
resources :searches, only: :index do
collection do
get 'search'
end
collection do
get 'result'
end
end
end
resources :groups do
resources :productions
end
end
#/controllers/productions/searches_controller.rb
def search
@production_result = Production.new
product_id = Product.find_by(code: params[:production][:product_id]).id
@production_result = Production.search(params[:production][:date], params[:production][:group_id], product_id)
redirect_to result_productions_searches_path(@production_result)
end
def result
end
def self.search(date,line_id,product_id)
if date and group_id and product_id
Production.where
("(date = ?) AND (group_id = ?) AND (product_id = ?)", "%#{date}%", "%#{group_id}%", "%#{product_id}%")
else
redirect_to productions_searches_path
end
end
-#views/productions/searches/result.html
検索結果
<%= @production_result.date %>
<%= @production_result.group_id %>
<%= @production_result.product_id %>
id | date | group_id | product_id |
---|---|---|---|
26 | 2019-12-13 00:00:00 | 1 | 1 |
試したこと
binding pryをしてみたところ、seaechメソッドをすると@production_resultが[]となってしまいます。
追記 part2
上記の状況から進展がありました。
@production_resultがnilになってしまうのはproduct_idの指定の仕方が間違えていたことによるものでした。
上の方にも書いた通り、product_idは他のテーブルに値を探しにいって変数product_idに入れて、searchメソッドに渡しています。その時にフォームから直接受け取ったgroup_idは"1"となっていたのに対し、product_idは 1 となっていました。そのため、そのまま、product_idを検索条件に入れてしまうと、条件に引っかからず、検索結果が0となり、@production_resulがnilになっているのでしたそこで下記のように、searchメソッドを書き直したところ、きちんと検索結果が、@production_resultに入ってくれました。
#production.rb
def self.search(date,line_id,product_id)
Production.where(date: date).
where(group_id: group_id).
where(product_id: "#{product_id}")
end
[1] pry(#<Productions::SearchesController>)> product_id
=> 1 #こっちはただの数字
[2] pry(#<Productions::SearchesController>)> params[:production][:group_id]
=> "1" #こっちはダブルクォーテーションで囲まれている
ただ、まだ検索結果のビューでは、@production_resulはnilclassになってしまいますね、、、。
うまく変数が渡せていないだけだと思うのですが、、、。
追記 part3
なんとか解決しました。
ビューの方の表記を変えたところきちんと検索結果が表示されました。
間違い
<%= @production_result.date %>
正解
<%= (@production_result.to_a)[0].date %>
また、asmさんのアドバイス通りwhereでなく、find_byを使えば@production_result.dateという形でも取り出せます。whereやfind_byの違いや原理を理解していないのがエラーにハマった原因でした。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
def self.search(date,group_id,product_id)
if search
Production.search
メソッドの再帰呼び出しになります。
このsearch
は何なのでしょうか?
Production.where
("(date = ?) AND (group_id = ?) AND (product_id = ?)", "%#{date}%", "%#{group_id}%", "%#{product_id}%")
Production.where()
("(date = ?) AND (group_id = ?) AND (product_id = ?)", "%#{date}%", "%#{group_id}%", "%#{product_id}%")
と解釈されます。
コメントに返信
redirect_to productions_searches_path
モデルのなかでredirect_toを使うのは避けた方がいいでしょう。
(そもそも使えないと思います。)
LIKE検索でもないのに%で囲む意味がよくわかりませんが
Production.where(date: date).
where(group_id: group_id).
where(product_id: product_id)
Production.where("(date = ?) AND (group_id = ?) AND (product_id = ?)",
date, group_id, product_id)
どっちでもよかったはずです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
アドバイスを沢山もらったので自己解決ではないですが、追記を繰り返して見辛いので、最終的なコードを示しておきたいと思います。
検索結果は基本的に複数件ヒットすることはないので、find_byを使うことにしました。
途中で作ったresultアクションは使わないので削除しました。
# routes.rb
Rails.application.routes.draw do
root 'groups#index'
namespace :productions do
resources :searches, only: :index do
collection do
get 'search'
end
end
end
resources :groups do
resources :productions
end
end
# models/production.rb
def self.search(date,group_id,product_id)
Production.find_by("(date = ?) AND (group_id = ?) AND (product_id = ?)",
date, group_id, product_id)
end
#searches_controller.rb
class Productions::SearchesController < ApplicationController
def index
@production = Production.new
end
def search
product_id = Product.find_by(code: params[:production][:product_id]).id
@production_result = Production.search(params[:production][:date], params[:production][:group_id], product_id)
end
end
#search.html
検索結果
<%= (@production_result.date %>
<%= (@production_result.group_id %>
<%= (@production_result.product_id %>
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.33%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/12/14 13:47
そこは記述するならsearchではなく、date and group_id and product_idですね。
三つの条件を満たす結果があれば、@productionに検索結果を挿入して、もし条件を満たす物がなかったら、検索ページ(searchのsearchアクション)を呼び出す、という風に記述したかったのでした。
よくわからないまま引用してきた結果です。
修正しておきます。
その部分を修正したら、取り敢えず今出てるエラーは解決しました。検索結果の表示はうまくいっていないですが、、、。
ありがとうございます。先に進めたので、がんばってみようと思います。
2019/12/14 14:37 編集
2019/12/14 16:55
指示通り修正してみたのですが、まだ
undefined method `date' for nil:NilClass
となってしまいますね、、、。
2019/12/14 21:14
検索結果を挿入した@production_resultの型が普通の配列と違ったようで、ビューの方で取り出し方を下記のように変えたら、きちんと表示されるようになりました。
ありがとうございました。助けてもらったので自己解決ではありませんが、追記などをしてゴチャゴチャになったので、解決方法を自己解決の欄にまとめたいと思います。
お世話になりました。
<%= (@production_result.to_a)[0].date %>
2019/12/14 21:19
whereをfind_byにした方がよさそうですね。
2019/12/14 21:29
@production_result.date
みたいな表記でできますね。find_byとwhereの違いを調べてみたのですがよくわかりません(笑)
find_byは一個しかデータを取ってこないが、whereだと、複数の行のデータが入っているから、きちんと何番目か指定してあげないと取り出せない、みたいな感じでしょうか。
長々とありがとうございました。お世話になりました。