20210730のMySQLに関する記事は7件です。

【基本】AWSでRDS(mysql)に接続してみた

概要 AWSのRDSを使ってMySQLへ接続をしてみました。 前提事項 RDSの作成で行うパラメータ設定は、基本的にはすべてデフォルトで行っています。 また、接続方法はEC2インスタンスの踏み台サーバを使ってRDSへ接続します。 MySQLで接続してみる EC2にMySQLクライアントを入れる ・mysql8.0がインストールされているか確認する [root@ip-10-0-1-10 ~]# yum info mysql Loaded plugins: extras_suggestions, langpacks, priorities, update-motd Error: No matching Packages to list インストールできないのでmysql8.0のリポジトリを追加します [root@ip-10-0-1-10 ~]# yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm Installed: mysql80-community-release.noarch 0:el7-3 Complete! mysql8.0のリポジトリを有効化にしていきます yum-config-manager --disable mysql57-community yum-config-manager --enable mysql80-community mysql-community-clientをインストールする [root@ip-10-0-1-10 ~]# yum install -y mysql-community-client Installed: mysql-community-client.x86_64 0:8.0.26-1.el7 mysql-community-libs.x86_64 0:8.0.26-1.el7 mysql-community-libs-compat.x86_64 0:8.0.26-1.el7 Dependency Installed: mysql-community-client-plugins.x86_64 0:8.0.26-1.el7 mysql-community-common.x86_64 0:8.0.26-1.el7 ncurses-compat-libs.x86_64 0:6.0-8.20170212.amzn2.1.3 Replaced: mariadb-libs.x86_64 1:5.5.68-1.amzn2 Complete! RDSへ接続する [root@ip-10-0-1-10 ~]# mysql -h database-1.c5jqncbegdvz.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 22 Server version: 8.0.23 Source distribution Copyright (c) 2000, 2021, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> 参考 MySQLクライアントで接続する方法
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#3 sinatraでActiveRecordを使わずに掲示板アプリを作ってみた

前回の続き。 前回はモデルを見て行ったので、今回はdatabaseディレクトリ を見ていく! create_database.sql ここにデータベースやテーブル作成のSQLを書いてくっぽいけど、どんなコマンドを実行したら データベースが作られるのかは全く分からない。そこからイメージがついてない。 てか、ここにSQL文書いても、まずデータベースに接続ができるのかが怪しい。 確かにクライアントは定義したけど、別のディレクトリのファイルに定義したから それをどう連携させるのか。include db.rbとかするわけでもなさそうだし。 一旦、そこは飛ばしてどんなコードか理解していくとする CREATE DATABASE IF NOT EXISTS 0ch; まぁこれはそのままで、Ochって名前のデータベースがなければ、 そのデータベースを作るって感じです。 next! create_post.sql CREATE TABLE IF NOT EXISTS posts ( id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL, topic_id INTEGER UNSIGNED NOT NULL, name VARCHAR(255), email VARCHAR(255), body TEXT NOT NULL, created_at DATETIME NOT NULL, PRIMARY KEY (id) ); IDカラムのデータ型はINTEGERで数値が入っていく UNSIGNED AUTO_INCREMENT は、https://kin-memo.hatenablog.com/entry/2018/02/07/182952 この記事にある通りで UNSIGNEDは、正の数値のみ受け付ける感じ。 AUTO_INCREMENTはその名の通り。 レコードが追加されると、自動的に付与される。今回付与されるのはid レコードが追加されるたび、idカラムにインクリメントされた数値が追加されていく。 NOT NULLはその名の通り、このカラムには絶対何かしらの値が入っていなきゃいけない。といった制約。 topic_idがなぜあるかというと、 一つのトピックに、いくつもの投稿が紐ずくので、 どのトピックに対する投稿かを識別できるように、 外部キーを設定する必要がある。 https://www.dbonline.jp/mysql/table/index8.html PRIMARY KEY(主キー)とは作成したテーブルの中の1つまたは複数のカラムの組み合わせに対して設定するもので、テーブルに格納されているデータをに格納されているデータを識別するための目印のようなものです。 まぁ確かにプライマリーキーがあれば、id=3でそのデータが参照できるってわけか。 プライマリーキーに指定したカラムは重複とNULLを受け付けないようになる。 受け付けたら識別できなくなるからね てか、railsで開発してた頃は、プライマリキーを指定した覚えなんてないんだが、、 それなのに困ったことなかった。。。。なんでやねん。。。 sinatraとrailsを行き来すれば、理解深まりそうと思った。 railsの仕組みについても興味が湧いてきますね。 create_topics.sql CREATE TABLE IF NOT EXISTS topics ( id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY (id) ); まぁ、さっき解説した通りですね〜。 app.rb ついでにapp.rbも見ておきましょう。 require 'sinatra' require 'slim' require_relative 'models/topic' require_relative 'models/post' get '/' do @topics = Topic.all slim :index end post '/topics' do topic = Topic.new(title: params[:title]) topic.save redirect '/' end get '/topics/:id' do @topic = Topic.find(params[:id]) @posts = Post.of_topic(@topic.id) slim :show end post '/topics/:topic_id/posts' do name = params[:name].empty? ? '名無し' : params[:name] post = Post.new(name: name, email: params[:email], body: params[:body], topic_id: params[:topic_id]) post.save redirect back end なんだかroutes.rbみたい まぁ、なんとなくわかるので、大丈夫でしょう。 次回はいよいよ、アプリを実行していきたいと思います。 コードを書いたはいいけど、何のコマンドを打てば データベース作られたりするのかがいまいちよく分からないですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLに躓きすぎたので備忘録として残す

題名通り今回はMySQLで躓きすぎたので備忘録として、今後もしまた同じ目に遭ったとしても対処できるように備忘録として残す事にしました。 使用環境 Ubuntu : 18.04.3 LTS \n \l Rails : 6.1.3.2 MySQL : Ver 14.14 Distrib 5.7.34 Vagrant : 2.2.17 エラー内容 今回のエラーは、MySQLの環境構築の完了後マイグレーションしようとした時に出てきたエラーになっております。 結論 結論として、今回のエラーは「schema.rb」の環境がどうやら悪さをしていたみたいなので、今まで使用していた「schema.rb」を消して新しい「schema.rb」を作る事によって、無事MySQLのエラーをクリアすることができました。 エラー文の全容 マイグレーションしようとしたら出てきたエラー ターミナル $ rails db:migrate == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: you can't define an already defined column 'name'. /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:36:in `block in change' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ArgumentError: you can't define an already defined column 'name'. /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:36:in `block in change' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) まず「devise_create_users」の36行目と5行目のカラム'name'が二つありますよというエラー文になります。 ということはカラム'name'を消せば解決です。 2 rails db:migrate:statusでマイグレーションの状態を確認する ターミナル $ rails db:migrate:status database: hoge_development Status Migration ID Migration Name -------------------------------------------------- up 20200208124233 Create hoges down 20200209055424 Devise create users down 20200220052712 Add hoges tosees down 20201207042223 Add hoge to hoges down 20201210015310 Add user id to hoges down 20201222045544 Create hoges down 20210303012038 Add hoge to users down 20210714052813 Create hoges 一応、rails db:migrate:statusで確認をしてからカラム'name'を消しました。 (statusがdownだと手動で直すことができます) 3.再びrails db:migrateをする ターミナル $ rails db:migrate == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) -> 0.0673s -- add_index(:users, :email, {:unique=>true}) -> 0.0530s -- add_index(:users, :email, {:unique=>true}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Mysql2::Error: Duplicate key name 'index_users_on_email' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:41:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::StatementInvalid: Mysql2::Error: Duplicate key name 'index_users_on_email' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:41:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Duplicate key name 'index_users_on_email' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:41:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) 成功した!と思ったのも束の間、新たなエラーが、、、。 今度は、devise_create_users.rbの41行目とMySQLにエラー。。。 4.rails db:dropをしてみた devise_create_users.rbの41行目は直しても、MySQLかぁ。。。と思ったので、一度dropしてみました。 ターミナル $ rails db:drop rails aborted! ActiveRecord::NoEnvironmentInSchemaError: Environment data not found in the schema. To resolve this issue, run: bin/rails db:environment:set RAILS_ENV=development /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:drop => db:check_protected_environments (See full trace by running task with --trace) ※rails db:dropとは一度データベースを消すときに使います。 「bin/rails db:environment:set RAILS_ENV=development」というのが出ましたが、今はやめときました。 5.rails db:createしてみた ターミナル $ rails db:create Database 'hoge_development' already exists Database 'hoge_test' already exists 既に存在している模様 6.もう一度rails db:migrateしてみた ターミナル $ rails db:migrate == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Mysql2::Error: Table 'users' already exists /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::StatementInvalid: Mysql2::Error: Table 'users' already exists /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Table 'users' already exists /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) 若干変わったけど進展なし。。。 7.rails db:resetで実行 ターミナル $ rails db:reset rails aborted! ActiveRecord::NoEnvironmentInSchemaError: Environment data not found in the schema. To resolve this issue, run: bin/rails db:environment:set RAILS_ENV=development /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:drop => db:check_protected_environments (See full trace by running task with --trace) 実行できない。。。(泣) おのれschemaめ。。。 8. bin/rails db:environment:set RAILS_ENV=development ターミナル $ bin/rails db:environment:set RAILS_ENV=development vagrant@ubuntu-bionic:/vagrant/hoge$ お!いけるか! 9.rails db:reset ターミナル $ bin/rails db:environment:set RAILS_ENV=development vagrant@ubuntu-bionic:/vagrant/hoge$ rails db:reset Dropped database 'hoge_development' Dropped database 'hoge_test' Created database 'hoge_development' Created database 'hoge_test' rails aborted! ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `comments` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:setup => db:schema:load (See full trace by running task with --trace ...。 10. 念の為MySQLのバージョンを確認 ターミナル $ mysql --version mysql Ver 14.14 Distrib 5.7.34, for Linux (x86_64) using EditLine wrapper 11. rails db:migrate ターミナル $ rails db:migrate == 20200208124233 Createhoges: migrating ====================================== -- create_table(:hoges, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Mysql2::Error: Table 'hoges' already exists /vagrant/hoge/db/migrate/20200208124233_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::StatementInvalid: Mysql2::Error: Table 'hoges' already exists /vagrant/hoge/db/migrate/20200208124233_create_blogs.rb:3:in `change' /vagrant/hege/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Table 'blogs' already exists /vagrant/hoge/db/migrate/20200208124233_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) エラーの内容が変わりました。 MySQLの何かが悪さをしています。 12. rails db:reset ターミナル $ rails db:reset Dropped database 'hoge_development' Dropped database 'hoge_test' Created database 'hoge_development' Created database 'hoge_test' rails aborted! ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:setup => db:schema:load (See full trace by running task with --trace) どうやら一つはdatabase.ymlの入力がよろしくないようですね。 13.database.ymlを変更して再度rails db:reset ターミナル $ rails db:reset Dropped database 'hoge_development' Dropped database 'hoge_test' Created database 'hoge_development' Created database 'hoge_test' rails aborted! ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:setup => db:schema:load (See full trace by running task with --trace) 変わらないな・・・。 最終手段でschemaを古いものを消して、新しくschemaを作る事にしました。 14. 一度まっさらな状態にして$ rails db:migrate:statusを見てみた ターミナル $ rails db:migrate:status Schema migrations table does not exist yet. 一応schemaファイルは無くなっていますね 15. schemaファイルを作り直してbin/rails db:migrate ターミナル $ bin/rails db:migrate == 20200208124233 Createhoges: migrating ====================================== -- create_table(:hoges, {}) -> 0.0566s == 20200208124233 Createhoges: migrated (0.0569s) ============================= == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) -> 0.0592s -- add_index(:users, :email, {:unique=>true}) -> 0.0587s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0553s == 20200209055424 DeviseCreateUsers: migrated (0.1741s) ======================= == 20200220052712 AddBlogsTosees: migrating =================================== == 20200220052712 AddBlogsTosees: migrated (0.0000s) ========================== == 20201207042223 AddNameToBlogs: migrating =================================== -- add_column(:hoges, :name, :string) -> 0.1584s == 20201207042223 AddNameToHoges: migrated (0.1588s) ========================== == 20201210015310 AddUserIdToHoges: migrating ================================= -- add_column(:hoges, :user_id, :integer) -> 0.1395s == 20201210015310 AddUserIdToHoges: migrated (0.1397s) ======================== == 20201222045544 Createhoges: migrating =================================== -- create_table(:hoges, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/onsen/db/migrate/20201222045544_create_hoges.rb:3:in `change' /vagrant/onsen/bin/rails:9:in `<top (required)>' /vagrant/onsen/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/migrate/20201222045544_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/migrate/20201222045544_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) おしい・・・! どうやらhogesカラムのidをbigintに変えればいけそうな感じですね。 ※(t.bigint :hoge_id)に変えればよい 16.修正して再度bin/rails db:migrate ターミナル $ bin/rails db:migrate == 20201222045544 CreateHoges: migrating =================================== -- create_table(:hoges, {}) -> 0.0619s == 20201222045544 CreatHoges: migrated (0.0620s) ========================== == 20210303012038 AddProfileImageToUsers: migrating =========================== -- add_column(:users, :profile_image, :string) -> 0.1556s == 20210303012038 AddProfileImageToUsers: migrated (0.1557s) ================== == 20210714052813 CreateHoges: migrating ================================== -- create_table(:hoges) -> 0.0691s == 20210714052813 CreateHoges: migrated (0.0694s) ========================= 通った〜!! 疲れた。。。 MySQLは本当に面倒なので皆様も似たような現象がありましたら、「schema.rb」を見てみてください。 見てくださった皆様、お付き合いありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#2 SinatraでActiveRecordを使わずに掲示板アプリを作ってみた

前回rubyでSQL文発行して、データベースを操作するノリが分かってきたので、今回は これのコードリーディングをやっていきたいと思います。 (的外れな可能性大なので鵜呑みにしないでください。あくまで軽いメモ用です。。) モデルから見ていく models/db.rb require 'mysql2' class DB def self.query(sql) client.query(sql, symbolize_keys: true) end private def self.client @client ||= Mysql2::Client.new(host: 'localhost', username: 'root', database: '0ch') end end client.queryはなんか前回出てきたやつですね 前回は、client = Mysql2::Client.new(host: "localhost", username: "root", password: '', database: 'mysql') こんな感じで定義されていたと思います。 クライアント、いわゆるどこにどんなユーザー情報、パスワードでデータベース(MySQL)に接続するのかを提示します。 どんなクライアントかはまだ定義してないですね。 symbolize_keyはハッシュ のキーをシンボルにするメソッドらしい。(いやオプションかもしれん) なんでこれをつけなければいけないのかが全く分からない。 def self.client @client ||= Mysql2::Client.new(host: 'localhost', username: 'root', database: '0ch') end ここでどんなクライアントかを定義しますと んで、@clientの中身に何かあればそれ使って、なかったクライアントを新たに生成する的な。 ||=と書くことで、データベースへの問合せを最小限にしています。 とにかくクライアントを定義するメソッドと、クエリをデータベースに投げるメソッドがあるということです。理解度は全然ですが、とりあえず次。 models/post.rb なんだか投稿に関するモデルっぽいですね〜 require_relative 'application_entity' class Post < ApplicationEntity MIN_SIZE = 1 MAX_SIZE = 140 attr_reader :name, :email, :body, :topic_id, :id, :created_at def initialize(name: nil, email: nil, body:, topic_id:, id: nil, created_at: nil) @name, @email, @body, @topic_id, @id, @created_at = name, email, body, topic_id, id, created_at end def self.of_topic(topic_id) DB.query("SELECT * FROM posts WHERE topic_id = #{topic_id}").map { |hash| new(hash) } end def save validate DB.query("INSERT INTO posts (name, email, body, topic_id, created_at) VALUES ('#{@name}', '#{@email}', '#{@body}', '#{@topic_id}', NOW())") end def validate unless @body.size >= MIN_SIZE && @body.size <= MAX_SIZE raise Invalid, "本文は#{MIN_SIZE}文字以上、#{MAX_SIZE}文字以下で指定してください" end end end 'require_relative 'application_entity'は一旦置いといて、 attr_reader :name, :email, :body, :topic_id, :id, :created_at とはなんぞや。と、attr_accessorは知っとるけど、attr_readerは知らんぞと https://qiita.com/aberyotaro/items/626a88388d44802240a0 が分かりやすかったので、拝見してみた。 attr_readerはインスタンス変数の読み出し専用アクセサを定義できる。 はい、アクセサとはなんやねん。と インスタンス変数の値を読み書きするメソッドのこと。 Rubyはそのままではインスタンス変数にアクセスできない仕様になっています。 もっというとruby はclassの外からインスタンス変数を参照、再定義できないので、 それらをしようとしたときにアクセサメソッドが必要なのです。 今回は、参照するだけで、一度投稿した投稿は編集できない感じだと思うんで、 attr_readerなのでしょう これでpostの属性を一気に定義できる。便利やのう initializeメソッドで @name, @email, @body, @topic_id, @id, @created_at = name, email, body, topic_id, id, created_at で一気に定義できるのも初めて知った。  def self.of_topic(topic_id) DB.query("SELECT * FROM posts WHERE topic_id = #{topic_id}").map { |hash| new(hash) } end で、さっきのDBクラスのqueryメソッドを呼んでるって感じです。 こないだやった通り、生SQLが書いてありますね、訳してみると postsテーブルの全情報を取得、ただし条件はトピックidが◯のトピックの投稿だけを取得してきてねーー。 って感じですね。 topic_idがいつ、どの瞬間に入るのかがイメージできないですが、一旦次。 map { |hash| new(hash) } ですが、これはよくわらかなくて、取得した投稿全部をハッシュ化するのでしょうか、、、? なぜハッシュ化するのかよく分からないので、次。 って思ったのですが、単純に、取得したデータからインスタンスを生成してるだけでした。 なぜhashという変数名にしたのかは、あとで谷道さんに聞くことにしましょう。 考えてみれば、データベースから取得したデータをそのまま使えるわけではなく、 インスタンス化しないことには、ruby内でそのデータを使えないってわけですね。 railsではそんなことを意識せずともなんとなくアプリが作れてたので、 感動するとともに、そりゃ実力つかんわーー。とも思った。 アンチrailsになりそうな気持ちを沈めつつ次へ。 def save validate DB.query("INSERT INTO posts (name, email, body, topic_id, created_at) VALUES ('#{@name}', '#{@email}', '#{@body}', '#{@topic_id}', NOW())") end 最初にvalidateを呼び出していますが、validateメソッドは後々定義するから一旦飛ばして、 NOW()メソッドは、現在時刻を取得するMySQLのメソッドらしいです。 def validate unless @body.size >= MIN_SIZE && @body.size <= MAX_SIZE raise Invalid, "本文は#{MIN_SIZE}文字以上、#{MAX_SIZE}文字以下で指定してください" end end そして、肝心のvalidateメソッド raise Invalidってのが引っかかった。raiseは例外処理を発生させるメソッドらしいが、 Invalidが何やと。その答えは後々登場。 MIN_SIZE MAX_SIZEを変数にすることで後から、やっぱ最大文字数200文字で!って言われたときも変更に対応しやすいコードになってます。 こういった細かい工夫も注目しつつ次いきましょう。 models/topic.rb require_relative 'application_entity' class Topic < ApplicationEntity MIN_SIZE = 1 MAX_SIZE = 50 attr_reader :title, :id, :created_at, :updated_at def initialize(id: nil, title:, created_at: nil, updated_at: nil) @id, @title, @created_at, @updated_at = id, title, created_at, updated_at end def self.all DB.query('SELECT * FROM topics ORDER BY updated_at DESC').map { |hash| new(hash) } end def self.find(id) result = DB.query("SELECT * FROM topics WHERE id = #{id} LIMIT 1").first new(result) end def save validate DB.query("INSERT INTO topics (title, created_at, updated_at) VALUES ('#{@title}', NOW(), NOW())") end def validate unless @title.size >= MIN_SIZE && @title.size <= MAX_SIZE raise Invalid, "タイトルは#{MIN_SIZE}文字以上、#{MAX_SIZE}文字以下で指定してください" end end end てか、どのクラスもApplicationEntityを継承してるってことに今気づいた。 そのクラスも後々登場してきます。 result = DB.query("SELECT * FROM topics WHERE id = #{id} LIMIT 1").first .fitstがなぜあるのか、 配列の先頭の要素を返します。要素がなければ nil を返します と書いてあったが、なぜこのメソッドが必要なのかがイメージできてない。 取得したいデータがなかった場合にもエラーを起こさないためなのか。 未来の自分が解決してくれるだろう。 LIMIT 1は取得するデータの行数を制限。と書いてあった。 "行数"を制限という言い回しが気になるが、単純に取得するデータの個数を制限してるって感じでいいんすかね。 トピックがなぜ一個しか取得できない仕様なのかがよく分からない。 多分、トピックが被らないようにするため、、、?? まぁなんとなくイメージができたんで次。 application_entity.rb post.rbとtopic.rbの継承元となっていた、モデルですね。 require_relative 'db' class ApplicationEntity class Invalid < StandardError end end お、見覚えがあるInvalidが出てきた。 しかもStandardErrorを継承している。。。 Invalidクラスに何も書かないなら、raise Invalidとかじゃなくて、 railse StandardErrorでええやん。とか Post < StandardErrorでええやん。とか思ったりしてる。 なんでやねん。。。。調べてみると、、 StandardErrorのスーパークラス(親クラス)がExceptionらしい。 https://yarb.hatenadiary.org/entry/20121005/p1 https://qiita.com/kasei-san/items/75ad2bb384fdb7e05941 この記事出てきたが、rescueに関係ありそうなので、一旦置いといて、 raiseは、プログラムの中で意図的に例外(エラー)を発生させるときに使います。 と書いてあった。 んーー、でもなぜStandardErrorをInvalidに継承させる必要があるのかが、分かりませんねー。 二度手間やん。って初心者は思っちゃう。 まぁ、理解はそこそこに全体像をつかみたいので、今回はこんな感じで。 #3はこちら
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sinatraでActiveRecordを使わずに掲示板アプリを作ってみた

プロローグ Rails今までやってきて、あまり基礎力というか、地力ついた感じしないんすけど、何やったらいいすかねーーー。。。ってruby-jpに相談したら、 https://github.com/ttanimichi/0ch#sinatra%E3%81%A7%E6%8E%B2%E7%A4%BA%E6%9D%BF%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86 この課題に取り組んでみてください。 とアドバイスをいって頂いた。 この課題を見てみると、ActiveRecordを使わずに、生SQLを書いて掲示板アプリを作るという指定があった。 そんなことやったことがないので、早速詰んだ。 def save validate DB.query("INSERT INTO posts (name, email, body, topic_id, created_at) VALUES ('#{@name}', '#{@email}', '#{@body}', '#{@topic_id}', NOW())") end 多分だけど、この生SQLを書けば、ActiveRecord使わずとも、データベースとやり取りができそう。 ActiveRecordのsaveメソッドがそこら辺をよしなにやってくれてたと思うと、そりゃ実力付かんわ。 と改めて反省。 何はともあれ、ActiveRecordを使わずにデータベースを操作する練習をしなきゃならんので、 https://qiita.com/toshiro3/items/b65b2ad744d8f3ecc734 この記事をやってみることに。 この記事通りだとうまく行かないことあるので、 補足させていただくと まず、CREATE DATABASE test; を実行しないと、 create table test.languages (id int, name varchar(32)); これでエラー出るようです。 CHAR 型は指定した文字数以下の文字を格納した場合には文字列の末尾に空白を必要なだけ付け加えて指定の長さの文字列として格納します。ただし値を取得する場合は末尾にある空白は全て削除された上で取得されます。比較される時も同じです。 VARCHAR 型は末尾に空白を付けるようなことはしません。また現行のバージョンでは末尾に空白がある文字列であっても空白が付いたまま格納されます。取得する時も空白付きで取得しますが、 WHERE 句で比較する時だけ末尾の空白を削除した上で比較されます。 引数には、最大文字列を指定してるっぽい。 https://www.dbonline.jp/mysql/type/index3.html 引用 require 'mysql2' client = Mysql2::Client.new(:host => 'localhost', :user => 'root', :password => 'password') query = %q{select user, host from test.languages} results = client.query(query) results.each do |row| puts "--------------------" row.each do |key, value| puts "#{key} => #{value}" end end これだとエラー出るので、 require 'mysql2' query = %q{select * from test.languages} に変更。 てか、require 'mysql2' って書いた時点で、mysql使えるのはしゅごい。 Macにmysqlをインストールしたからなのは分かってるけど。。。。 そこら辺を上手いこと参照してくれるのは驚き。 将来の成長した自分が、そこら辺の疑問点を解決してくれることを願って、先に進めよう。 あと %q{}って記法がよく分からないので、調べてみると https://qiita.com/mogulla3/items/46bb876391be07921743 シングルクオートやダブルクオートのエスケープが不要になる。 うん、意味が分からん。 https://blog.senseshare.jp/escape.html を参考にして説明すると、 エスケープ処理とは、プログラムの中で使う特殊な記号を「ただの文字」として扱いたい時に行う処理です。 とありました。なるほど、なるほど。 次回はいよいよ https://github.com/ttanimichi/0ch#sinatra%E3%81%A7%E6%8E%B2%E7%A4%BA%E6%9D%BF%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86 この課題のコードリーディングで基礎力や地力をつけていきたいと思います。 #2はこちらから
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQL[CRUD処理]

ドットインストール(MySQL)とスッキリわかるSQL入門の学習を進めている初学者です。 アウトプットのために、Qiitaに投稿します。 訂正箇所などがあれば、随時教えて頂けると幸いです。 MySQLとは RDBMS(Relational DataBase Management System) →情報を使いやすく表形式で整理整頓してある箱 OSS(Open Source Software) →コードを無償公開している。 主に出来ることは データのCRUD処理 C(作成),R(検索),Update(更新),Delete(削除) テーブルの作成、削除、結合など データベースの用語 olinpiansテーブル id name sport 1 大橋 競泳 2 伊藤 卓球 3 橋本 体操 4 高橋 柔道 表形式でデータが管理される。 表のことを テーブル   例)olinpians Table 列のことを カラム    例)id,name,sport 行のことを レコード   例)1 大橋 競泳 テーブル作成 SQL(Structured Query Language) 問い合わせ言語を用いて、データベースを作成。 データベースに問い合わせをするという意味でクエリと呼ばれる。 CREATE TABLE テーブル名(カラム設定); $ CREATE TABLE olinpians( id INT NOT NULL AUTO_INCREMENT, // 連続した数値を自動的に生成する name VARCHAR(20), // 20字の制限 sport VARCHAR(10), // 10字の制限 PRIMARY KEY(id) // 一意に識別するための設定 ); 空のテーブルが作成出来ました。 テーブルの構造の確認、テーブルの一覧を見たい場合は以下のクエリを実行 $ DESC olinpians; // テーブルの構造チェック $ SHOW TABLES; // テーブル一覧チェック id name sport 空のolinpiansテーブルが確認出来ます。 テーブルの削除 テーブル削除のクエリ csharp: $ SHOW TABLES; // 念の為テーブルを確認 $ DROP TABLE olinpians; データの挿入と確認 データの挿入のクエリ INSERT INTO テーブル名(カラム名) VALUES(値); $ INSERT INTO olinpians (name, sport) VALUES('大橋', '競泳'); // 競泳の大橋選手を登録 テーブルのデータを確認するクエリ SELECT カラム名 FROM テーブル名 $ SELECT * FROM olinpians; *をカラム名に設定することで、全てのデータを抽出出来ます。 結果は以下のようになるはずです。 id name sport 1 大橋 競泳 データの更新と削除 データの更新をしたい時は以下のクエリを実行 UPDATE テーブル名 SET カラム名 = 新規内容 WHERE カラム名 = 変えたい値; $ UPDATE olinpians SET name = '本田' // 本田選手に変更したい WHERE name = '大橋'; // 大橋選手から id name sport 1 本田 競泳 では、データを削除しましょう、 データ削除の時は以下のクエリを実行 DELETE FROM テーブル名 WHERE カラム名 条件に当てはまるデータを削除します。 $ DELETE FROM olinpians // olinpianテーブルから削除 WHERE id = 1; // idが1のデータ id name sport 空っぽになりました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MariaDB の LIMIT 句や OFFSET 句には指定できる限界値がある

MariaDB に限らず、MySQL や PostgreSQL の場合にも限界値はあるようだが、今回は MariaDB でのみ検証を実施。 環境 MariaDB 10.4.11 発端 ページネーション用の OFFSET を GET パラメータより受け取るよくある検索画面にて、膨大な数を指定された際にデータベースエラーが発生した。 これまで意識したことが無かったが、そりゃあ限界値あるよね。 検証 LIMIT 句の場合 MariaDB [testdb]> SELECT * FROM users LIMIT 18446744073709551615; +----+-------+-------------------+-------------------+----------+------------+----------------+---------------------+---------------------+ | id | name | email | email_verified_at | password | logined_at | remember_token | created_at | updated_at | +----+-------+-------------------+-------------------+----------+------------+----------------+---------------------+---------------------+ | 1 | user1 | user1@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 2 | user2 | user2@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 3 | user3 | user3@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 4 | user4 | user4@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 5 | user5 | user5@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 6 | user6 | user6@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 7 | user7 | user7@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 8 | user8 | user8@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | | 9 | user9 | user9@example.com | NULL | | NULL | NULL | 2021-07-29 00:00:00 | 2021-07-29 00:00:00 | +----+-------+-------------------+-------------------+----------+------------+----------------+---------------------+---------------------+ 9 rows in set (0.00 sec) MariaDB [testdb]> SELECT * FROM users LIMIT 18446744073709551616; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '18446744073709551616' at line 1 OFFSET 句の場合 MariaDB [testdb]> SELECT * FROM users LIMIT 1 OFFSET 18446744073709551615; Empty set (0.00 sec) MariaDB [testdb]> SELECT * FROM users LIMIT 1 OFFSET 18446744073709551616; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '18446744073709551616' at line 1 結論 符号なし BIGINT の最大値「18446744073709551615」まで指定可能。 直接的な公式ドキュメントの記載は発見できなかったが、以下の情報を集約する限り間違っていないかと思われる。 特定のオフセットから結果セットの最後までのすべての行を取得するために、2 番目のパラメータにある程度大きい数字を使用できます。 次のステートメントは、96 行目から最後の行までのすべての行を取得します。 SELECT * FROM tbl LIMIT 95,18446744073709551615; SELECT に LIMIT 句がある場合、LIMIT が sql_select_limit の値に優先されます。 MariaDB [testdb]> SHOW variables LIKE 'sql_select_limit'; +------------------+----------------------+ | Variable_name | Value | +------------------+----------------------+ | sql_select_limit | 18446744073709551615 | +------------------+----------------------+ 1 row in set (0.00 sec) 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む