20210914のRubyに関する記事は11件です。

文字列と数値はそのままでは連結できない!?

◼️ タイトルにもある通り、文字列と数値は連結できない。もし、文字列と数値を連結したいなら下記の書き方を覚える必要がある。 書き方:  puts "1日は" + (24 * 60 ).to_s + "分です。" 上記のように数字の値の辺りに( ).to_s という記号を加えるだけでOK!! 今日の投稿は以上です。 wagaでした!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング学習履歴

2020年4月〜7月 Progate:HTML,CSS,JavaScript,Ruby,Ruby on Rails,Command Line,Git,SQL ドットインストール はじめてのHTML はじめてのCSS 詳解HTML 基礎文法編 詳解CSS 基礎文法編 Visual Studio Code入門 はじめてのJavaScript 詳解JavaScript 基礎文法編 詳解JavaScript オブジェクト編 詳解JavaScript DOM編 Ruby入門 MySQL入門 基礎編 2020年8月〜12月 テックキャンプ 2021年1月〜2月 1つ目のポートフォリオ作成 2021年2月〜3月 キタミ式イラストIT塾 基本情報技術者 Linux標準教科書 新しいLinuxの教科書 Udemy:Git:はじめてのGitとGithub Ruby on Railsチュートリアル Amazon Web Services 基礎からのネットワーク&サーバー構築 2021年4月〜6月 2つ目のポートフォリオ作成 使用技術 フロントエンド HTML/CSS JavaScript jQuery tailwindcss(1.9.0) バックエンド Ruby(3.0.0) Ruby on Rails(6.1.3) MySQL(8.2.3) インフラ heroku(開発初期) AWS(VPC/EC2/S3/RDS) Nginx(Webサーバー) Puma(アプリケーションサーバー) テスト RSpec CI/CD CircleCI(自動テスト) Capistrano(自動デプロイ) Rubocop(コーディングチェック) バージョン管理 Git/GitHub 開発環境 VScode Docker docker-compose 2021年7月 paiza Cランク問題達成 Bランク問題挑戦も未達成 Udemy 超Vue.js 2 完全パック (Vue Router, Vuex含む) Nuxt.js入門決定版!Vue.jsのフレームワークNuxt.jsの基本からFirebaseと連携したSPAの開発まで 2021年8月〜現在 転職活動 3つ目のポートフォリオ作成 使用技術 フロントエンド Nuxt.js バックエンド Ruby on Rails(APIモード)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[RSpec]いいね機能の単体テストについて

はじめに 本記事では、いいね機能のテストについて記述します。 いいね機能のテストコードを書いておりました。 前提 いいね機能は導入済みです。 私が、実装しているいいね機能は、投稿した食べ物(food)をユーザーが(user)がいいねするものになっています。 コード 早速ですが、コードを記述します。 初めの方のsleep 0.2は必要ありません。 自宅のWi-Fiがとんでもないぐらい遅いので記述しています。一応記事を添付します。 spec/models/like_spec.rb require 'rails_helper' RSpec.describe Like, type: :model do before do user = FactoryBot.create(:user) food = FactoryBot.create(:food) @like = FactoryBot.build(:like, user_id: user.id, food_id: food.id) sleep 0.2 end describe 'いいね機能' do context 'いいねできる場合' do it "user_idとfood_idがあれば保存できる" do expect(@like).to be_valid end it "food_idが同じでもuser_idが違えばいいねできる" do another_like = FactoryBot.create(:like) expect(FactoryBot.create(:like, user_id: another_like.user_id)).to be_valid end it "user_idが同じでもfood_idが違えばいいねできる" do another_like = FactoryBot.create(:like) expect(FactoryBot.create(:like, food_id: another_like.food_id)).to be_valid end end context 'いいねできない場合' do it "user_idが空ではいいねできない" do @like.user_id = nil @like.valid? expect(@like.errors.full_messages).to include "User must exist" end it "food_idが空ではいいねできない" do @like.food_id = nil @like.valid? expect(@like.errors.full_messages).to include "Food must exist" end end end end テストする項目として、 - user_idとfood_idがあれば保存できる - food_idが同じでもuser_idが違えばいいねできる - user_idが同じでもfood_idが違えばいいねできる - user_idが空ではいいねできない - food_idが空ではいいねできない の5つかなと考えました。 context 'いいねできない場合' do it "user_idが空ではいいねできない" do @like.user_id = nil @like.valid? bindng.pry expect(@like.errors.full_messages).to include "User must exist" end it "food_idが空ではいいねできない" do @like.food_id = nil @like.valid? expect(@like.errors.full_messages).to include "Food must exist" end end ここに関しては、 なかなかうまくいかなかったので、@like.valid?の後にbinding.pryして、 何がOKで、何がダメなのかを考えていきました。 27: 28: context 'いいねできない場合' do 29: it "user_idが空ではいいねできない" do 30: @like.user_id = nil 31: @like.valid? => 32: binding.pry 33: expect(@like.errors.full_messages).to include "User must exist" 34: end 35: 36: it "food_idが空ではいいねできない" do 37: @like.food_id = nil [1] pry(#<RSpec::ExampleGroups::Like::Nested::Nested_2>)> @like.errors.full_messagesについて、 こちらの記事を参考にして、 【Rails6】 RSpecによるLikeのモデル単体テストの実装 @like.errors[:user_id]と記述しておりましたが、 なかなかうまくいきませんでした。 @like.errors.full_messagesの中身を確かめたところ、 無事に["User must exist"]が出現しました。 27: 28: context 'いいねできない場合' do 29: it "user_idが空ではいいねできない" do 30: @like.user_id = nil 31: @like.valid? => 32: binding.pry 33: expect(@like.errors.full_messages).to include "User must exist" 34: end 35: 36: it "food_idが空ではいいねできない" do 37: @like.food_id = nil [1] pry(#<RSpec::ExampleGroups::Like::Nested::Nested_2>)> @like.valid? => false [2] pry(#<RSpec::ExampleGroups::Like::Nested::Nested_2>)> @like.errors[:user_id] => [] [3] pry(#<RSpec::ExampleGroups::Like::Nested::Nested_2>)> @like.errors.full_messages => ["User must exist"] [4] pry(#<RSpec::ExampleGroups::Like::Nested::Nested_2>)> 以上です。 この件について、 私の探し方が悪いのか、記事があまりなさそうでしたので、参考にしていただけますと幸いです。 終わりに テストコード、うまくいくと結構楽しいですね。 私は、好きです。 また、テストコードを書き始めたとき、以下のようなエラーが起きてました。 Failure/Error: expect(@like.errors.full_massages).to include "User must exist" NoMethodError: undefined method `full_massages' for #<ActiveModel::Errors:0x00007fb04cb95d30> Did you mean? full_messages full_message 「なんでや?あってるやんけ!」と30分調べた末、 massagesになってました...。 「マッサーゲっておま。。。」 タイポはほんと注意しないといけないですね。。 以下参考記事です。 【Rails6】 RSpecによるLikeのモデル単体テストの実装 Railsでいいね機能(ajax処理)のRSpecの書き方 今日中に、フォロー機能とコメント機能のテストも完了させたいと思います! 今日の残りと明日も頑張りましょう!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラーメッセージの日本語化

環境 ruby (2.6.5) rails (6.0.0) mysql2 (0.5.3) 日本語化の設定 config/application.rb module #App名 class Application < Rails::Application # 日本語の言語設定 config.i18n.default_locale = :ja end end config.i18n.default_locale = :jaを追記。 Gemfileの編集 Gemfile gem 'rails-i18n' Gemfileの一番下に追記。 bundle install 日本語化用ファイル作成 localeファイルの中に日本語化用のファイルを作成し、英語を日本語に翻訳する。 下記サイトの記述内容をコピーし、作成したdevise.ja.ymlの中に貼り付ける。 devise.ja.yml config/locales/devise.ja.yml ja: activerecord: attributes: user: confirmation_sent_at: パスワード確認送信時刻 confirmation_token: パスワード確認用トークン #〜省略〜 one: エラーが発生したため %{resource} は保存されませんでした。 other: "%{count} 件のエラーが発生したため %{resource} は保存されませんでした。" 自らが作成したカラム名は、'rails-i18n'やdevise.ja.ymlの導入によって使える日本語に含まれないため、英語で表示される。したがって、これらを翻訳するファイルを手動で作成する。 config/locales/ja.yml ja: activerecord: attributes: user: name: 氏名 occupation: 職種 profile: プロフィール image: 画像 staff_id: スタッフID customer: member_id: 会員ID email: メールアドレス #〜省略〜 また、自ら設定したエラー文を表示させたい場合は、下記のように対象のモデルへ記述する。 models/customer.rb class Customer < ApplicationRecord with_options presence: true do validates :name, format: {with: /\A[ぁ-んァ-ヶ一-龥々ー]+\z/, message: "は全角漢字または、ひらがなで入力してください"} validates :name_kana, format: {with: /\A[ァ-ヶー-]+\z/, message: "は全角カタカナで入力してください"} validates :postal_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "はハイフン(-)を含めて入力してください"} with_options numericality: { other_than: 0, message: "が選択されていません" } do validates :prefecture_id end end end おわりに エラーメッセージを日本語表示に変えた場合、単体テストコード中の期待されるエラーメッセージも日本語に変更する必要がある。テストを実行し、必要に応じて修正する。 参考 rails-i18n devise.ja.yml
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

helper と decorator の使い分け

例えば下記のようなコードはviewを肥大化させてしまい、さらに変更(#{@user.midlle_name} を追加したいなど)があった場合に対応しづらくなってしまう。 <%= "#{@user.first_name} #{@user.last_name}" %> そこで下記のようなメソッドに切り分けることを考えると思います。 def full_name end これをmodelに定義するのか、helperに定義するのか、はたまたdecoratorに定義するのか、そもそもこれらの違いはなんなのか、というのが今回のテーマです。 model の肥大化を防ぐ 基本的にメソッドはmodelに定義することで実装できます。ただ全てをmodelに書いてしまうとコード量が増え、可視性が悪くなり扱いづらくなってしまいます。 そこで登場するのが helper と decorator 。 これらは基本的にviewの肥大化を防ぐために使われます。viewの共通化やロジックを切るときにはmodelではなく、helper か decorator を使うようにしましょう。 じゃあ、これらは2つはどのように使い分ければ良いのでしょうか? helper と decorator の違いについて helper Modelに依存しないロジック → modelにアクセスする際に定数が必要 module ApplicationHelper def full_name(model) model.first_name + model.last_name end end グローバルに有効(アプリケーション内のどこでも使える)という特徴があるので、他のファイルでメソッド名が被ってしまったときに、どちらか一方が使えなくなるという事故に繋がるため注意が必要。 decorator Modelに依存するロジック → modelにアクセスする際に定数を必要としない module UserDecorator def full_name first_name + last_name end end gem 'draper'をインストールする必要がある まとめ 基本はmodelに書く viewのロジックでModelに依存しないときはhelper viewのロジックでModelに依存するときはdecorator ちなみに下記のような場合ではdecoratorを使うのが適切かと思います。 <%= "#{@user.first_name} #{@user.last_name}" %> <変更後> class UserDecorator def full_name first_name + last_name end end <%= @user.decorate.full_name %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【個人開発】Youtubeの企画をテーマにしたアプリ「〇〇王!! - quiz about me -」をリリースしました!

はじめに この度「私のことをどれだけ知ってる?」をコンセプトにした、問題の作成、回答ができるクイズアプリ、「〇〇王!! - quiz about me -」をリリースしました! 知ってる方も多いかと思いますが、実はこのアプリ、Youtuberさん達の間で人気の企画「〇〇王」からインスピレーションを受けています! この企画、見てるだけでも面白いですが、私たち視聴者も参加したいと思いませんか?? そんな時に使っていただきたいのがこのアプリです。 Youtuberさんが問題を作成し共有することで、視聴者さんも問題に回答できるようになります! もちろん、友達同士で問題を出し合っても楽しそうですね! 使い方・機能紹介 1. トップページ 若者受けしそうなデザインを意識しました。 ニックネームを入力することで問題を作成できます。 2. 問題作成する こちらの画面で問題の作成、削除ができるようになっております。 また、デフォルトで問題をいくつか用意させていただきました。 作った問題はSNSで共有してみてください。 3. 問題に回答する ニックネームを入力することで問題に回答できます。 また、クイズをより楽しくするため、ランキング機能を設けました。 回答結果もSNSで共有してみてください。 使用技術 バックエンド ・ Rails 6.0.4.1 ・ Ruby 2.6.6 ・ RSpec 5.0.2 フロントエンド ・ HTML ・ CSS (SCSS) ・ JavaScript (jQuery) ・ Bootstrap4 こだわった点 ユーザーのストレスをできるだけ減らした このアプリはじっくり使うというモノよりかは、サクッと気軽に遊べるような作りにして、ユーザーのストレスを減らすような作りが良いと考えました。 特に、問題作成の際、作成や削除をページ内で完結させたかったため、Ajaxを使いページの遷移をさせないような作りにしました。 ログイン機能もユーザーに対する1つの壁となる気がしたのであえて用意しませんでした。 デザイン面 できるだけシンプルかつ、ポップで若者(特にJK)に受けそうなデザインに仕上げました。 問題を表示する箇所はインスタのストーリーで使われている問題機能を参考にしました。 Youtubeをテーマにしてることから、ユーザーのほとんどはスマホでアクセスすると思ったので、デザインはスマホに寄せております。 おわりに 自分自身Youtubeで「〇〇王」という企画を見るたびに、これ友達同士でもやれたらいいなと思っていたので、形にできたのがすごく嬉しいです。 サービスをデプロイ後たくさんのユーザーさんに、「バズりそー!」などと感想をいただきました。 正直このサービスを思いついた時は、自分天才だな?なんて思ってしまいました(笑) また、感想以外にもご指摘など、ありがたい言葉をたくさんいただきました。ありがとうございます? 今後ご意見を参考にしつつ、サービスをよりよいものにしていけるように頑張っていきます! 最後までご覧いただきましてありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】S3にCSVデータを出力する

はじめに CSVファイルのデータをAWSのS3に保存するロジックを実装したので、よかったら参考にしてみてください。 Rails: 5.2.6 Ruby: 2.7.2 実装したコード S3のバケットに 例: 2021_10/2021_10_01.csv といったファイル名で出力されます。 こちらは毎日バッチで実行することを想定して作成おります。 export_csv.rb # frozen_string_literal: true require 'csv' require 'aws-sdk-s3' class ExportCsv def self.execute(params) output = CSV.generate do |csv| csv << params['headers'] params['values'].each do |value| csv << value end end export_csv_to_s3(output, params) end def self.export_csv_to_s3(data, params) s3_client = Aws::S3::Client.new(stub_responses: Rails.env.test?, access_key_id: params['access_key_id'], secret_access_key: params['secret_access_key'], region: params['region']) bucket_name = params['bucket_name'] folder_name = Time.current.yesterday.strftime('%Y_%m').to_s file_name = "#{Time.current.yesterday.strftime('%Y_%m_%d')}.csv" file_full_path = "#{folder_name}/#{file_name}" # バケットの存在確認とアクセス権の確認 if bucket_exists_and_accessible?(s3_client, bucket_name) Rails.logger.info "Bucket '#{bucket_name}' exists and is accessible to you." else Rails.logger.info "Bucket '#{bucket_name}' does not exist " \ 'or is not accessible to you.' end # ファイルアップロードが完了したか確認 if file_uploaded?(s3_client, bucket_name, file_full_path, data) Rails.logger.info "Object '#{file_full_path}' uploaded to bucket '#{bucket_name}'." else Rails.logger.info "Object '#{file_full_path}' not uploaded to bucket '#{bucket_name}'." end end def self.bucket_exists_and_accessible?(s3_client, bucket_name) s3_client.head_bucket(bucket: bucket_name) return true rescue StandardError return false end def self.file_uploaded?(s3_client, bucket_name, path, data) response = s3_client.put_object( bucket: bucket_name, key: path, body: data, content_type: 'text/csv' ) return true if response.etag rescue StandardError => e Rails.logger.info "Error uploading object: #{e.message}" return false end private_class_method :export_csv_to_s3, :bucket_exists_and_accessible?, :file_uploaded? end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RubyKaigi 2021 参加レポート(というより所感)

はじめに 今回RubyKaigiに初参加してきましたので参加レポート(というより所感)をアウトプットさせていただきます! 筆者について Rubyスキル 初めてComputer Software業界に入ったときに研修でRubyを少し使ったくらい Ruby on Railsの研修を3ヶ月みっちりしたくらい 業務ではまだ毛が生えた程度 経歴 2021年に転職をし入社するまでRuby on Railsをするとは思ってなかったのでそもそもRailsが初になります。主にJavaとかGoなどのコンパイル言語が主な経験になるのでRubyやPythonなどのインタプリタ言語自体の開発経験が初になります。 その上でのRubyKaigi参加となるのでお手柔らかに見ていただければと思います! 特に印象に残った発表 TypeProf for IDE: Enrich Dev-Experience without Annotations The newsletter of RBS updates Ruby, Ractor, QUIC [JA] Matz Keynote / Yukihiro "Matz" Matsumoto @matz ※YouTubeの動画リンクにつながっていますので良ければ御覧ください TypeProf for IDE: Enrich Dev-Experience without Annotations こちらはIDE (VSCode) での静的型付け(TypeProf)のお話になります。 僕はJavaやTypeScriptをよく使用していたのでわかりますが、型を書くのって結構ストレスなんです。新しいNode Module Libraryを入れるときも型が対応していないとTypeScriptでは使えないですし、どうしても使いたい場合は自分で書くという辛さがあります。(大抵のライブラリには型は書かれていますが) なので最近の流行?トレンド的には別で定義ファイルを自分たちで書いておいてそのファイルをもとにTSの型を生成するというフローを入れるようなライブラリが増えてきています。(PrismaとかOpenAPIとか) Rubyの静的型付けに対する考えとしては 型は手動で書かない をポリシーに開発されているようで、過去のそういった苦しみや課題をうまく取り入れて開発を進めているようです。 Rubyはインタプリタなので実行しないと型というかオブジェクトがわからないので、型を決めるためには実行(どこかで使用していること)が必要とのことです。 方針としては書かないけど、RBSで型を明示することができるとのことでVSCodeのGo to definitionをクリックすると型定義が作成されるらしい!(これはかなり便利そう) 全体的な話を見た上での感想としては、VSCodeのGo to definitionで型定義が簡易に作れるのに全ファイルを走査してすべての型ファイルをGenerateしないのはやはり型は必要なときに使うというポリシーで無駄な管理コストを省くためなのかなーと思いました。(でも結局ライブラリに依存するから全生成しちゃったほうが良いような。。。) 少し残念だったのはTypeProf for IDEでは規模の大きいRubyファイルを解析するとレスポンスが最悪10分かかることがあるよう(対応としては長い処理の場合は打ち切りにする)で、Railsとかで使おうとすると大丈夫なのかなーとかまだ実用的ではないのかもと思いました。 The newsletter of RBS updates そもそも RBS とは RBS はRuby版の型言語といったところですね。 Ruby 3.0 から同梱されている Ruby 2.6 でも gem install rbsで使用できる そもそも RBS Collectionとは RBS v2からの新機能 Bounded type parameters これはいわゆるクラスレベルでのジェネリクスの機能になるようです。 入力値に推論してくれて特定の型を返す汎用的な機能の作成に役立ちそうです。 Generic Type Aliases こちらも構造情報に型情報を流すことができるようになる 感想 rbs collectionが以前より簡単に導入できるようになったようでセットアップが簡単なのが便利そうです。今までは導入のためにハードルが高かったようです。 個人的にはRBS v2のジェネリクス機能が楽しみですね。早く型使いたい。。。 Ruby, Ractor, QUIC そもそもRactorとは Rubyにおける並列実行可能な仕組み、Goroutineが近い Ractorの前に近年のRealTime通信技術について 現状 WebRTC WebSocket これから WebTransport HTTP/3から use UDP QUICを使用する QUICとは 現状のTCP/IPでのパケット損失を解決するための新しいプロトコル 現在のChromeやFirefoxなどのブラウザで既に使用されている 感想 噂のQUICとRactorで実装したとのことです。そもそもQUICに対して聞いたことはあるけど、よく知らない状態だったのでこの機会に知れてよかったです。データの中身のHeaderとpayloadの仕様を知れたり、Rubyでのデータ処理方法の実装例を知れました。 結果としては残念ながらRubyの純粋なコードのほうが早く、Ractorを使うと85倍も遅くなるようです。同じマシンでの実験のため原因がメモリ差などではないのが少し残念ですが、これからのRactorの動向に期待したいですね。 Ractor 関連 終わりに 今回初めてのRubyKaigiの参加となりましたが、Rubyが性能向上、静的型付けの対応、並列実行の強化など生まれ変わろうとしていることがわかりました。 また、今回Rubyが初なのでRubyの言語としてのポジショニングというのがより深く理解できて参加してよかったと思っています。 新しい静的型付けのツールやRactorなど業務でなくてもツールとして活用できればと思いました! 末筆ではありますが閲覧頂きありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【個人開発】自分だけのうまくいく方法を見つける目標達成サービス「b-logic」をリリースしました。

はじめに 突然ですが、目標を立てて達成できたことありますか? 筆者は英語を喋れるようになるや筋肉ムキムキになるといった目標を人生の中で幾度となく立ててきました。 ほとんど3日坊主で続きません。 なんどもなんども自分はなんて意志力のない人間なんだと嘆きました。 しかし本当にそうでしょうか? 実はやり方がまずいだけなのではないでしょうか?自分だけのうまくいく方法があるはずです。 そう、プログラムのように今まではエラーが起きていて、実は正しいプログラムではなかったのです。 正しいプログラムさえ、正しいやり方さえ見つければどんな目標だって達成できるはず このような思いから、目標達成を条件ベースで考えていく目標達成サービスを作りました。 サービス概要 ユーザーは目標、課題、タスクといった3つ観点から目標を計画をします。 達成できない目標はいつだって、具体的な行動が欠けていたり、ひとそれぞれ集中できる環境、タイミングが存在します。(家だと集中できないけど図書館なら集中できるとか) 自分だけのうまくいく方法をサービスを使いながら、見つけていきユーザーへ目標達成を促します。 https://b-logic.herokuapp.com/ 何がうれしいのか? 目標が3日坊主で終わる原因の大半は見切り発車で、具体的な計画を立てて無いことが原因です。 作成したサービスでは目標、課題、タスクと決まったフォーマットを用意し順番に作成していくことで、自然と計画的な目標を立てることができます。 使い方 目標新規作成 まず目標を作成します。 目標新規作成ボタンをクリックします。 目標登録 目標名と期限決めます。 目標名は画像のように数字で具体的にしましょう。悪い例としてお金持ちになるという目標はざっくりすぎなのでやめましょう。 登録ボタンを押して目標を作成します。 課題が解除された 鍵が解除されて課題という項目が出現しました。 課題一覧をクリックして課題一覧ページへ移動しましょう。 課題一覧ページ 課題一覧ページではすべての課題と、作成した目標別の課題が表示されています。 左のエリアを見ると、先程作成した目標名が表示されていますね。 現状課題を作成していないので、作ってみましょう。 +ボタンをクリックします。 課題・解決案作成 課題名と解決策を決めます。 今回は2つ登録してみました。 課題は現状の問題点をあげ、問題点に対してどうするかの方向性を解決策として登録します。 お菓子の出費が激しいのは夜中にコンビニに行くという習慣ができてしまっているため、22時に寝る ECサイトでの出費が多いのは、気軽に購入できてしまうため、踏みとどまれるようにクレジットカードの登録を解除して、購入に時間をかからせる。 このように課題と解決策を登録していきます。 課題は作りすぎても大変なので、2〜3つがベストかと思います。 タスク鍵解除・タスク一覧ページへ タスクを登録します。 トップページに戻り、タスク一覧ページへ移動します。 タスク作成 左の枠からタスクを追加する課題を選び+ボタンをクリックします。 タスク完了・未完了切り替え 3つ追加してみました。 タスクは解決策を達成するための行動になります。 今回の場合22時に寝るためにお風呂、歯磨き、布団に入るというタスクを指定された時間内にしなければ、ならないということです。 またチェックをつけることで、タスクの完了を意味します。 目標完了 このように目標の計画を立てていきます。 目標が達成したいこと、課題が目標を達成する上での障壁になるもの、または現状の問題点、タスクが解決策を達成するための行動です。 最後に目標が達成されたら、目標一覧ページから達成ボタンを押すことで、目標達成です。 もし期限内に達成できなかったら、見落としている課題があるか、タスクの見直しをしてみてください。 こだわった点 UIデザイン 一昔前のレトロPCのようなUIを意識しました。 目標を計画することは大変骨の折れる作業です。 計画している最中に飽きてしまわないよう、デザインで楽しめるようなUIにしました。 ターミナルを作った help(使えるコマンド表示)、ls(ファイル表示)、open(画面遷移)、clear(画面表示削除)使えるコマンドは少ないですが、ターミナルのような動作をするUIで遊べます。(息抜きにどうぞ) エラー画面 目標や、タスクには期限を設定できますが、もし設定した期限をすぎると画面遷移するたびにエラー画面が出現します。 このサービスは前置きの通り、ユーザーが決めた計画はプログラムと仮定してます。 そのため、期限を過ぎたらエラー画面のような通知で表示させています。 エラーだ!速く直さなくちゃと感じてくれたら幸いです。 使用技術 Rails bootstrap モーダル系はすべてbootstrapを使用しています。 ターミナルはcoffeescript(js)で実装しています。 300行以上あるため、全ては載せませんが、行っていることは押されたキーを取得し、押されたキーによって条件分岐をして処理を分けています。 さらに押されたキーがenterキーだった場合は更に処理を追加しています。 基本的には押されたキーの条件分岐、enter時は入力されたキーの羅列によって条件分岐しています。 # 入力keyによって動作を制御 key_control = (i_key, target) -> # バグ対応 何故か読み込み時にi_keyがundefindとして発火してしまうため if i_key.keyCode == undefined false # enter key押したとき else if i_key.keyCode == 13 enter(target) false # backspace押した時 else if i_key.keyCode == 8 # 入力文字削除 word_delete() # space key押した時 else if i_key.keyCode == 32 # 空白文字追加処理 word_add_blank target # 動作に関係ないkey押した時 else if not_used_key i_key # 表示したくない無いkey排除 false else true enter時の処理 # enter時はコマンド実行 別の処理 enter = (target) -> # 入力されたコマンド cmd = word.join '' # コマンド空白 or 未入力時 if space.test(cmd) || cmd.length == 0 # 改行して新たなプロンプト出現 # id削除 prompt_delete() # prompt追加 prompt_add() word = [] else if ((cmd.match open) || (cmd.match open_name) || (cmd.match open_not_name)) open_control(cmd) else if cmd == 'clear' prompt = document.getElementById 'prompt' while prompt.lastChild prompt.removeChild prompt.lastChild add_element() word = [] # 存在しないコマンド else if cmd == 'ls' ls() enter_flug = 1 prompt_delete() prompt_add() word = [] else if cmd == 'help' help() enter_flug = 1 prompt_delete() prompt_add() word = [] else enter_flug = 1 target.innerHTML = word.join '' error_msg() prompt_delete() prompt_add() word = [] 今後の展望 チュートリアルモード作成 ターミナルコマンド追加(tab、など...) ターミナルエリアクリック時のみコマンド受付(現状キーボードを押すと入力を受け付けている) 最後に ここまで読んでくれてありがとうございました。 使い方がわからないという意見を頂いているので、チュートリアルを作成しより使いやすく改良していきます。 ぜひこのサービスを使い倒し目標達成の助けになればと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby|csv_box を使ってもっと楽に CSV をつくりたい

やりたいこと CSV 出力は案件ごとに手製で作ることが多いと思います。業務で関わるサービスだと列数も多く、並び替えや条件による列の追加・削除でバグが起きやすいですよね。 問題はデータ部の出力と列の並びが直結しているので、それを分けてやると管理しやすいと考えました require 'csv' Book = Struct.new(:id, :title, :price) books = [Book.new(1, 'How to cook delicious meals', 1500), Book.new(2, '10 tips to lose weight', 250)] table = CSV::Table.new([]) headers = [ 'id', 'title', ... 'price' ] # メンテナが代わることによる無理な列名の追加... headers << 'tax price' if .... books.each do |book| # ヘッダ部をみながらデータ部の並びを整えるのが大変... table << CSV::Row.new(headers, [book.id, book.title, ..., book.price]) end puts table.to_csv やってみたこと 数年前ですが、csv_box を作ってみました。Rails で使われることを想定していて、いまのところカラムの内容をそのまま出力します。 CSVBox.add で出力したい列を定義します。ここでは並びは関係なく、何を出力したいかです。引数にはモデル名など対象がわかるようにすると良いと思います。 CSVBox.add 'book' do field 'id' field 'title' field 'price' end CSVBox.layouts は CSVBox.add で登録した対象にどの順番で出力したいかを決めることができます。レイアウトに layout で名前をつけることができて CSV の作成時に使います。 CSVBox.layouts 'book' do layout 'shuffled layout' do |box| box.price box.id box.title end  layout 'simple layout' do |box| box.title box.price end end CSVBox.take で対象の名前とレイアウト名を指定して、何をどうやって出力するかを決めます。<< で CSV::Table を使って行を追加してたように追加することができます。 box = CSVBox.take 'book', 'shuffled layout' books.each do |book| box << book end puts box.to_csv __END__ price,id,title 1500,1,How to cook delicious meals 250,2,10 tips to lose weight レイアウトの変更も楽で条件によって変えるのであれば次のようになります。 box = if ... CSVBox.take 'book', 'shuffled layout' else CSVBox.take 'book', 'simple layout' end books.each do |book| box << book end puts box.to_csv CSV 出力と分けて、対象の何を出力するのか、カラムの順番や条件をレイアウト毎に変えてやることによってかなりスッキリしたのではないでしょうか?今後ですが、例えば税込価格を表示したいなどその時だけの計算もあると思いますデコレータで逃げてもいいと思いますが、計算も組み込めるようになるのが今後の展望です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]モーダルウィンドウを作る

はじめに 本記事では、過去に作ったモーダルウィンドウの作り方を記述します。 イメージ このような形です。 かっこいいですよね。 コード 該当のビュー 省略 <div class="menu-details"> <div class="search-contents"> <div class="fas fa-search"></div> <h2 class="menu-content">SEARCH</h2> </div> </div> 省略 <%# モーダルウィンドウ %> <div class="modalsearch"> <i class="far fa-times-circle modalsearch-close"></i> <div class="modalsearch-contents"> <div class="modalsearch-left"> <h2 class="modalsearch-title">Let's<br/>Search !</h2> </div> <div class="modalsearch-right"> <div class="modalsearch-contents"> <%= search_form_for @q, url: search_foods_path, class: "food-search", id:"pull-down" do |f| %> <%= f.label :shop_name_or_shop_name_kana_or_food_name_or_station_cont, '店名・メニュー名・駅名', class: "search-label" %><br/> <%= f.text_field :shop_name_or_shop_name_kana_or_food_name_or_station_cont, placeholder: "KEYWORD", class: "search-text" %><br/> <%= f.label :user_nickname_cont, 'ユーザー名', class: "search-label" %><br/> <%= f.text_field :user_nickname_cont, placeholder: "KEYWORD", class: "search-text" %><br/> <%= f.label :meal_type_id_eq, '種類', class: "search-label" %><br/> <%= f.collection_select :meal_type_id_eq, MealType.all, :id, :name, {include_blank: '--', disabled: 0}, class: "search-text" %><br/> <%= f.label :spicy_level_id_eq, '辛さ', class: "search-label" %><br/> <%= f.collection_select :spicy_level_id_eq, SpicyLevel.all, :id, :name, {include_blank: '--'}, class: "search-text" %><br/> <%= f.submit "SEARCH", class: "search-submit" %><br/> <% end %> </div> </div> </div> </div> <div class="masksearch"></div> <script> $(function() { $('.search-contents').on('click',function(){ $('.modalsearch,.masksearch').fadeIn(); }); $('.modalsearch-close,.masksearch').on('click',function(){ $('.modalsearch,.masksearch').fadeOut(); }); }); </script> <%# /モーダルウィンドウ %> 下から13行目にある<div class="masksearch"></div>はdivタグで囲っていませんので、注意。 ここはブワッと出た時の黒い部分になります。 CSSでは画面全体を黒くするようにしております。 CSSはモーダルウィンドウの部分だけにします。 //モーダルウィンドウ .modalsearch { position: fixed; background-image: image-url("search-title.png"); background-size: cover; background-repeat: repeat; background-color: rgba(255, 255, 255, 0.8); background-blend-mode: lighten; width: 80vw; height: 70vh; top: 50%; left: 50%; transform: translate(-50%,-50%); border-radius: 10px; z-index: 2; display: none; } .modalsearch-contents { display: flex; justify-content: space-around; align-items: center; } .modalsearch-title { height: 20vh; width: auto; color: rgb(0, 0, 0); font-family: 'Permanent Marker', cursive; font-size: 7vw; text-align: center; } .modalsearch-close { cursor: pointer; font-size: 4vw; } .search-label { font-family: "M PLUS Rounded 1c"; font-size: 1.2vw; } .search-text { width: 25vw; height: 5vh; color: #000000; border: solid 3px #000000; margin: 0.5em; font-size: 1.2vw; background-color: #ffffff33; } .search-submit { width: 15vw; height: 7vh; color: #000000; border: solid 3px #000000; border-radius: 20%; margin: 0.5em; font-size: 1.2vw; background-color: #ff00004f; font-family: 'Permanent Marker', cursive; } .masksearch { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); z-index: 1; display: none; } // /モーダルウィンドウ 初めの方の<h2 class="menu-content">SEARCH</h2>でSEARCHを押すと、 ブワッと出ます。 まず、前述の通り、 .masksearch { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); z-index: 1; display: none; } は外側の黒い部分です。 potision: fixed;にする必要があるので注意です。 出ないとスクロールしたらその分だけ黒い部分はなくなります。 内側の部分についても、黒い部分よりも小さくなるようにCSSで設定し、 以下の通り、これもpotision: fixed;します。 また、z-index: 2;することで、黒い部分よりも前面になるように設定します。 .modalsearch { position: fixed; background-image: image-url("search-title.png"); background-size: cover; background-repeat: repeat; background-color: rgba(255, 255, 255, 0.8); background-blend-mode: lighten; width: 80vw; height: 70vh; top: 50%; left: 50%; transform: translate(-50%,-50%); border-radius: 10px; z-index: 2; display: none; } 最後は、scriptタグです。 <script> $(function() { $('.search-contents').on('click',function(){ $('.modalsearch,.masksearch').fadeIn(); }); $('.modalsearch-close,.masksearch').on('click',function(){ $('.modalsearch,.masksearch').fadeOut(); }); }); </script> .search-contentsをクリックすると、 検索項目と黒い部分が出る(フェードイン)ようにしました。 逆に、検索項目内にある印(ここでは).modalsearch-closeと黒い部分.masksearchをクリックすると、 検索項目と黒い部分が出るようにしました。(フェードアウト) 検索項目については、 それぞれのアプリケーションで表現したいことを記述すれば完了です。 私の場合は、以下の部分です。 <div class="modalsearch-contents"> <div class="modalsearch-left"> <h2 class="modalsearch-title">Let's<br/>Search !</h2> </div> <div class="modalsearch-right"> <div class="modalsearch-contents"> <%= search_form_for @q, url: search_foods_path, class: "food-search", id:"pull-down" do |f| %> <%= f.label :shop_name_or_shop_name_kana_or_food_name_or_station_cont, '店名・メニュー名・駅名', class: "search-label" %><br/> <%= f.text_field :shop_name_or_shop_name_kana_or_food_name_or_station_cont, placeholder: "KEYWORD", class: "search-text" %><br/> <%= f.label :user_nickname_cont, 'ユーザー名', class: "search-label" %><br/> <%= f.text_field :user_nickname_cont, placeholder: "KEYWORD", class: "search-text" %><br/> <%= f.label :meal_type_id_eq, '種類', class: "search-label" %><br/> <%= f.collection_select :meal_type_id_eq, MealType.all, :id, :name, {include_blank: '--', disabled: 0}, class: "search-text" %><br/> <%= f.label :spicy_level_id_eq, '辛さ', class: "search-label" %><br/> <%= f.collection_select :spicy_level_id_eq, SpicyLevel.all, :id, :name, {include_blank: '--'}, class: "search-text" %><br/> <%= f.submit "SEARCH", class: "search-submit" %><br/> <% end %> </div> </div> </div> 以上です。 いかがでしょうか。 終わりに モーダルウィンドウがアプリケーションにあるとかなりおしゃれになるので、どんどん使用していきたいところです。 特にログアウト時や投稿削除時には、入れておくことで未然に誤作動を防ぐことができますね。 以下参考サイトです。 モーダルウィンドウ・ダイアログウィンドウの作り方1(HTML、CSS、JavaScriptで作る) 【jQuery・CSS】意外と簡単!モーダルウィンドウをプラグインなしで作る 明日も頑張ります!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む