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

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

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

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

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Sinatra

Sinatraは、Rubyで作られた オープンソースのWebアプリケーションフレームワークです。

Q&A

解決済

1回答

2355閲覧

【sinatra】(おそらく)SQLを使うことに起因するエラー

programming

総合スコア476

Ruby

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

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Sinatra

Sinatraは、Rubyで作られた オープンソースのWebアプリケーションフレームワークです。

0グッド

0クリップ

投稿2016/09/11 07:44

Ruby(Sinatra)初心者です。
Sinatraで
http://localhost:4567/browse/9784041003237/3
にアクセスするとエラーが表示されます。

  • 48行目などにある、以下のようなコマンドを実行すると戻り値は配列になるのでしょうか。

調べてみても、そもそも execute に関する説明があまり見つかりませんでした。

  • 他にも様々なバグを含んでいることはわかっているのですが、場所がわかりません。

これも教えていただけるとありがたいです。

ruby

1data = @db.execute(sql) 2

以下がエラーです。

TypeError at /browse/9784041003237/3 no implicit conversion of Fixnum into Array

以下はソースコードです。
基本部分の.rbファイルとデータベース内容のみです。
必要がありましたら、その都度ソースコードをお伝えしたいと思います。

ruby

1require 'sinatra' 2require 'sqlite3' 3require "sinatra/reloader" if development? 4 5#データベースの準備 6before do 7 @db = SQLite3::Database.new("BookInformation.db") 8end 9after do 10 @db.close 11end 12 13#メインページ 14get '/' do 15 erb :index ,layout: :layout 16end 17 18#閲覧ページ 19get '/browse/:ISBN/:ID' do 20 @ISBN = params["ISBN"].to_i 21 @ID = params["ID"].to_i 22 23 #IDが指定されていなかった場合に、入力されたISBNが結び付けられている中で最後のIDを指定 24 if(!@ID) 25 sql = <<-SQL 26 SELECT id FROM BookInformation WHERE isbn = "#{@ISBN}" 27 SQL 28 data = @db.execute(sql) 29 if (data.empty?) 30 redirect '/' 31 end 32 @ID = data[data.length-1] 33 end 34 35 #IDに結びついているISBNが入力されたISBNと等しいか確認 36 sql = <<-SQL 37 SELECT isbn FROM BookInformation WHERE id = "#{@ID}" 38 SQL 39 data = @db.execute(sql) 40 if(!data.include?(@ISBN)) 41 redirect '/about' 42 end 43 44 #閲覧数更新 45 sql = <<-SQL 46 SELECT views FROM BookInformation WHERE id = "#{@ID}" 47 SQL 48 data = @db.execute(sql) 49 tmp = data.first 50 tmp = tmp + 1 51 52 sql = <<-SQL 53 UPDATE BookInformation SET views = "#{tmp}" WHERE id = "#{@ID}" 54 SQL 55 @db.execute(sql) 56 57 #閲覧ページに移動 58 erb :browse ,layout: :layout 59end 60 61#登録ページ 62get '/registration' do 63 erb :registration ,layout: :layout 64end 65 66#登録作業 67get '/registration/insert' do 68 @isbn = params["isbn"].to_i 69 @title = params["title"] 70 @author = params["author"] 71 @publisher = params["publisher"] 72 @publication_year = params["publication_year"].to_i 73 @publication_month = params["publication_month"].to_i 74 @publication_date = params["publication_date"].to_i 75 76 if (@isbn || @title) 77 sql = <<-SQL 78 INSERT INTO BookInformation(isbn,title,author,publisher,publication_year,publication_month,publication_date) 79 VALUES("#{@isbn}","#{@title}","#{@author}","#{@publisher}","#{@publication_year}","#{@publication_month}","#{@publication_date}"); 80 SQL 81 @db.execute(sql) 82 83 #idの取得 84 sql = <<-SQL 85 SELECT id FROM BookInformation WHERE ROWID = last_insert_rowid(); 86 SQL 87 @id = @db.execute(sql); 88 redirect '/browse/@isbn/@id' 89 else 90 redirect '/registration' 91 end 92 93end 94 95#アプリケーション紹介ページ 96get '/about' do 97 erb :about ,layout: :layout 98end
1|9784044288228||||2009|8|20|1 2|9784044288228|サマーウォーズ|岩井恭平|株式会社角川文庫|2009|8|20|0 3|9784041003237|おおかみこどもの雨と雪|細田守|株式会社角川書店|2012|7|15|1

いくら考えてもわかりません。
どうか解決法をお教えください。

文章がうまくまとまっていなくてすみません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

sqlite3-rubyのドキュメントを参照してみてください。解りづらいですが、any results are accumulated into an array and returned wholesale.とあり、(ブロックが与えられなかったならば)配列でまとめて返す、とあります。
data = @db.execute(sql)とした場合のdataは配列で合っています。

ではなぜだめなのかというと、no implicit conversion of Fixnum into Arrayとあります。
このメッセージは"Fixnum(整数)からArray(配列)への暗黙の変換はありません"という意味です。
これが発生する箇所は以下だと考えられます:

Ruby

1#閲覧数更新 2sql = <<-SQL 3 SELECT views FROM BookInformation WHERE id = "#{@ID}" 4SQL 5data = @db.execute(sql) 6tmp = data.first 7tmp = tmp + 1 # ここ!

SQLite3::Database#executeの戻り値はたしかに配列ですが、その要素もデフォルトでは配列**※**です。
質問者様の例ですと変数tmpはおそらく[534]といったような要素が閲覧数1つだけの配列になっているはずです。なのでtmp + 1という「配列 + 整数」という計算をしようとしてエラーが出ているということです。
SQLite3::Databaseインスタンスのresults_as_hashプロパティをtrueにするとexecuteの戻り値の配列の要素が{"views" => 534}のようなカラム名をキーとするハッシュとなります。

ではどうすればいいかというと、もちろんtmp[0]のように値を取得してもいいのですが、SQLite3::Database#get_first_valueを使うのがよいでしょうか。

Ruby

1#閲覧数更新 2sql = <<-SQL 3 SELECT views FROM BookInformation WHERE id = "#{@ID}" 4SQL 5tmp = @db.get_first_value(sql) 6tmp = tmp + 1

get_first_valueはクエリの結果の最初の行の最初の値を取得してくれます。上記のように特定の1行の1つのカラムの値を取得するには便利です。

投稿2016/09/11 18:06

guest1213

総合スコア306

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

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

programming

2016/09/12 01:47

ありがとうございます! エラーは表示されなくなりました。 紹介していただいたサイトも参考にしていこうと思います。 ただやはり違うバグが潜んでいるので、頑張ってみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問