- 投稿日:2020-08-09T22:49:46+09:00
Node.jsでmysqlのDate型が勝手にDatetime型で取得される問題を解決する
はじめに
Node.jsドドド初心者です。ローカルで動くDBの情報を表示する簡単なアプリを作成しようと思い立って作ったのですが、思わぬところで落とし穴があったので、それについての覚え書きです。
Node.js Expressで、mysqlを操作している際に発生した事象です。DATE型がDATETIME型として取得されてしまう
今回表示するテーブルは非常にシンプルな情報で構成されていました。
table名 : youtube +----+------------+-----------------------------------------------------------------+ | id | date | title | +----+------------+-----------------------------------------------------------------+ | 1 | 2020-08-08 | 【絶対解けない】答えが「見たことない字」になる合体漢字クイズ | | 2 | 2020-08-07 | 数学の図形を使った共通点当てゲームで爆笑連発!【VENN'S CODE】 | | 3 | 2020-03-27 | 伊沢vs伊沢vs伊沢vs伊沢 | +----+------------+-----------------------------------------------------------------+(中身は、すきなYoutuberさんの動画の情報を拝借しました。)
しかし、実際に情報をNode.jsで表示すると、DATE型のdateカラムが勝手にDATETIME型になってしまう問題が発生しました。
コードは以下の通りです。app.js/*(中略)*/ app.get("/youtube_list",(req,res) =>{ connection.query( 'SELECT * FROM youtube', (error,results) =>{ res.render("youtube_list.ejs",{items: results}); )}; });youtube_list.ejs<% items.forEach((item) => { %> <li> <div class="item-data"> <span class="id-column"><%= item.id %></span> <span class="first-column"><%= item.date %></span> <span class="second-column"><%= item.title %></span> </div> </li> <% }); %>調べた際に、同様の事象が発生している方が何人かいました。JSONの仕様では?という話もあったので、おそらくその影響でしょうか。
シンプルな解決策:connection option
最初は、関数を作ってDATETIME型の情報をこねくり回す方法を取ったのですが、その後改めて調べてみたら、とても単純な話で、「connectionの際にoptionを付与するだけ」でした。
app.jsconst connection = mysql.createConnection({ host:'localhost', user:'root', password:'password', database:'quizknock', dateStrings: 'date' /*または'true'*/ }); connection.connect();このdateStringsで、mysqlから取得するデータを文字列として取得することができます。
知ってしまえばめちゃくちゃ簡単ですね・・・
参考:mysql Git
- 投稿日:2020-08-09T17:41:57+09:00
deviseでusersテーブルを作成しようとした時に発生したMysql2::Error:Specified key was too long; max key length is 767 bytesのエラー対処法
基本的には何もいじらずデフォルトの設定でマイグレーションしようとしただけなのでそれでエラー出るってどうよっていう話ですが、gem入れた後に
rails g devise user
でモデル作って何も触らず
rails db:migrate
しようとしたら
Mysql2::Error: Specified key was too long; max key length is 767 bytesとエラーが出ました。
原因はこちらの記事に実にわかりやすくまとまっていました。
emailの文字数制限を変えることで解決する方法が載っていました。自分はめっちゃ長いメールアドレスあったらどうすんねんとか訳のわからない意見が自分の中に湧き上がってきたので別の方法で解決しました。ええ。文字コード自体変えました。
database.ymldefault: &default adapter: mysql2 # encodingの値をutf8mb4からutf8に変更 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: socket: /tmp/mysql.sock #(以下略)めでたしめでたし。
それにしてもカラムの型がvarchar(255)だとエラー出るとか納得いかない参考にした記事
- 投稿日:2020-08-09T15:10:19+09:00
INSERT を重複せずに実行する
あるテーブルに重複有無を確認後、重複がなれけばINSERTしたいときの方法。
例えば users_booksテーブルが以下のようにあったとします。
id user_id book_id 1 5 10 ここで重複の有無を確認して、同じレコードが入っていないときINSERTしたいなら、以下のSQL文でできました。
INSERT INTO users_books(user_id, book_id) SELECT 5, 10, WHERE NOT EXISTS (SELECT user_id FROM users_books WHERE user_id = 5 AND book_id = 10)注意する点として、通常のINSERTなら
VALUES
となっているところが、SELECT
になっていること。
- 投稿日:2020-08-09T14:46:54+09:00
【Rails】summernote 本番環境で画像保存ができない時の解決方法
はじめに
某スクールの学習過程ポートフォリオ作成の際に、Gem 'summernote'を用いて
リッチテキストエディタを実装しました。開発環境上では画像を含めたテキストの投稿が可能でしたが、
デプロイ後の本番環境にて画像を投稿しようとすると下記エラーが発生し、投稿保存がされませんでした。(0.5ms) ROLLBACK Completed 500 Internal Server Error in 46ms (ActiveRecord: 12.9ms) ActiveRecord::ValueTooLong (Mysql2::Error: Data too long for column 'article_content' at row 1: INSERT INTO `articles` (`admin_id`, `article_title`, `article_content`, `article_image_id`, `created_at`, `updated_at`) VALUES (1, '観葉植物の置き場所はどこがいいか', '<p><img src=\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QB+RXhpZgAATU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAABJADAAIAAAAUAAAAUJKGAAcAAAASAAAAZKACAAQAAAABAAA...(以下長すぎるので省略します)解決方法
【前提】
・テーブル名はArticleとしてます。(Article=記事の意)。この部分は任意の名前にしてください。①エラー文の解釈
まず、ターミナルに表示されていたActiveRecord::ValueTooLong (Mysql2::Error: Data too long for column...)このエラー文が解決への糸口になります。
簡潔にいうと、「データが長すぎ」と言われています。
投稿文を保存するarticle_contentのデータ型をtextにしていましたが、これでもまだ足りないと言われているわけです。
代表的なデータ型として短文(1〜255文字)はstring型、長文()はtext型を使うという程度の知識でした。②変更すべき点
上記内容で、「データが長すぎて保存できない」という問題点がわかりました。
そうしたら収まるように大容量用のデータ型に変更してあげればいいだけです!
下記記述が修正を加えたマイグレーションファイルになります。(date)_change_column_to_article.rbclass ChangeColumnToArticle < ActiveRecord::Migration[5.2] def up change_column :articles, :article_content, :text, null: false, limit: 4294967295 end def down change_column :articles, :article_content, :text, null: false end end※以下、修正内容についての詳細です。
デプロイの際にMySQL
MySQLにあるデータ型は以下の通りです。
データ型 解説 CHAR 255Bまでの固定長文字列 VARCHAR 64KBまでの可変長文字列 TINYTE 255Bまでの可変長文字列 TEXT 64KBまでの可変長文字列 MEDIUMTEXT 1.6MBまでの可変長文字列 LONGTEX 4.3GBまでの可変長文字列 この中のLONGTEXTを使用する事にしました。(最大にしておけば足りなくなることはまずないだろうという考え)
ただし前述した通り、Railsの学習をした際にstringとtextくらいしか学習した記憶がなかったため設定方法がわかりませんでした。調べた結果、結構簡単でリミットをつけるだけでした。
まずカラムに変更を加えるため、以下のようにします。ターミナル$ rails g migration ChangeColumnToArticleすると、以下の内容でマイグレーションファイルが作成されます。
日付_change_column_to_Article.rbclass ChangeColumnToArticle < ActiveRecord::Migration[5.2] def change endそして、変更前の記載と変更後の記載を加えます。
ここの記述は冒頭に記載したものと同じになります。日付_change_column_to_article.rbclass ChangeColumnToArticle < ActiveRecord::Migration[5.2] ※変更を加えた記述 def up change_column :articles, :article_content, :text, null: false, limit: 4294967295 end ※変更前の記述 def down change_column :articles, :article_content, :text, null: false end endリミットを書き加えることで、LONGTEXT型にします。
なお、4294967295と言う数字は4294967295バイト(4.3GB)でLONGTEXT型の上限です。
limitの範囲を16777216 ~ 4294967285にするとLONGTEXT型になるそうです。ターミナル$ rails db:migrate変更を反映させて終了です。
そもそも、なぜ開発環境では使えて、本番環境でエラーが出たのか
本番環境ではMySQLを使用していて、MySQLのtext型には最大長が設定されており、半角で65,535文字を超える文字列は扱えません。単純なことでこれが開発環境と本番環境での違いによるエラーの発生の理由でした。(現在の知識・語彙力ではこれが限界です。いずれもっと詳しく解説を加えられたらと思います!)