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

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

新規登録して質問してみよう
ただいま回答率
85.48%
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Ruby

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

Ruby on Rails

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

Q&A

解決済

2回答

1788閲覧

railsにおける csvファイル読み込み

shutainer

総合スコア11

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Ruby

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

Ruby on Rails

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

0グッド

0クリップ

投稿2020/08/19 13:18

編集2020/08/19 13:34

rails 5.0.1 ruby 2.4.5にて
下記サイトを参考にcsvファイルの読み込みを実装中です。

rubyのコードについてわからないところがあり解説願いできたら幸いです。

【Ruby on Rails】CSVインポート

app/model/user.rb

1class User < ApplicationRecord 2 def self.import(file) 3 CSV.foreach(file.path, headers: true) do |row| 4 # IDが見つかれば、レコードを呼び出し、見つかれなければ、新しく作成 5 user = find_by(id: row["id"]) || new 6 # CSVからデータを取得し、設定する 7 user.attributes = row.to_hash.slice(*updatable_attributes) 8 # 保存する 9 user.save 10 end 11 end 12 13 # 更新を許可するカラムを定義 14 def self.updatable_attributes 15 ["id", "name", "age"] 16 end

のimportはクラスメソッドは、であり、Userモデルを操作して、最終的にuserテーブルにデータを保存する役目であることは理解できます。

ruby

1user = find_by(id: row["id"]) || new

にてnil判定を行っているのはわかるのですが、右のnewというオブジェクトは何を意味するのでしょうか?rooやcsvライブラリに実装されているのでしょうか?

ruby

1user.attributes = row.to_hash.slice(*updatable_attributes)

rowはcsvの行で、ハッシュに変換しているとおもうのですが、実際どのようなハッシュになるのでしょうか?(キーは?)

*updatable_attributes
このような、記法はまだみたことがありません。
self.updatable_attributesメソッドをsliceメソッドの引数にしているように見えますが、
不勉強ながら、メソッドを引数に入れるためにはproc? & を用いると聞きかじったことがあります。

上記2点についてお教え願いますでしょうか?

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

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

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

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

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

guest

回答2

0

「メソッドの中でメソッドを使う場合は,インスタンスを省略できるので」
という方向は合っていますが、「この場合インスタンスはなにか?」というところで間違えています
user = find_by(id: row["id"]) || new
の find_by の インスタンスは何だと思いますか? def self.。。。なのでUserです。
newも同じく Userがこの場合のインスタンスです。
user = User.find_by(id: row["id"]) || User.new ということです。
find_by で見つかったら 元々あるuserの更新
みつからなかったら(nilが返ってくるので)新しいuserを用意して作成
ということを行ってます

投稿2020/08/19 22:43

winterboum

総合スコア23349

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

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

0

ベストアンサー

(1)について

なかなか難しいところですが、このコードで説明できているでしょうか?

ruby

1class User 2 3 # インスタンスメソッド 4 def method1 5 ここでのselfはインスタンス = User.newした時のオブジェクト 6 usersテーブルの1レコードを表すオブジェクト 7 end 8 9 # クラスメソッド 10 def self.method2 11 ここでのselfUserクラス自身を示す 12 self.new => User.new 13 self.find(1) => User.find(1) 14 なお、selfは省略可能 15 16 new => User.newであり、self.newでもある 17 find(1) => User.find(1)でありself.find(1)である 18 end 19 20 21end

(2)について

*配列は可変長引数を受け取るメソッドに配列を引数として渡す方法です。
Hash#sliceは渡した引数のキーだけを持つ新しいHashを返します。

row = { "id" => 1, "name" => "ユーザ1", "age" => 10, "hoge1" => "aaa", "hoge2" => "bbb" } # 本来の渡し方=可変長引数 row.slice("id", "name", "age") => {"id" => 1, "name" => "ユーザ1", "age" => 10} # 配列を可変長引数として渡すために*を先頭につける row.slice(*["id", "name", "age"]) => {"id" => 1, "name" => "ユーザ1", "age" => 10}

投稿2020/08/19 13:41

編集2020/08/19 15:55
mingos

総合スコア4025

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

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

shutainer

2020/08/19 15:37

ありがとうございます。 ご回答にもかかわらず理解できずにおります。 1) ```ruby user = find_by(id: row["id"]) || new ``` はnot nil判定を行っていると理解しました。 しかし、newの意味はなんでしょうか? 予想では、以下みなおしたところ、 https://gihyo.jp/book/2017/978-4-7741-9397-7 プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで メソッドの中でメソッドを使う場合は,インスタンスを省略できるので、 row.new を省略して new ということなのでしょうか? 以下公式documentをみると、CSV::Rowにnewメソッドがあり新しいrowを返すようです。 https://docs.ruby-lang.org/ja/latest/class/CSV=3a=3aRow.html 2) 理解できておりません。
mingos

2020/08/19 15:57 編集

とりあえず私の回答は(1)だけです。 まずは(1)を先に解決したほうが良いと思ったためです。 ※追記 (2)についても説明を追加しました。 ただ、こっちは無理に理解する必要はないです。使用頻度も低いので。 私が例に出したコードを見てください。コメントも含めて。 self.method2が今回のself.importにあたりますよね? クラスメソッドなので。 クラスメソッドの中では、selfはインスタンスではなくクラスそのものを表します。 また、メソッドの中ではselfは省略可能です。 まず、このように見てはだめです。 ```ruby user = find_by(id: row["id"]) || new ``` このように必要な文脈というか塊で見ないと意味がわからないためです。 ```ruby class User < ApplicationRecord def self.import(file) ... user = find_by(id: row["id"]) || new ... end end ``` Userクラスのクラスメソッド import内で書かれているので、 import内ではself=Userであり、またメソッド内でselfは省略可能です。 なので、 user = find_by(id: row["id"]) || new は user = self.find_by(id: row["id"]) || self.new であり、self=Userなので、こう書いてあるのと同じです。 user = User.find_by(id: row["id"]) || User.new
shutainer

2020/08/21 09:40

ありがとうございます。 理解できました。 ご丁寧にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問