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

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

ただいまの
回答率

90.38%

  • Ruby

    9946questions

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

  • Ruby on Rails

    9355questions

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

  • Ruby on Rails 5

    3591questions

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

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 115

Amkys

score 2

前提・実現したいこと

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
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Amkys

    2019/07/12 09:50

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

    addやupdateに関しては、今回無視して頂いて結構です。

    キャンセル

  • winterboum

    2019/07/12 09:56

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

    キャンセル

  • Amkys

    2019/07/12 10: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

    キャンセル

回答 4

checkベストアンサー

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 14:01

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

    本当にありがとうございました。

    キャンセル

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 10:41

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

    キャンセル

  • 2019/07/12 18: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したらよいでしょうか?

    キャンセル

  • 2019/07/12 19:12

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

    キャンセル

  • 2019/07/16 10: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での処理の仕方が悪いのか?ってところで悩んでいます。

    キャンセル

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 11:42 編集

    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

    キャンセル

  • 2019/07/16 12:25

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

    キャンセル

  • 2019/07/16 12:49 編集

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

    キャンセル

  • 2019/07/16 13:45

    申し訳ございませんでした。
    @statuses << { "error_reason"] => "エラー理由",,,,}
    の形式でもう一度、codingし直したら、viewでうまく値が表示されました。

    親身になってこちらの悩みに、丁寧に対応頂き本当にありがとうございました。
    自分自身、かなり勉強になりました。

    キャンセル

0

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

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


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/16 14:30

    コメントありがとうございます。
    困っていることは、先程、全て解決いたしました。
    自身でも、修正は質問そのものに修正すべきと、回答頂いた方とのやり取りで、深く感じました。
    今後は、修正/更新が分かりやすいように、teratailを利用していきます。

    modelで、データ登録出来るか判断し(判断条件が複雑なので、varidationにしませんでした)
    登録不可データの@statusへの詰め込み方と、controllerへの渡し方、viewへの渡し方と表示方法が分からなかったのです。

    キャンセル

  • 2019/07/16 14:36

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

    キャンセル

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

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Ruby

    9946questions

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

  • Ruby on Rails

    9355questions

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

  • Ruby on Rails 5

    3591questions