質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

4回答

407閲覧

rails on Ruby:modelで判断した情報を表示したい。

Amkys

総合スコア17

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

2クリップ

投稿2019/07/09 06:29

編集2019/07/16 05:20

前提・実現したいこと

CSVファイルを読み込み、DB登録するのですがvalidationでは複雑になるので
model側で、登録可否を判断しています。
そのmodelの判断で不整合と判断した情報を、viewで表示したい。

modelで、不整合と判断した情報を、オブジェクトに追加するコーディングが分かりません。

どのようにmodel → controller → view 表示できるでしょうか?

該当のソースコード

controller

def import if params[:file].blank? flash[:danger] = 'Import failure. CSV file is not selected' redirect_to statuses_path else add_cnt, update_cnt, error_cnt, @statuses = List.tss_import(params[:file]) if error_cnt > 0 then flash.now[:alert] = "Import result to tool_list<br/>          ---> Import_error = #{error_cnt.to_s}".html_safe render template: "statuses/import_result", collection: @statuses else flash.now[:notice] = "Import result to tool_list<br/>             ---> Added = #{add_cnt.to_s}<br/>      ---> Updated = #{update_cnt.to_s}".html_safe redirect_to lists_path end end end

model(controllerとは別のmodel)

def self.tss_import(file) add_cnt = 0 update_cnt = 0 error_cnt = 0 line = 1 error_reason = "" @statuses = [] @lists = [] CSV.foreach(file.path, headers: true, encoding: 'Shift_JIS:UTF-8') do |row| if row[…] ※判断文(省略) @statuses << { "error_reason" => "E002", "line" => line, "row" => row } error_cnt += 1 next end line += 1 end end if error_cnt > 0 return add_cnt, update_cnt, error_cnt, @statuses end

view

h1 Status import result table thead tr th line th error_reason th number th generation tbody - @statuses.each do |status| tr td =status["line"] td =status["error_reason"] td =status["number"] td =status["generation"] end

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

winterboum

2019/07/10 13:40

viewにどう表示したいのか controllerにどういう情報を渡したいのか  問題有る場合となかった場合で が決まれば自ずと決まります。 それらはどんなん?
Amkys

2019/07/11 00:22 編集

コメントありがとうございます。 viewには、一覧形式で表示したいので controllerには #<ActiveRecord::Relation [#<Status number: "0001", generation: "1">, #<Status: "0002", generation: "2">,(他にも複数あれば)]> という情報を渡したいのです。 ※modelで、このオブジェクトへの詰め込むcodingが分かりません。 問題あり/なしは、上記に加えてerror_cntの情報を渡します。 controller側では、modelの呼び出しと実行、そして受け取り方を以下のようにしています。 add_cnt, update_cnt, error_cnt, @obj_import_result = List.tss_import(params[:file])
winterboum

2019/07/11 02:56

<ActiveRecord::Relation [#<Status number: "0001", generation: "1">を返すということは、 CSVからListモデルのDBにsaveすることはしない。 データが正しいかどうかをチェックして、Statusに入れて返す ということでしょうか add_cnt, update_cnt, error_cnt は @statusesから取ることは出来ませんか? 例えば add_count = @statuses.select{|status| status.new?}.size
Amkys

2019/07/11 14:09

はい、その通りです。 データを登録してはいけない、不整合のデータならば、そのデータを@statusに入れて、返したいです。 add_cnt,update_cnt,error_cntは、既にcontrollerに渡せているので、@statusに詰め込む所だけが、分かりません。
winterboum

2019/07/11 15:06

Statusの構造、 Statusに何を入れて返すのか、add、update、errorの場合それぞれ は?
Amkys

2019/07/12 00:50

今回知りたいのは CSVファイルを読み込み、1行分をrowに入れる。 そのrowのデータが、問題だった場合に @statusesのオブジェクトへの詰め込み方が知りたい。 @statuses = rowだと、問題だったデータが最後のデータのみに上書きされてしまうので 構造としては、ハッシュになるのだと思いますが、 問題だったデータ(row)を、全て@statusesに詰め込みたいのです。 addやupdateに関しては、今回無視して頂いて結構です。
winterboum

2019/07/12 00:56

ですから、どう詰め込みたいのか、を聞いています。rowをそのまま入れるのか、何がまずかったかも入れるんか、行数とか。 具体的に書いていただかないと考えにくいです
Amkys

2019/07/12 01:12

早速の返信ありがとうございます。 rowをそのままと、エラーのあった行番号、エラー理由を@statusesに詰め込みたいです。 以下の感じを想定しています。 def self.tss_import(file) add_cnt = 0 update_cnt = 0 error_cnt = 0 line = 0 statuses = "" CSV.foreach(file.path, headers: true, encoding: 'Shift_JIS:UTF-8') do |row| if (問題あり) row["error_reason"] = "エラー理由" row["line"] = line @statuses = row error_cnt += 1 end line += 1 if error_cnt > 0 return add_cnt, update_cnt, error_cnt, @statuses end end
guest

回答4

0

普通にtss_importのようなものをvalidationに定義すればいいような気もしますが
パッと見てとりあえず気になったところだけ。

rb

1 CSV.foreach(file.path, headers: true, encoding: 'Shift_JIS:UTF-8') do |row| 2 # CSV.foreach を普段使わないので多分...ですが row って配列になってませんか? 3 if row[] ※判断文(省略) 4 # row は配列だと思うんですが、もしそうであれば row["error_reason"] は TypeError になる 5 row["error_reason"] = "E001" 6 row["line"] = line 7 @statuses << { "row" => row } 8 error_cnt += 1 9 next 10 end 11 end 12 line += 1 # foreachの外にあるので row["line"] = line の line は全て1のままです。

現状困っている原因が質問文から読み取れませんでした。
エラーが出ているのか、戻り値が期待通りではないのか(であれば何が返ってきているのか)など
質問への追記や修正依頼などはいちいち読まないので、何か変更があった場合は質問そのものを修正してください。

投稿2019/07/16 05:07

Mugheart

総合スコア2340

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Amkys

2019/07/16 05:30

コメントありがとうございます。 困っていることは、先程、全て解決いたしました。 自身でも、修正は質問そのものに修正すべきと、回答頂いた方とのやり取りで、深く感じました。 今後は、修正/更新が分かりやすいように、teratailを利用していきます。 modelで、データ登録出来るか判断し(判断条件が複雑なので、varidationにしませんでした) 登録不可データの@statusへの詰め込み方と、controllerへの渡し方、viewへの渡し方と表示方法が分からなかったのです。
winterboum

2019/07/16 05:36

判断条件が複雑でも validates でなく validate の方で書けばvalidationで対応できるかとも思うのです。
guest

0

ベストアンサー

``
@statuses << Status.new(
{ "error_reason" => "エラー理由",
"line" => line,
"row" => row
}

でなく、
row["error_reason"] = "E001" row["line"] = line @statuses << { "row" => row }
になってますね。 すると  status["row"]["line"] ですね

投稿2019/07/16 04:44

winterboum

総合スコア23284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Amkys

2019/07/16 05:01

ありがとうございました。 viewでは、 td = status["line"] td = status["row"][number] の記述で、値を表示できました。 本当にありがとうございました。
guest

0

@statuses は Hashの配列になっています。
つまり、viewでstatus.lineとしているstatus が Hashです。
Hashには line というmethodも属性もないのでエラーになっています。

status["line"] として下さい。

status.line としたい場合は、

@statuses << { "error_reason"] => "エラー理由", "line" => line, "row" => row }

と Hash で作っているのをやめて、Structureにするかもしくは
class Status を作って

@statuses << Status.new( { "error_reason" => "エラー理由", "line" => line, "row" => row } )

とするか、ですね

投稿2019/07/16 02:02

winterboum

総合スコア23284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Amkys

2019/07/16 02:47 編集

viewで表示する時、status["line"] の形にしました。 エラーはなくなったのですが、一覧に値が表示されませんでした。 そこでviewの頭に、debugを付けみると ------------------------------------------------ h1 Status import result = debug @statuses ------------------------------------------------ 画面には、以下のように表示されました。 --- - row: &1 !ruby/object:CSV::Row header_row: false row: - - number - TEST001 - - generation - 1 - - error_reason - '' - - line - 1 - row: *1
winterboum

2019/07/16 03:25

@statuses << { "error_reason"] => "エラー理由",,,,} になっていないのでは? そこのところのcode見せて下さい。 このコメント欄だと読みにくいので、該当のソースコード のところに<code>で
Amkys

2019/07/16 04:26 編集

冒頭のmodel、controller、viewを現状のcodeにしました。 お手数お掛けしますが、codeチェックをお願いします。
Amkys

2019/07/16 04:45

申し訳ございませんでした。 @statuses << { "error_reason"] => "エラー理由",,,,} の形式でもう一度、codingし直したら、viewでうまく値が表示されました。 親身になってこちらの悩みに、丁寧に対応頂き本当にありがとうございました。 自分自身、かなり勉強になりました。
guest

0

CSV.foreach(file.path, headers: true, encoding: 'Shift_JIS:UTF-8') do |row| if (問題あり) row["error_reason"] = "エラー理由" row["line"] = line @statuses = row

@statuses = [] CSV.foreach(file.path, headers: true, encoding: 'Shift_JIS:UTF-8') do |row| if (問題あり) @statuses << { "error_reason"] => "エラー理由", "line" => line, "row" => row }

かな?

投稿2019/07/12 01:27

winterboum

総合スコア23284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Amkys

2019/07/12 01:41

回答、ありがとうございます。 早速試してみます。 確認出来ましたら、結果をレポートさせて頂きます。
Amkys

2019/07/12 09:00

結果として、controllerには、データが渡ったのですが view側で一覧表示するのに、うまくいきませんでした。 model側は、以下のようにしました。 @statuses = [] CSV.foreach(file.path, headers: true, encoding: 'Shift_JIS:UTF-8') do |row| if (問題あり) row["error_reason"] = "" row["line"] = line @statuses << { "row" => row } error_cnt += 1 end if error_cnt > 0 return add_cnt, update_cnt, error_cnt, @statuses end controller側には、@statusesを確認すると [{"row"=>#<CSV::Row "number":"TEST001" "generation":"1" error_reason":"" "line":1>}, {"row"=>#<CSV::Row "number":"TEST002" "generation":"2" error_reason":"" "line":2>}] で渡ってきました。 viewには、以下のように渡しています。 render template: "statuses/import_result", collection: @statuses view側では、どのようにcodingしたらよいでしょうか?
winterboum

2019/07/12 10:12

どうしたいんかわからないので、まず書いてみて
Amkys

2019/07/16 01:45

返信遅くなり申し訳ありません。以下にコメントさせて頂きます。 controllerからview(テンプレート:statuses/import_result)にはerror_cntと@statusesを渡し viewでは ・error_cntの情報は、app/layouts/_header.html.slimで表示(ここは確認できています。) ・@statusの情報(line / number / generation / error_reason の順に)を一覧表示したい。 (↓現状のcontroller) if error_cnt > 0 then flash[:alert] = "Import result to tool_list<br/> ---> Import_error = #{error_cnt.to_s}".html_safe render template: "statuses/import_result", collection: @statuses (↓現状のview) h1 Import result table thead tr th line th number th generation th error_reason tbody - @statuses.each do |status| tr td =status.line td =status.number td =status.generation td =status.error_reason end 現状、この状態でviewに処理が流れると以下のエラーになってしまいます。 ActionView::Template::Error (undefined method `line' for #<Hash:0x00007fea04f81a10>): controllerからの渡し方が悪いのか? viewでの処理の仕方が悪いのか?ってところで悩んでいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問