20220113のMySQLに関する記事は5件です。

rails db:migrateを実行すると、Warning: the running version of Bundlerと警告が出る

データベースを更新し、usersデータモデルを作成するために下記を実行したところ、、 % rails db:migrate Warning: the running version of Bundler (2.2.32) is older than the version that created the lockfile (2.2.33). We suggest you to upgrade to the version that created the lockfile by running `gem install bundler:2.2.33`. と警告が出る。 ↓ ``` % gem install bundler:2.2.33 Fetching bundler-2.2.33.gem Successfully installed bundler-2.2.33 Parsing documentation for bundler-2.2.33 Installing ri documentation for bundler-2.2.33 Done installing documentation for bundler after 3 seconds 1 gem installed ``` この状態で再度 rails db:migrate を試すも、、 % rails db:migrate Running via Spring preloader in process 1788 == 20220110000241 CreateUsers: migrating ====================================== -- create_table(:users) rake aborted! StandardError: An error has occurred, this and all later migrations canceled: you can't redefine the primary key column 'id'. To define a custom primary key, pass { id: false } to create_table. /Users/chiharatomoya/Desktop/portfolio/mo-vie/db/migrate/20220110000241_create_users.rb:4:in `block in change' /Users/chiharatomoya/Desktop/portfolio/mo-vie/db/migrate/20220110000241_create_users.rb:3:in `change' <internal:/Users/chiharatomoya/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require' <internal:/Users/chiharatomoya/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require' -e:1:in `<main>' 調べてみたのですが、idをわざわざ定義しようとしなくても、勝手にidは反映されるので再定義しなくていいとのこと。 なので、idを定義していた一文を消します。(画像) https://gyazo.com/5f17f452baa250030e29241b3099b9d1 % rails db:migrate Running via Spring preloader in process 1973 == 20220110000241 CreateUsers: migrating ====================================== -- create_table(:users) -> 0.0043s == 20220110000241 CreateUsers: migrated (0.0047s) ============================= 問題なく実行できました。 一応rails sでサーバーを実行し、/usersを見てみます。 https://gyazo.com/4c30d2ccb3b720d429cf5873d5a1f5fb (userモデルが作成できました。)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ツイートを作成順ではなく、いいねした順に表示したい

概要 ツイート投稿機能とツイートへのいいね機能を持つアプリケーションを開発中、 いいねした順番にツイートを取得する方法について調べたのでメモ。 環境 ruby 3.0.2 rails 6.1.4 mysql 8.0.26 やりたいこと ツイートの作成順がデフォルトの時に、 ツイートの作成順ではなくユーザーがいいねした順にツイートを取得したい。 先に結論 reorderを使用し、中間テーブルのカラムを直接指定する users_controller.rb # ユーザー詳細画面で表示したい場合 def show @user = User.find(params[:id]) @favorites = @user.favorite_tweets.reorder('favorites.created_at DESC') end 以下、詳細 関連するモデル user.rb class User < ApplicationRecord has_many :tweets, dependent: :destroy has_many :favorites, dependent: :destroy has_many :favorite_tweets, through: :favorites, source: :tweet end tweet.rb class Tweet < ApplicationRecord belongs_to :user has_many :favorites, dependent: :destroy has_many :favorite_tweets, through: :favorites, source: :tweet # ツイートのデフォルトとしては投稿順に並べたいためここで指定 default_scope -> { order(created_at: :desc) } end favorite.rb class Favorite < ApplicationRecord belongs_to :user belongs_to :tweet end ER図 結論に至るまで コンソールで確認しつつ試行錯誤。 # userに一人目のユーザーを取得 user = User.find(1) # favoritesに、userがいいねしたツイートを取得 favorites = user.favorite_tweets これだと、tweetのデフォルトである、 tweetsテーブルのcreated_atカラムの降順 での取得となってしまう。 (このデフォルトはtweet.rbのdefault_scopeで指定しているもの) そもそもどんなクエリが発行されているのか? ActiveRecordで発行されるSQLを確認するのに、to_sqlという便利なメソッドがあるとのこと。 先ほどの中身を確認。 # userに一人目のユーザーを取得 user = User.find(1) # userがいいねしたツイートを取得するSQLを確認 user.favorite_tweets.to_sql # 見やすいよう改行 => "SELECT `tweets`.* FROM `tweets` INNER JOIN `favorites` ON `tweets`.`id` = `favorites`.`tweet_id` WHERE `favorites`.`user_id` = 1 ORDER BY `tweets`.`created_at` DESC" ORDER BY tweets.created_at DESC" とあるように、tweetsテーブルのcreated_atカラムをDESCで並べている。 指定したいのは ユーザーがツイートをいいねした順番 つまり、 中間テーブルのcreated_at なので、 上記ORDER BYの箇所を ORDER BY favorites.created_at DESC にできればいいのでは? defaultを上書きしたい # userに一人目のユーザーを取得 user = User.find(1) # userがいいねしたツイートを取得するSQLを確認 >> user.favorite_tweets.order('favorites.created_at DESC').to_sql # 見やすいよう改行 => "SELECT `tweets`.* FROM `tweets` INNER JOIN `favorites` ON `tweets`.`id` = `favorites`.`tweet_id` WHERE `favorites`.`user_id` = 1 ORDER BY `tweets`.`created_at` DESC, favorites.created_at DESC" ORDER BY tweets.created_at DESC, favorites.created_at DESC" .orderでは、デフォルトの後の指定として追加できるだけのよう。 ここで結論 reorderで初期化の上、順番を指定 # userに一人目のユーザーを取得 user = User.find(1) # userがいいねしたツイートを取得するSQLを確認 >> user.favorite_tweets.reorder('favorites.created_at DESC').to_sql # 見やすいよう改行 => "SELECT `tweets`.* FROM `tweets` INNER JOIN `favorites` ON `tweets`.`id` = `favorites`.`tweet_id` WHERE `favorites`.`user_id` = 1 ORDER BY tweet_bookmarks.created_at DESC" 無事、意図通りのいいね順で取得することができた。 参考にした記事 reorder含む、default_scopeの初期化 【Railsドキュメント】reorderについて 最後に より良い方法や間違い等ありましたらご指摘いただけますと幸いです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【個人開発】MySQLにCRUDできるノーコードアプリをRailsで作ってみた

個人開発で作ったサービス【shareCRUD】を先日ベータ版にて公開しました。この記事は、個人開発でサービス作ってる・作りたいけど、事例を参考にしたい人向けに、開発したサービスのご紹介と、それを作るまでの経緯をまとめてみました。 作ったサービス【shareCRUD】 サイトはこちらです→https://sharecrud.com アプリ化したいDB(MySQL)につなげて、必要な設定をすると、ブラウザからGUIでCRUD(登録・検索・更新・削除)できる機能が作れます。イメージとしては、phpMyAdminみたいな機能をノーコードで作れるサービスです。 どんなシーンで役に立つか? 1. プロダクトの運営初期から「管理画面」が手に入る 例えば「toC向け」Webサービスの場合、初期の開発ではフロント向けに専念し、管理画面は作らず直接DBにつなげての運用も多いと思います。shareCRUDでDBを操作できるアプリを作れば、開発コストをかけずに管理画面に似た機能が手に入るので、エンジニアでない方でもデータの管理が可能になります。 2. 管理画面とshareCRUDの「二刀流」で、効率的に運用できる ある程度成長したWebサービスでも、管理画面開発は運営上クリティカルな機能に限定し、一般的なデータの参照や更新はshareCRUDを使う「二刀流」にすることで、管理画面の開発コストを下げながら効率よくサービスを成長できます。 アイデア出しから実装までの道のり ここからは、個人開発ならではのエピソードも交えて、サービス開始までの経緯をまとめてみます。 サービスの「管理画面」に感じていた課題 開発途上のサービスの管理画面について 私は今回の開発以前にも、いくつかの個人開発をしてサービスを作ってきましたが、toC向けサービスはフロント向け機能のみ作り、管理画面は作らずDBを直接参照して対応していました。小規模のサービスでも、非エンジニアの方が運営するには、DB直接参照というわけにも行かないので、簡易な管理ツールを作るか、開発元のエンジニアにメンテを依頼もあると思われます。 過去にActiveAdminなどの利用もしましたが、導入にも環境構築にもそれなりにコストがかかり、私個人としてはあまり好みではありませんでした(一個人の意見です) 小規模で開発途上のサービスの場合、一定量は管理画面がないのではと予想しています。 成長したサービスの管理画面について 以前お世話になった自社サービスを運営している会社では、サービスは成長しているので管理画面も存在し、非エンジニアの方がオペレーションを担っています。しかし、管理画面ですべて対応はできておらず、ちょいちょいエンジニアに依頼が入ってデータメンテをしていました。依頼にすぐ対応ができなかったり、作業が中断したりで、もどかしい部分がありました。 普段の業務から得た着想 一方で、私は普段フリーで受託開発をしていて、業務システムや管理画面をRailsで作ることが多いです。業務・管理画面系のシステムは共通化できる部分が多いので、自分なりにフレームワーク化していました。モデリングした内容をフレームワークに落とし込むと、ベースとなるシステムができます。落とし込むと言っても、案件の都度、決まった流れのコードを手動で書いてたので、これを自動化できれば、管理画面に代替する機能をノーコードで作れるかもと考えました。 ノーコードに対する不信感と向き合う 実は「ノーコード」のサービスにはあまり良いイメージがありませんでした。「エンジニアいらずで、なんでも簡単につくれる」といった謳い方をしているサービスが多いように感じ、違和感を感じました。これからノーコードを作ろうとしているくせに、ノーコードツールにあまりよいイメージがないのはなんとも矛盾していますね そこで、自分がノーコードを作るのなら、この点にきちんと向き合おうと思いました。具体的には なんでもできそうなアプリではなく、CRUDが主目的なことを明確にする 基盤をエンジニアが設定をして、運営者がエンドユーザーになる使い方を想定 といった点です。以上から「DBにCRUDできるアプリをノーコードで生成するプラットフォーム作り」とのアイデアで実装を進めることとしました。 技術的な実現方法を検討 ここからは技術調査です。私にはノーコードツールの開発経験は無かったので、まず実現方法から考えました。といっても、このタイミングで一から新たな技術を学ぶというより、その時点で自分ができることを応用できればと思いました。 RailsのScaffoldから着想を得て、Thorを使うことにした Railsには、コマンドから雛形となるソースコードを生成できる機能(ジェネレータ)があります。scaffoldではベースとなるソースコードを生成しているので、この機能を応用してコードを自動生成すれば、ノーコードのエンジンが作れると考えました。 Railsでジェネレータは普段から使っていましたが、具体的にどのような仕組みで実現しているか把握していませんでした。調査すると「Thor」というツールの上に成り立っていることを知りました。 以下のドキュメントに大変お世話になりました。 また、Rails自体のGenerators部分のコードも大変参考になりました。 ソースコード生成までのフローをまとめる Thorを使って生成する部分はイメージできたので、システムの具体的な設計をしました。以下のフローで実現を図りました。 ① DBの接続情報を入力して、テーブル定義などを読み取る 主に以下の情報を取得しています。 テーブルとフィールド名、型の取得 主キーやNotNull、一意制約、AUTO INCREMENTなどの取得 他テーブルとの外部キー、など ② 読み取ったテーブル定義をもとに、アプリの設定をする 画面から以下のような設定をしてもらいます。 テーブルに対する設定 フィールドのlocale(和名)を設定 表示フォーマットや単位の定義 バリデーションの追加(文字数や最大・最小値など) enumなどの区分値に対する表示名の定義、など アプリに対する設定 検索条件の定義 一覧や詳細画面に表示するフィールド、表示順序 登録フォームのパーツ選択(ラジオボタン or ドロップダウンなど) リレーショナル(1:n)への、親・子データの扱い、など ③ ②で登録した設定内容をもとに、ビルド処理でソースコードを生成する Thorを使って各ファイルを作っていきます。一例ですが、モデルのファイルを生成する場合、以下のようにしています。 ※説明用にアレンジしています。 model.rb.tt <%-# このファイルをテンプレートにして、テーブルごとにmodelファイルを作成しています -%> <%-# @modelは、上記①②で設定したテーブル情報を保持しています -%> class <%= @model.name %> < SharecrudAppModelBase self.primary_key = '<%= @model.pk_column.name %>' <%- @model.columns.select { |c| c.kind_enum? }.each do |column| -%> <%-# コードの文字列が返ってくるメソッドを定義してます-%> <%= column.enum_code -%> <%-# ↑例えば enum gender: { man: 1, woman: 2 } 的なコードが挿入されます -%> <%- end -%> <%- @model.columns.select{ |c| c.unique? }.each do |unique_column| -%> validates :<%= unique_column.name -%>, uniqueness: true <%- end -%> <%- @model.columns.select{ |c| c.kind_number? }.each do |c| -%> <%= c.number_validates_code -%> <%- end -%> ... end model_generator.rb ### 上記テンプレートを呼び出すgeneratorを定義します module Sharecrud class ModelGenerator < Rails::Generators::NamedBase def setup @model = Model.includes(:columns).find(name.to_i) end def create_model_file base_path = "tmp/product/#{@model.project_code}/app/models" model_file_path = File.join(base_path, "#{@model.name.underscore}.rb") template "model.rb", model_file_path, encoding: :utf8 end ... end end そして、ビルド処理の中で Rails::Generators.invoke('sharecrud:model', [model.id.to_s], destination_root: Rails.root) といった形でGeneratorをキックして、テーブルごとにModelのファイルを生成しています。 同様な仕組みで、他にもアプリごとにViewやControllerなどを生成しています。 ノーコード(自動化)の対象をどこまでとするか ソースコードは前述の仕組みでノーコード化できそうですが、生成したコードを動かす「環境」について、自動化の対象に含めるか迷いました。当初は、新規ユーザーが利用する際は、まずお問い合わせをもらい、私が手動で環境を構築してから利用開始のフローを計画していました。個人開発でリソースも限られることから、まずはソースコード自動生成に重点を置き、その他は当面手動でもよいかなと。 しかし、企業が運営するプロダクトであればまだしも、個人開発みたいなプロダクトに対して、機能を試すためにお問い合わせまで要するというのは、ユーザーにとって相当なハードルとなり、結果誰も使ってくれないサービスになると考えました。 そこで、アカウント登録したら、すぐにアプリを使えるフローを目指しました。開発に要する作業量はかなり増えましたが、この実現は必須だったと感じています。個人開発だからやらなくてよいことと、個人開発だからこそやらなきゃいけないこと、この切り分けは重要だと感じました。 Dockerコンテナを使って環境構築を自動化 いくつかの実現方法を試し、最終的にはアプリごとにDockerコンテナをポコポコ立ち上げるようにしました。アプリのベースとなるイメージを一つ作成し、生成したソースコードをアプリ専有のコンテナに COPY してから起動し、リバースプロキシを窓口にしてサブドメインごとにコンテナに振り分けています。 また、気軽に試せるようにしたことで「少し試して終わる」アプリが増えることが予想されます。何も対策をしないと、使われなくなったアプリでサーバーのリソースを使い切ってしまうため、一定期間リクエストが無いアプリは自動でコンテナを停止し、改めてリクエストが来た際にコンテナを自動起動するようにしました。 一つのサーバー上にコンテナをたくさん立ち上げる方式のため、今後サービスがスケールしたら課題が残りますが、将来そんな嬉しい事象が見えてきたら、その時検討しようと思っています。 最終的にRailsのプロジェクトは3つになった 以上の機能を実現するために、Railsのプロジェクトを3つにわけました。 エンジン用プロジェクト アプリの設定入力画面 ビルド・デプロイ機能 アプリ用テンプレートプロジェクト アプリの共通機能などを管理 プロジェクトをDockerイメージにして、アプリごとにコンテナを起動する エンジン用プロジェクトで生成したソースコードをアタッチする リクエスト振り分け用プロジェクト リクエストのサブドメインから、振り分け先のアプリコンテナを特定する コンテナが停止していたら起動する 一定期間リクエストがないコンテナを停止する ドキュメントとチュートリアル用のコンテンツ作成 サービス運営に向けて、LPとドキュメント用サイトを作りました。LPは多くの個人開発でも作ると思いますが、ツール系のサービスなので、ドキュメントサイトも必要だと考えました。せっかく興味をもってくれたのに、使い方がわからずに離脱してしまうユーザーを少しでも減らせたらと思います。まだまだコンテンツ量が少ないですが、今後拡充させていければと思っています。 https://docs.sharecrud.com このドキュメントには、チュートリアルとサンプルDBも用意しました。サービスの特性上、ユーザーのDBに接続する必要がありますが、仮に試用であっても、初見のサービスを自分のDBにつなげることには抵抗があると予想します。そこで、チュートリアルでサンプルDBも公開し、そこに接続して試した後であれば、自分のDBに接続するハードルを下げられるのではないかと考えています。 ドキュメントサイトにはVuePress + AWS Amplifyを採用 ドキュメントサイトを作る際、以下の条件にマッチするサービス/ツールを探しました。 マークダウンで記述できる ドキュメントとして使えるUI 動作環境も簡単に作れる 当初は WordPress や GitBook なども検討しましたが、VuePress が今回のニーズに一番あってると判断しました。また、環境構築は AWS Amplify で速攻ででき、感動しました。このあたりは後日別記事でまとめられたらと思います。 ベータ版の開始 〜 サービスの今後 以上の紆余曲折を経て、先日やっとベータ版として公開することができました。文章にまとめるとスムーズに行ったような雰囲気がありますが、実際は苦難の連続でした。本業が忙しいために個人開発に時間を割けない時期もあったとはいえ、当初の着想からトータルで1年くらい要してしまいました。ずいぶんと時間がかかってしまい、リーン開発でいう「MVPを作ってすぐに検証」の定石からは道を外しまくってます。途中何度も辞めようと思いました。 ベータ版で少しでも多くの方にお試しいただき、目処が立ったタイミングで正式リリースの流れを計画しています。これからは、このサービスのプロモーションにも力を入れていこうと思っています。 おまけ - 周りの意見を聞くために、Zoomインタビューをしてみた 個人開発は孤独です。一人で思考していると、どんどん煮詰まって悪循環に陥るときがあります。そんな時に、一人で考えていては単なる想像の世界を抜け出せないと思い、他のエンジニアの方の意見を聞いてみたいと感じました。 そこでクラウドソーシングの「ランサーズ」を使って、エンジニアの方にお声掛けし、有償でインタビューをさせてもらいました。私自身インタビューの経験はなかったのですが、コロナ禍の影響で「Zoomを使ってミーティングする」ことが当たり前になっていたので、検索したエンジニアの方に依頼すると、結構な確率で快諾してくれました(このときインタビューさせてもらったエンジニアの方々には大変感謝しております。) もちろんインタビューをして、それだけですぐに答えが見つかるほど甘くはありません。ましてや私みたいな素人では、インタビューしても何も引き出せないのではと懸念しましたが、他の方と話すことで、以下のメリットがありました。 思考を整理できたので、気持ちが前向きになった 会話の流れで、見落としていた発想を得られた Zoom等でインタビューして、他の人に話したり意見を聞くことは、手軽に大きな効果を得られる場合もありそうです。個人開発では一つの有効な手段かもしれません。 おわりに 長文にお付き合いいただき、ありがとうございました! 現状の反省点としては、個人開発なのに選択したテーマが重く、開発に時間がかかりすぎてしまった点です。個人開発では、アイデアもさることながら、実現に要するボリュームも見極める必要がありそうです。長くても数ヶ月でリリースまでたどり着くほうが、精神的にも健全です。 この記事を見て、個人開発の参考やモチベーション維持に少しでも貢献できたらとても嬉しいです。 最後に、shareCRUDを是非お試しください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

django.db.utils.OperationalError: (2002, "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)")

目的 djangorestframeworkを利用してAPIを作成しようとした. 既存のsqliteではなく、MySQLを使ってみようと思い、python manage.py runserverを実行してみた。 すると下記のエラーに苦しめられた。 Can't connect to local MySQL server through socket '/tmp/mysql.sock 結論 Can't connect to local MySQL server through socket '/tmp/mysql.sock このエラーは $ mysql.server start で解決できた。 実施環境 ハードウェア環境 項目 情報 OS macOS Catalina(10.15.7) ハードウェア MacBook Air (11-inch, Early 2015) プロセッサ 1.6 GHz デュアルコアIntel Core i5 メモリ 4 GB 1600 MHz DDR3 グラフィックス intel HD Graphics 6000 1536 MB ソフトウェア環境 項目 情報 homebrew 3.3.8 mysql Ver 8.0.27 for macos10.15 on x86_64 python 3.8.12 django 3.0.0 anaconda 4.10.1 pip 21.2.4 原因究明 Can't connect to local MySQL server through socket '/tmp/mysql.sock こちらのエラーを日本語に直して考えてみると、socketを通してMySQLサーバーにアクセスできないと言っている。 必要な設定などは済んでいるのになんでだろう。 この記事などを参考に、djangoのsettings.pyを変更などしてpython manage.py runserverをもう一度を実行するもエラーに苦しめられる。 しかしよく考えるとMySQLを接続するのにMySQLを起動しているのか?と気づいた。 ここで指摘されているように、MySQLの起動ができていなかった。 $ mysql.server start を行い、MySQLを実行した後にもう一度 python manage.py runserver を実行する。 MySQLにログインする。 mysql -h localhost -u root 成功。 参考 Django の runserver 立ち上げたら "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)" とかなる場合のメモ Can't connect to local MySQL server through socket '/tmp/mysql.sock
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】mysql2のインストールができない場合の対処法【MySQL】

はじめに  本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。  そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。  間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。 mysql2のインストールができない場合の対処法 環境 OS: MacOS Big Sur 11.6.1(M1 mac) Ruby: 2.7.5 Rails: 5.2.6 MySQL: 5.7(8.0でも確認しました。) 状況 データベースをMySQLに指定した上でrails newをした後にbundle installをしても以下のような文章が出力され、インストールできませんでした。 また、インストールができてもrails sをした際にLoad Errorが出てしまう状況でした。 linking shared-object mysql2/mysql2.bundle ld: library not found for -lzstd clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [mysql2.bundle] Error 1 make failed, exit code 2 Gem files will remain installed in /Users/taichi/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3 for inspection. Results logged to /Users/taichi/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-21/2.6.0/mysql2-0.5.3/gem_make.out An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue. Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling. In Gemfile: mysql2 解決した方法 私の場合には、以下の方法で解決しました。 openssl@3とzstdをインストール $ brew install openssl@3 zstd openssl@3のパスを通す $ echo 'export PATH="/opt/homebrew/opt/openssl@3/bin:$PATH"' >> ~/.zshrc LIBRARY_PATHにzstdを追加する $ export LIBRARY_PATH=$LIBRARY_PATH:$(brew --prefix zstd)/lib ld-flags に openssl@3/libを追加する $ bundle config --local build.mysql2 "--with-ldflags=-L$(brew --prefix openssl@3)/lib" ※.bundle/configに   BUNDLE_BUILD__MYSQL2: "--with-ldflags=-L/opt/homebrew/opt/openssl@3/lib" と記述されているのを確認する。 bundle installする $ bundle install
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む