index
アクションで @income_values
に値をセットしていますが,ビューでは
if @income_value.present?
となっていて,変数名が違う(複数形と単数形)のが原因かな。
現在家計簿アプリを作成中です。
エラーは出てないのですが、入力した投稿の一覧が見れません。
saveできたときに「登録しました」という文字を出すようにしていますが、その文字は出てきます。
実際の画面です。
1枚目が入力ページ、
2枚目が一覧ページです。
こんな感じで「登録しました」と出てくるためセーブされているはずが、一覧に表示されません。
関係ありそうな箇所のコードがこちらです。
<% require 'active_support/core_ext/numeric/conversions' %>
<h2>収入科目の新規データ登録</h2>
<p>登録年月を設定してください</p>
<%= form_tag({controller: :income_values, action: :new}, {method: :post}) do %>
<input type="month" name="year_month">
<input type="submit">
<% end %>
<h2>収入科目 データ一覧 </h2>
<% if @income_value.present? %>
<table>
<tr>
<th>登録年月</th>
<th>名称</th>
<th>値</th>
<th>備考</th>
<th>操作</th>
</tr>
<% @income_values.each do |income_value| %>
<tr>
<td><%= income_value.year_month.strftime('%Y年%m月') %></td>
<td><%= @incomes.find(income_value.income_id).name %></td>
<td><%= income_value.value.to_s(:delimited) %> 円</td>
<td><%= income_value.description %></td>
<td><%= link_to "編集", [:edit, income_value] %> | <%= link_to "削除", income_value, method: :delete, data: { confirm: "本当に削除しますか?"} %></td>
</tr>
<% end %>
</table>
<% else %>
<p>登録されているデータがありません。</p>
<% end %>
class IncomeValuesController < ApplicationController
def index
@incomes = Income.order(created_at: :asc)
@income_values = IncomeValue.order("year_month asc")
end
def show
@income_value = IncomeValue.find(params[:id])
end
def new
year_month_day = params[:year_month] + "-01"
@year_month = year_month_day.to_date
@incomes = Income.order(created_at: :asc)
@form = Form::IncomeForm.new
end
def edit
@income_value = IncomeValue.find(params[:id])
@income = Income.find(@income_value.income_id)
end
def create
@form = Form::IncomeForm.new(income_form_params)
if @form.save
redirect_to :income_values, notice: "登録しました"
else
redirect_to :income_values, notice: "登録に失敗しました"
end
end
def income_form_params
params
.require(:form_income_form)
.permit(income_values_attributes: Form::IncomeValue::REGISTRABLE_ATTRIBUTES)
end
def update
@income_value = IncomeValue.find(params[:id])
@income_value.assign_attributes(params[:income_value])
if @income_value.save
redirect_to :income_values, notice: "情報を更新しました"
else
インターンへ向けてのポートフォリオ作成中なのですが
ここで詰まってしまい、2日ほど試行錯誤してお手上げ状態です、、、
プログラミング初心者で質問も初めてなので至らない点が多いと思います、すみません
もしよろしければ、ご教授の程よろしくお願いします。
※補足です
ご回答いただいたように
<% if @income_value.present? %>
を
<% if @income_values.present? %>
としましたところ、
このようなエラーが出てしまいました。
SQLの方に問題があるということでしょうか?
もし、エラーの原因がお分かりでしたら
ご教授願いたいです🤲
さらに補足です
ご回答いただいた通りにやったところ、このようなエラーが出ました。
これはなんだかよく見るエラーです。
NillClassにstrftimeなんていうメソッドはない
ということで、
調べながら色々と手を動かしてみましたが、このエラーからもなかなか抜け出せません。
もし、エラーの原因がお分かりでしたら
ご教授願いたいです🤲
index
アクションで @income_values
に値をセットしていますが,ビューでは
if @income_value.present?
となっていて,変数名が違う(複数形と単数形)のが原因かな。
@studio15 さん
そうですね,私の勘違いでした。
レコードが 1 件以上あるかどうかを確認するのは,元のコードのとおり
@income_values.present?
で OK ですね。勉強になりました。
@Shota_U さん,混乱させてしまってすみません。
以下,調べて分かったことを少し説明します。
私が早とちりした理由は,
IncomeValue.order("year_month asc")
の返り値は配列とかではなく IncomeValue::ActiveRecord_Relation
(ActiveRecord::Relation
のサブクラス)のインスタンスであることでした。
しかし,ActiveRecord::Relation
には empty?
メソッドが実装されていました。これで,レコードが 0 件かどうかを判定します。present?
は,この empty?
に基づいて動作します。だから present?
でいいんですね。
なお,
nil, “”, “ “(半角スペースのみ), 空の配列, 空のハッシュのときにfalseを返します
は不正確です(このサイトは誤りを指摘しようにも連絡先が分からないんですよね)。
String 以外は empty?
があればそれに基づきますし,String では半角スペースのほか,改行・タブ・全角スペースなどなどが入っていても blank?
は真になります。
<% if @income_value.present? %>
を
<% if @income_values.present? %>
に変更でどうでしょう。
「登録しました」と出てくるためセーブされているはずが
データが保存されているかどうかはビューにどう表示されているかより、Railsサーバーのログや、SQLのテーブルのデータ自体を参照したほうが確実なので、そちらも見てみると良いかもしれません。
【追記:このコメントは誤りでした。この下のコメント参照】
なお,変数名を揃えた場合,
@income_values.present?
は(レコードが 1 件も無くても)常に真となって,意図と違う判定になるのではないかと思います。
IncomeValue
モデルのレコードが 1 件以上存在することを確認するなら
@income_values.count > 0
かな。
Qiita の質問て,回答が時系列順位並ばないので「下のコメント」とか書くとワケわからなくなるんですね。
さて,ActiveRecord::StatementInvalid in IncomeValues#index の件ですが,order
の指定の仕方が怪しい気がします。
ここから先は rails console でやっていきましょう。そのほうが早いと思います。
rails console 上で,
IncomeValue.order("year_month asc")
と打ってみてください。
先に進む前にちょっと説明ですが,上記のコードだけでは,実際には検索は行われません。先に書いたようにこのコードは IncomeValue::ActiveRecord_Relation
のインスタンスを返すだけだからです。
ところが,rails console 上で上記のコードを実行させると,IncomeValue::ActiveRecord_Relation
を文字列化しようとして(表示するためには文字列化する必要がありますね!),その際に検索が実行される仕様になっています。
おそらく ActiveRecord::StatementInvalid
が出るでしょう。
繰り返しますが,エラーが出るのは IncomeValue.order("year_month asc")
を評価した時点ではなく,それを文字列化しようとして検索が行われるタイミングです。
こういうとき,どんな SQL で検索を行おうとしたのか確認します。それには,rails console 上で
IncomeValue.order("year_month asc").to_sql
とします。
こうすると,IncomeValue::ActiveRecord_Relation
オブジェクトから生成される SQL 文が端末に表示されます。
さて,推測ですが,order
の引数が "year_month asc"
なのが怪しいと思いました。
asc(昇順)はデフォルトなので省略してもよく,
IncomeValue.order("year_month")
とか
IncomeValue.order(:year_month)
とか書けば目的がかなうはずです。
もしこれでエラーが出なくなるなら,やはり引数の与え方ですね。
これらを to_sql
して何が違うのかを調べてみましょう。
さて,降順に並べたい場合や,昇順だけどどうしてもあらわに asc を指定したい場合はどう書くか。
ふつうは
IncomeValue.order(year_month: "asc")
のようにハッシュ形式で引数を与えると思います。
これも to_sql
してみて,どう違うかを確認してみましょう。
結果を教えてくださいね。
@Shota_U
Questioner@Shota_U
Questioner@Shota_U
Questioner@Shota_U
Questioner@Shota_U
Questioner