20211205のRailsに関する記事は12件です。

[初心者] Railsでyoutube APIを使って検索機能を実装してみた

はじめに ポートフォリオ作成をするにあたりyoutube APIを使い、検索機能を追加したく、実装してみました。 不慣れで読みにくいかもしれませんが何卒ご了承ください。 YouTube APIは取得しているものとします。 主にこちらの記事を参考にしています。 Railsでyoutube APIを使ってみた 大変お世話になりました?‍♂️ 開発環境 Rails:6.1.4 Visual Studio Code:1.61.2 実装してみる youtube.controller class YoutubeController < ApplicationController GOOGLE_API_KEY = ENV["API_KEY"] def find_videos(keyword, after: 1.months.ago, before: Time.now) service = Google::Apis::YoutubeV3::YouTubeService.new service.key = GOOGLE_API_KEY keyword = params[:search] next_page_token = nil opt = { q: keyword, type: "video", max_results: 6, order: :date, page_token: next_page_token, published_after: after.iso8601, published_before: before.iso8601, } service.list_searches(:snippet, opt) end def index @youtube_data = find_videos(@keyword) end end find_videosメソッドに keyword = params[:search]を追加し、indexメソッドから keyword を呼び出す。 あとはviewから form_tag を用いて、method: :getのHTTPメソッドを指定し、データを取得します。 view/youtube/index.html.erb <div class="search-form"> <%= form_tag(youtube_index_path, method: :get) do %> <%= text_field_tag :search, "", placeholder:"材料をどうぞ" %> <%= submit_tag '検索' %> <% end %> </div> <div class="row row-cols-3"> <% @youtube_data.items.each do |item| %> <div class="card-box"> <div class="card border-dark mb-3"> <div class="bd-placeholder-img card-img-top"> <% @snippet = item.snippet %> <% @video_id = item.id.video_id %> <div class="embed-responsive embed-responsive-16by9"> <div><iframe width="560" height="315" src="https://www.youtube.com/embed/<%= @video_id %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div> </div> <div class="card-body"> <h4>タイトル:<%= @snippet.title %></h4> <p>チャンネル名:<%= @snippet.channel_title %></p> </div> </div> </div> </div> <% end %> </div> class="embed-responsive embed-responsive-16by9"で取得したYouTube動画のレスポンシブ対応をしています。 実装結果 最後に とりあえずエラーが出ずに実装することができた程度なんで、もっと簡単な方法があればアドバイスいただけると嬉しいです? 最後まで読んでいただき、ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails×AWS】yamlファイルにおける'please note that yaml must be consistently indented using spaces'の解決

https://qiita.com/gyu_outputs/items/b123ef229842d857ff39 こちらの記事を参考にrailsアプリをawsにデプロイする過程で発生したエラーに関する備忘録です。 エラー詳細 ページトップに添付した記事の中の「credentials.ymlの設定」の箇所で直面したエラーです。 credentials.yml db: database: アプリ名 username: root password: 設定したPW socket: /var/lib/mysql/mysql.sock credentials.ymlを記述した後に、 database.yml production: <<: *default database: <%= Rails.application.credentials.db[:database] %> username: <%= Rails.application.credentials.db[:username] %> password: <%= Rails.application.credentials.db[:password] %> socket: <%= Rails.application.credentials.db[:socket] %> 上記のようにdatabase.ymlを記述してrspecでテストを実行したところ下記のエラーが発生しました。 RuntimeError: YAML syntax error occurred while parsing /Users/hoshiyuunari/Desktop/new_app/selftalk_app/config/database.yml. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Error: (<unknown>): found character that cannot start any token while scanning for the next token at line 75 column 13 ちなみに上記エラーコードの「at line 75 column 13」はdatabase.ymlの中では password: <%= Rails.application.credentials.db[:password] %> の最初の"<"の部分です。 原因 エラーコード上はインデントの問題とありましたがそうではありませんでした。 database.yml production: <<: *default database: <%= Rails.application.credentials.db[:database] %> username: <%= Rails.application.credentials.db[:username] %> password: "<%= Rails.application.credentials.db[:password] %>" #""をつけただけ socket: <%= Rails.application.credentials.db[:socket] %> credentials.ymlで設定したpasswordの項目が関係していました。 私の場合、パスワードの頭文字が@だったのですがyamlファイルの規則では@には""をつける必要があります。 credentials.ymlではpasswordに""を付けていましたが環境変数として記述する場合も付ける必要がありました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】環境構築

ターミナルの設定を弄っていたら、今まで入れていたバージョンがどこかに行ってしまったので、再度環境構築する羽目になりました。環境構築は面倒なので今のうちにメモを。 状態確認 実行したコマンド ・ruby -v ・rbenv -v ・which ruby → /usr/bin/ruby 状況確認のため上記のコマンドを実行し、結果を見て見ると -v コマンドで確認したものは問題無くバージョンが表示されていたが which ruby → /usr/bin/ruby which rubyの結果、パスが間違っているのでここを修正できると判断。 ❌ which ruby → /usr/bin/ruby ⭕️ which ruby → /Users/user/.rbenv/shims/ruby パスとは ファイルやフォルダの置いてある場所のこと。 ・パス = PC内の住所 ・パスを通す = パスを省略できるようにする 設定を変える rubyの住所を変えるために、.zshrcにて変更を加える必要がある。 .zshrcとは? ターミナルひらくときに最初に読み込まれるファイル。 初期化コマンドや パス通す処理やエイリアス(=別名,ショートカット)を記述するファイル。 変更手順 ① .zshrcを開く       open ~/.zshrc ② 以下の2行を.zshrcに追加  ・  export PATH="$HOME/.rbenv/bin:$PATH"  ・  eval "$(rbenv init -)" ③追加した記述を保存      source ~/.bash_profile 最後に状態確認にて行ったコマンドで正しい場所にできたら、 インストールしたいバージョンを指定。 参考記事 M1 Mac上でRubyとRailsの開発環境構築やっていきます 【zsh, bash】macでPATHを通す方法 - not found と出てしまったら ファイルパス (file path) パスとは?PATHを通すとは?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Heroku】 ActionView::Template::Error (Webpacker can't find application.js in /ideaFrameworks/public/packs/manifest.json. Possible causes:

Rendered layout layouts/application.html.erb (Duration: 1.8ms | Allocations: 983) 2021-12-05T07:57:51.553760+00:00 app[web.1]: I, [2021-12-05T07:57:51.553723 #5] INFO -- : [7101643d-e3f6-44fc-8f81-5b4e42542e97] Completed 500 Internal Server Error in 45ms (ActiveRecord: 5.6ms | Allocations: 2446) 2021-12-05T07:57:51.554362+00:00 app[web.1]: F, [2021-12-05T07:57:51.554328 #5] FATAL -- : [7101643d-e3f6-44fc-8f81-5b4e42542e97] 2021-12-05T07:57:51.554363+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] ActionView::Template::Error (Webpacker can't find application.js in /ideaFrameworks/public/packs/manifest.json. Possible causes: 2021-12-05T07:57:51.554364+00:00 app[web.1]: 1. You want to set webpacker.yml value of compile to true for your environment 2021-12-05T07:57:51.554364+00:00 app[web.1]: unless you are using the webpack -w or the webpack-dev-server. 2021-12-05T07:57:51.554365+00:00 app[web.1]: 2. webpack has not yet re-run to reflect updates. 2021-12-05T07:57:51.554366+00:00 app[web.1]: 3. You have misconfigured Webpacker's config/webpacker.yml file. 2021-12-05T07:57:51.554366+00:00 app[web.1]: 4. Your webpack configuration is not creating a manifest. 2021-12-05T07:57:51.554367+00:00 app[web.1]: Your manifest contains: 2021-12-05T07:57:51.554368+00:00 app[web.1]: { 2021-12-05T07:57:51.554368+00:00 app[web.1]: } 2021-12-05T07:57:51.554368+00:00 app[web.1]: ): 2021-12-05T07:57:51.554369+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 7: <%= csp_meta_tag %> 2021-12-05T07:57:51.554370+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 8: 2021-12-05T07:57:51.554370+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 9: <%= stylesheet_link_tag 'application', media: 'all' %> 2021-12-05T07:57:51.554371+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 10: <%= javascript_pack_tag 'application' %> 2021-12-05T07:57:51.554371+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 11: 2021-12-05T07:57:51.554371+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 12: 2021-12-05T07:57:51.554372+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 13: 2021-12-05T07:57:51.554372+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] 2021-12-05T07:57:51.554373+00:00 app[web.1]: [7101643d-e3f6-44fc-8f81-5b4e42542e97] app/views/layouts/application.html.erb:10 といったエラーがおきた ActionView::Template::Error (Webpacker can't find application.js in /ideaFrameworks/public/packs/manifest.json. Possible causes: とあったので、 rails webpack:install heroku run bundle exec rails webpacker:compile git push heroku master をして、エラーが解決できた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ArgumentError (SMTP To address may not be blank: []):の対処法【Mailer】

症状 RailsのActionMailerで送信先のメールアドレスを変更しようとした時に、下記エラーメッセージが表示されました。 翻訳すると、「ArgumentError(SMTP宛先アドレスを空白にすることはできません:[]):」でした。 error [ActiveJob] [ActionMailer::MailDeliveryJob] [7112b19a-912c-49a9-b0ed-d7a83176ab57] Error performing ActionMailer::MailDeliveryJob (Job ID: 7112b19a-912c-49a9-b0ed-d7a83176ab57) from Async(mailers) in 1377.91ms: ArgumentError (SMTP To address may not be blank: []): C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/check_delivery_params.rb:21:in `check_to' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/check_delivery_params.rb:7:in `check' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp_connection.rb:52:in `deliver!' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb:101:in `block in deliver!' C:/Ruby30-x64/lib/ruby/3.0.0/net/smtp.rb:558:in `start' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb:109:in `start_smtp_session' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb:100:in `deliver!' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/message.rb:2159:in `do_delivery' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/message.rb:260:in `block in deliver' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/actionmailer-6.0.4.1/lib/action_mailer/base.rb:589:in `block in deliver_mail' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/notifications.rb:180:in `block in instrument' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/notifications/instrumenter.rb:24:in `instrument' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/notifications.rb:180:in `instrument' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/actionmailer-6.0.4.1/lib/action_mailer/base.rb:587:in `deliver_mail' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mail-2.7.1/lib/mail/message.rb:260:in `deliver' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/actionmailer-6.0.4.1/lib/action_mailer/message_delivery.rb:115:in `block in deliver_now' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/actionmailer-6.0.4.1/lib/action_mailer/rescuable.rb:17:in `handle_exceptions' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/actionmailer-6.0.4.1/lib/action_mailer/message_delivery.rb:114:in `deliver_now' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/actionmailer-6.0.4.1/lib/action_mailer/mail_delivery_job.rb:23:in `perform' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/execution.rb:40:in `block in perform_now' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:112:in `block in run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/i18n-1.8.10/lib/i18n.rb:314:in `with_locale' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/translation.rb:9:in `block (2 levels) in <module:Translation>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `instance_exec' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/core_ext/time/zones.rb:66:in `use_zone' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/timezones.rb:9:in `block (2 levels) in <module:Timezones>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `instance_exec' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/logging.rb:25:in `block (4 levels) in <module:Logging>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/notifications.rb:180:in `block in instrument' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/notifications/instrumenter.rb:24:in `instrument' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/notifications.rb:180:in `instrument' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/logging.rb:24:in `block (3 levels) in <module:Logging>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/logging.rb:45:in `block in tag_logger' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/tagged_logging.rb:80:in `block in tagged' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/tagged_logging.rb:28:in `tagged' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/tagged_logging.rb:80:in `tagged' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/logging.rb:45:in `tag_logger' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/logging.rb:21:in `block (2 levels) in <module:Logging>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `instance_exec' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:139:in `run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/execution.rb:39:in `perform_now' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/execution.rb:25:in `block in execute' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:112:in `block in run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/railtie.rb:43:in `block (4 levels) in <class:Railtie>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/execution_wrapper.rb:88:in `wrap' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/reloader.rb:72:in `block in wrap' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/execution_wrapper.rb:88:in `wrap' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/reloader.rb:71:in `wrap' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/railtie.rb:42:in `block (3 levels) in <class:Railtie>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `instance_exec' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activesupport-6.0.4.1/lib/active_support/callbacks.rb:139:in `run_callbacks' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/execution.rb:23:in `execute' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activejob-6.0.4.1/lib/active_job/queue_adapters/async_adapter.rb:70:in `perform' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/concurrent-ruby-1.1.9/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:363:in `run_task' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/concurrent-ruby-1.1.9/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:352:in `block (3 levels) in create_worker' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/concurrent-ruby-1.1.9/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:335:in `loop' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/concurrent-ruby-1.1.9/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:335:in `block (2 levels) in create_worker' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/concurrent-ruby-1.1.9/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:334:in `catch' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/concurrent-ruby-1.1.9/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:334:in `block in create_worker' 以下が該当のソースになります。 user_controller.rb #paramsにuser_idと送り先のメールアドレスであるnew_emailを受け取っている def send_change_email user = User.find_by(id: params[:user_id]) UserMailer.with(user: user,new_email: params[:new_mail]).change_emailaddress_email.deliver_later end user_mailer.rb def change_emailaddress_email @user = params[:user] @url = 'http://example.com/login' @new_email = params[:new_email] mail(to: @new_email, subject: 'メールアドレス変更を完了させましょう') end 解決策 controllerのparams指定が間違っていたため、うまく送り先のメールアドレスが受け取れずに、ブランクを渡してしまい、ブランク宛てにメールを送ってしまっていたようです。(params[:new_mail]からparams[new_email]に) ほぼほぼ翻訳通りの「宛先アドレスを空白にすることはできません」という内容でした。 user_controller.rb #paramsにuser_idと送り先のメールアドレスであるnew_emailを受け取っている def send_change_email user = User.find_by(id: params[:user_id]) UserMailer.with(user: user,new_email: params[:new_email]).change_emailaddress_email.deliver_later end 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

herokuへのコンテナデプロイでのエラー ActiveSupport::MessageEncryptor::InvalidMessage:

我らが山浦清透大先生のこの動画の通りに,herokuへのコンテナデプロイをしようとしてます。 heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks を実行したら ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage このようなエラーがでてきた。 secret_key_base config/master.key config/credentials.yml.enc 暗号化/複合化。 なんか聞いたことある。 端的にcredentials.yml.encの文字列とmaster.keyの文字列の組み合わせが不正解であるということです。 heroku config:set RAILS_MASTER_KEY=`cat config/master.key` を実行 これを実行したらエラー解決できるとキータの記事にあった() heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks エラー変わらず。 heroku config -a ideaframeworksで RAILS_MASTER_KEY:がちゃんと設定されていた。 ローカルのmaster.keyと同じなのに。。。。。 戯れにgit push heroku masterを実行 soichirohara@SoichironoMacBook-Pro ideaFrameworks % git push heroku master Enumerating objects: 321, done. Counting objects: 100% (321/321), done. Delta compression using up to 8 threads Compressing objects: 100% (285/285), done. Writing objects: 100% (321/321), 219.98 KiB | 5.95 MiB/s, done. Total 321 (delta 98), reused 0 (delta 0), pack-reused 0 remote: Compressing source files... done. remote: Building source: remote: === Fetching app code remote: remote: =!= Your app does not include a heroku.yml build manifest. To deploy your app, either create a heroku.yml: https://devcenter.heroku.com/articles/build-docker-images-heroku-yml remote: Or change your stack by running: 'heroku stack:set heroku-20' remote: Verifying deploy... remote: remote: ! Push rejected to ideaframeworks. remote: To https://git.heroku.com/ideaframeworks.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://git.heroku.com/ideaframeworks.git' heroku.yml build: docker: web: Dockerfile.production heroku.ymlでイメージをビルドしてdeployできるとかなんとか Dockerfile.production FROM ruby:2.6.5 ENV RAILS_ENV=production ## nodejsとyarnはwebpackをインストールする際に必要 # yarnパッケージ管理ツールをインストール RUN curl http://deb.debian.org/debian/dists/buster/main/binary-amd64/by-hash/SHA256/935deda18d5bdc25fb1813d0ec99b6e0e32a084b203e518af0cf7dc79ee8ebda | head RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn && apt-get install -y graphviz RUN /bin/sh -c /bin/sh -c bundle update --bundler RUN gem install bundler:2.1.4 RUN mkdir /ideaFrameworks WORKDIR /ideaFrameworks COPY . /ideaFrameworks COPY Gemfile /ideaFrameworks/Gemfile COPY Gemfile.lock /ideaFrameworks/Gemfile.lock RUN bundle install COPY start.sh /start.sh RUN chmod 744 /start.sh CMD ["sh","/start.sh"] heroku stack:set container git push heroku master を実行。 Post-install message from rubyzip: remote: RubyZip 3.0 is coming! remote: ********************** remote: remote: The public API of some Rubyzip classes has been modernized to use named remote: parameters for optional arguments. Please check your usage of the remote: following classes: remote: * `Zip::File` remote: * `Zip::Entry` remote: * `Zip::InputStream` remote: * `Zip::OutputStream` remote: remote: Please ensure that your Gemfiles and .gemspecs are suitably restrictive remote: to avoid an unexpected breakage when 3.0 is released (e.g. ~> 2.3.0). remote: See https://github.com/rubyzip/rubyzip for details. The Changelog also remote: lists other enhancements and bugfixes that have been implemented since remote: version 2.3.0. remote: Removing intermediate container abde761777fb remote: ---> 591c8c89978c remote: Step 13/15 : COPY start.sh /start.sh remote: COPY failed: stat /var/lib/docker/tmp/docker-builder709159940/start.sh: no such file or directory remote: remote: Verifying deploy... remote: remote: ! Push rejected to ideaframeworks. remote: To https://git.heroku.com/ideaframeworks.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://git.heroku.com/ideaframeworks.git COPY failed start.shが消えていたので、 start.sh #!/bin/sh if ["${RAILS_ENV}"="production"] then bundle exec rails assets:precompile fi bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0 を作成して コミット,pushして再度 git push heroku master というかビルドする方法をすこし変えただけなので、 heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks を実行したら ActiveSupport::MessageEncryptor::InvalidMessage: が出るエラーは多分変わらん。 根本的な問題はそこではない。 どうしてもできない場合は、 credentials.yml.encを一度消して、$ EDITOR="vi" bin/rails credentials:editを再度実行することで、credentials.yml.encとmaster.keyが新しく作り直されます とあるので、こうしたら秘密鍵と公開鍵が合致する可能性もある。 が、そこらへんをいじるのはこわいので最終手段。 なにはともあれ deploy成功した。ので heroku run bundle exec rails db:migrate RAILS_ENV=production soichirohara@SoichironoMacBook-Pro ideaFrameworks % heroku run bundle exec rails db:migrate RAILS_ENV=production - Running bundle exec rails db:migrate RAILS_ENV=production on ⬢ ideaframeworks... up, run.3070 (Free) rails aborted! ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage /ideaFrameworks/config/environment.rb:5:in `' Caused by: OpenSSL::Cipher::CipherError: /ideaFrameworks/config/environment.rb:5:in `' Tasks: TOP => db:migrate => db:load_config => environment (See full trace by running task with --trace) config/enviroment.rb Rails.application.initialize! この方も自分と同じエラーで、master.keyとcredentials.yml.encの削除 EDITOR="vi" bin/rails credentials:edit をすればいいらしい。 もうこれしかねぇ。 master.keyが再度作られない。。。。 この記事によるとsudoをやらないといけないらしい master.keyとcredentials.yml.encの削除して sudo EDITOR="vi" rails credentials:edit sudo権限を付与したら両方つくられた。 sudo vi config/master.key これでmaster.keyの値もみれた。 新しくつくられたmaster.keyの値もセットした heroku run bundle exec rails db:migrate RAILS_ENV=production お願いします!!!! エラー変わらず。。。。 credentials.yml.encを書き換えたあとにpushしわすれた。 git push heroku masterを実行 これでcredentials.yml.encとmaster.keyの値は一致するはず。 heroku run bundle exec rails db:migrate RAILS_ENV=production お願いします!!!! LoadError: Error loading the 'postgresql' Active Record adapter. Missing a gem it depends on? pg is not part of the bundle. Add it to your Gemfile. Caused by: Gem::LoadError: pg is not part of the bundle. Add it to your Gemfile. Tasks: TOP => db:migrate => db:load_config (See full trace by running task with --trace) エラー内容が変わった!やったぜ! これはheroku ポスグレのアドオンがideaframeworksに入っていたので、削除して、 再度 heroku run bundle exec rails db:migrate RAILS_ENV=production Running bundle exec rails db:migrate RAILS_ENV=production on ⬢ ideaframeworks... up, run.4267 (Free) rails aborted! ActiveRecord::ConnectionNotEstablished: Unknown MySQL server host 'db' (-2) Caused by: Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2) Tasks: TOP => db:migrate (See full trace by running task with --trace) エラーが変わりましたね。 database.yml production: <<: *default database: ideaFrameworks_production username: ideaFrameworks password: <%= ENV['MYSQL_ROOT_PASSWORD'] %> のプロダクションがこうなってました。 以前、設定した値が何故か吹きとんでたので この動画のまんまの設定にして database.yml production: <<: *default database: <%= ENV['APP_DATABASE'] %> username: <%= ENV['APP_DATABASE_USERNAME'] %> password: <%= ENV['APP_DATABASE_PASSWORD'] %> host: <%= ENV['APP_DATABASE_HOST'] %> に設定しなおして git pushとgit push heroku master して heroku run bundle exec rails db:migrate RAILS_ENV=production これでいけるだろ!!! soichirohara@SoichironoMacBook-Pro ideaFrameworks % heroku run bundle exec rails db:migrate RAILS_ENV=production Running bundle exec rails db:migrate RAILS_ENV=production on ⬢ ideaframeworks... up, run.8668 (Free) I, [2021-12-05T06:50:22.412316 #4] INFO -- : Migrating to CreateMandalarts (20211202075545) == 20211202075545 CreateMandalarts: migrating ================================= -- create_table(:mandalarts) -> 0.0229s == 20211202075545 CreateMandalarts: migrated (0.0230s) ======================== きた=======!!!!!!! まとめると ここまでうまくいってる前提で話します。 heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks を実行したら ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage というエラーがでてきた。 どうやら、credentials.yml.encの文字列とmaster.keyの文字列の組み合わせが合ってないらしい。 この記事を参考に、 master.keyとcredentials.yml.encの削除して sudo EDITOR="vi" rails credentials:edit sudo権限を付与したら両方つくられた。 sudo vi config/master.key これでmaster.keyの値もみれた。 新しくつくられたmaster.keyの値もheroku config:set とかでセットして、 git push origin master git push heroku master か、 heroku container:push とか 個人的には、heroku.ymlのほうが ビルドするDockerfileも指定しやすくて好き。 んで、どっちかのコマンドを打ったら、 master.keyとcredentials.yml.encが合致するので、うまくいくはず。 おまけ Dockefile.production FROM ruby:2.6.5 ENV RAILS_ENV=production ## nodejsとyarnはwebpackをインストールする際に必要 # yarnパッケージ管理ツールをインストール RUN curl http://deb.debian.org/debian/dists/buster/main/binary-amd64/by-hash/SHA256/935deda18d5bdc25fb1813d0ec99b6e0e32a084b203e518af0cf7dc79ee8ebda | head RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn && apt-get install -y graphviz RUN /bin/sh -c /bin/sh -c bundle update --bundler RUN gem install bundler:2.1.4 RUN mkdir /ideaFrameworks WORKDIR /ideaFrameworks COPY . /ideaFrameworks COPY Gemfile /ideaFrameworks/Gemfile COPY Gemfile.lock /ideaFrameworks/Gemfile.lock RUN bundle install COPY start.sh /start.sh RUN chmod 744 /start.sh CMD ["sh","/start.sh"] start.sh #!/bin/sh if ["${RAILS_ENV}"="production"] then bundle exec rails assets:precompile fi bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0 heroku.yml build: docker: web: Dockerfile.production これで,git push heroku masterでデプロイができるので良き
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsコマンドメモ

勉強内容をメモしたものです 基本スクリプト 説明 コマンド内容 アプリ作成 rails new [アプリケーション名] コントローラ作成 raild g controller [コントローラ名] モデル作成 rails g model [モデル名] モデル削除 rails d model [モデル名] マイグレーションファイルの作成 rails g migration [行う処理+テーブル名] アクション アクション REST index GET model名 new GET model/new show GET model/:id edit GET model/:id/edit create POST model update PUT model/:id destroy DELETE model/:id Model rails g model [model名] データ型 型名 string 文字列 text 長い文字列 date 日付 datetime 日時 time 時間 integer 整数 float 浮動小数 decimal 高精度少数 binary バイナリ boolean 真偽値 Migration Script file モデルを作成すると自動で生成される テーブルに変更を行いたい場合は手動で作成する rails g migration [行う処理+テーブル名] db/migrate/配下にファイルが生成される コマンド上で変更を行う rails g migration [クラス名] [カラム名]:[データ型] クラス名 AddXXXTo[テーブル名] RemoveXXXFrom[テーブル名] MigrationFileを変更する 実行する処理:upメソッド 戻す処理:downメソッド def up add_column :[Table名], :[カラム名], :[データ型] end def down remove_column [Table名], :[カラム名], :[データ型] end Command list maigration関連でよく使うコマンド集 処理  コマンド 備考 マイグレーション実行 rake db:migrate 状態を確認 rails db:migrate:status ファイルを削除 rails destroy migration [クラス名] DB未反映のファイルを削除 バージョン確認 rake db:version 反映済みのバージョンを確認する ロールバック rake db:rollback (STEP=[ステップ数]) 例) rake db:rollback STEP=2 View(template) ファイル名: アクション名.html.erb 置き場: app/view/コントロール名/ Layout 共通 優先度 アクション > クラス > コントローラ > アプリケーション Layoutを指定しない 指定先に"false" を使用 レイヤーごとの指定方法 アプリケーション*全体の共通レイアウト app/views/layouts/application.html.erb コントローラごとにレイアウトを自動指定 app/views/layouts/[コントローラ名].html.erb (コントローラ)クラスからレイアウトを指定 class [コントローラ名] < ApplicationController layout 'ファイル名' end アクションからレイアウトを指定 class [コントローラ名] < ApplicationController def [アクション名] render :layout => 'ファイル名' end end 部分Template ファイルの命名規則 _[ファイル名].html.erb 配置場所 app/views/ app/view/[コントロール名] 埋め込み方法 <%= render 'ファイル名' %> Rubyコード コードを記述: <% %>/<%= %> 改行を除く: <% _%>/<%= _%> 繰り返し [オブジェクト].each do |[変数名]| [変数名] end 条件分岐 if [条件] then # 実行する処理 else # 実行する処理 end インスタンス変数 @変数 = 100 @変数 #100
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails二重投稿防止の注意点

事象 railsではformで送信時にvalidateなどのメッセージを出せるが、 そのvalidateメッセージ表示周りがdivで囲まれ レイアウトが崩れる場合がある 対策 もしview周りはデザイナーが担当しており cssの指定が .class > p + span などのように 子、隣接結合子などを使って書かれている場合 デザイナーにBEM記法などで書き直してもらう必要がある よくあるその場しのぎ レイアウトが崩れるので、validate周りをdivで囲まないようにする為、configに以下を書いている場合 # 二重送信対策解除 config.action_view.automatically_disable_submit_tag = false もちろんこれだと二重送信防止が解除される為解決にならない 二重送信防止方法はこちら 結論 デザイナーに書き直してもらう or 自分で書く html, css記法は認識を共通しておく事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ユーザーの状態に応じた対話機能をLINEbotで実現する【LINE Messaging API】

概要 本記事は RUNTEQアドベントカレンダー 2021 の7日目の記事となります! 個人開発でゴミ捨て日を通知してくれるLINEアプリを開発したのですが、 その中で実装するのに苦労した「ユーザーの状態を把握する」方法を記事にします。 一般的なRailを使用したWebアプリケーションでは、Cookieを利用したユーザー識別やフォームを利用してユーザーの送信する内容を一挙に受け取るなどができますが、LINE Messaging APIではこれらが使えません... そこで私が実装した、Railsのみでユーザーの状態を保持する方法を紹介します。 これからRails x LINE Messaging API を試してみたい方の参考になれば幸いです。 ※ LINE Developperへの登録や設定、基本的な実装についての概要などは他に多数の素晴らしい記事があるため、割愛させていただきます。(こちらの記事など) ※ 私はいわゆる未経験エンジニアですので、あまり綺麗なコードではないかもしれませんし、他にもっといい方法があるかもしれません。マサカリ歓迎です。 どんな実装にしたかったか? まず、どんな実装にしたかったかを説明します。 ユーザーがゴミ捨ての予定を登録するという作業で、 「ゴミ捨ての予定を次々と質問され、それに答えていくと登録できる。」 というシナリオで実装したいと思いました。 具体的には、 下図のようにゴミの名前・収集する曜日・周期を答えていき 最後に通知してほしい時間を答えれば、ゴミ捨ての登録完了! という流れです。 しかし、LINEユーザーから送られてくる情報は主に ユーザーの識別情報 送信したテキスト の2つのため、ユーザーの状態の把握(セッション管理)まではできません。 例えば、「1」というテキストが送られてきただけでは「毎週」なのか「月曜日」なのか分からないということです。 実装 結論から言うと、Userモデルに対話状態を表すstatusカラムを持たせ、対話内容を記録するMessageモデルを作成しました。 コードで説明していきます。 Model Userモデルに状態を管理するstatusカラムを追加しました。 user.rb class User < ApplicationRecord ... has_many :messages, dependent: :destroy enum status: { top: 0, registration: 1, show_next: 2, add_day_of_week: 3, add_cycle: 4, add_notification: 5 } end Messageモデルを作成し、Userモデルに対し1対多の関連付けをしました。 message.rb class Message < ApplicationRecord belongs_to :user end ※ 他のモデルについては省略します Controller コントローラーの内容は少し複雑かと思いますので、4段階に分けて説明していきます。 1. 基本形 まずは基本的なオウム返しの実装です。 main_actionメソッドの中でユーザーの返信内容などによって条件分岐させることによって、 レスポンスメッセージを書き換えることができます。 これ以降はmain_actionメソッドに注目し、書き加えていきます。 linebot_controller.rb # オウム返しする LINEbot class LinebotController < ApplicationController require 'line/bot' def client @client ||= Line::Bot::Client.new { |config| config.channel_secret = ENV["LINE_CHANNEL_SECRET"] config.channel_token = ENV["LINE_CHANNEL_TOKEN"] } end def callback body = request.body.read signature = request.env['HTTP_X_LINE_SIGNATURE'] head :bad_request unless client.validate_signature(body, signature) events = client.parse_events_from(body) events.each { |event| case event when Line::Bot::Event::Message case event.type when Line::Bot::Event::MessageType::Text # 条件分岐 main_action(event) message = { type: 'text', text: @response } client.reply_message(event['replyToken'], message) end end } head :ok end # この中身だけ書き換える def main_action(event) # ユーザーの返信したメッセージ text = event.message['text'] @response = text end end 2. user の 状態によって返信内容を変える いちいちupdateが走ってしまいますが、やり取りの度にstatusカラムの値を更新して状態を保持します。 これによって、「ゴミの名前は?」「曜日は?」と言ったように、レスポンスを投げる順序を制御できます。 linebot_controller.rb class LinebotController < ApplicationController ... def main_action(event) # ユーザーの識別 @user = User.find_or_create_by(line_id: event['source']['userId']) text = event.message['text'] # statusカラムの値で分岐 case @user.status when 'top' case text # 1 が返信されたら、登録モードへ when '1' @response = "登録モードへ移行します。\nゴミの名前を入力してください。" @user.registration! end ### 登録モード ### when 'registration' @response = '曜日を入力してください。' @user.add_day_of_week! when 'add_day_of_week' @response = '周期を入力してください。' @user.add_cycle! when 'add_cycle' @response = '通知する時間を入力してください。' @user.add_notification! when 'add_notification' @response = '登録完了です。' # ゴミの登録が完了したら、topに戻す @user.top! end end end 3. ユーザーの返信内容を保存する ユーザーのいくつかの返信を組み合わせてゴミ捨て日のレコードを生成したいため、以前のユーザーの返信内容を保存しておく必要があります。 ここでMessageモデルを使用します。 以下のコードのように、ユーザーが返答した内容(ゴミの名前など)をDBに保存しておきます。 そして、登録完了メッセージと同時にゴミを確定し、ゴミのレコードを生成します。 linebot_controller.rb class LinebotController < ApplicationController ... def main_action(event) @user = User.find_or_create_by(line_id: event['source']['userId']) text = event.message['text'] case @user.status when 'top' case text when '1' @response = "登録モードへ移行します。\nゴミの名前を入力してください。" @user.registration! end ### 登録モード ### when 'registration' @user.messages.create!(text: text) # ゴミの名前を覚えておく @response = '曜日を入力してください。' @user.add_day_of_week! when 'add_day_of_week' @user.messages.create!(text: text) # ゴミの曜日を覚えておく @response = '周期を入力してください。' @user.add_cycle! when 'add_cycle' @user.messages.create!(text: text) # ゴミの周期を覚えておく @response = '通知する時間を入力してください。' @user.add_notification! when 'add_notification' # ここでゴミレコードを生成する @response = '登録完了です。' @user.top! end end end 4. 完成! ここまでの知識とその他諸々を組み合わせ、完成したコードです。 これで最初の写真のようなやり取りができるようになります! # main_action 完成形 class LinebotController < ApplicationController ... def main_action(event) @user = User.find_or_create_by(line_id: event['source']['userId']) text = event.message['text'] .tr("  \r\n\t", '') # 空白の除去 .tr('0-9', '0-9') # 全角数字を半角に case @user.status when 'top' case text # 1 が返信されたら、登録モードへ when '1' @response = <<~TEXT ゴミの名前を何にする?一つだけ答えてね! (例)燃えるゴミ TEXT @user.registration! end ### 登録モード ### when 'registration' # ゴミの名前を保存! @user.messages.create!(text: text) @response = <<~TEXT 収集日はいつにする? 1: 月曜日 2: 火曜日 3: 水曜日 4: 木曜日 5: 金曜日 6: 土曜日 7: 日曜日 0: ゴミの登録をやめる\n TEXT @user.add_day_of_week! when 'add_day_of_week' # 収集する曜日を保存! @user.messages.create!(text: text) @response = <<~TEXT 周期はどうする? 1: 毎週 2: 今週から隔週 3: 来週から隔週 4: 第1・3 5: 第2・4 0: やめる TEXT @user.add_cycle! when 'add_cycle' # 収集する周期を保存! @user.messages.create!(text: text) @response = <<~TEXT 何時に通知する? 10分単位で設定できるよ! (例1)6:40 (例2)7時20分 (例3)8時半 0: ゴミの登録をやめる TEXT @user.add_notification! when 'add_notification' text.gsub!(/時|分|半/, '時' => ':', '分' => '', '半' => '30') # 00:00-23:50のフォーマットに則っているかどうかの判定 if text.match(/^([01]?[0-9]|2[0-3]):[0-5]0$/) # やり取りしたゴミの情報を引き出す trash_name = @user.messages[-3].text day_of_weeks = @user.messages[-2].text cycle_num = @user.messages[-1].text collection_days = CollectionDay.find(day_of_weeks) cycle = Cycle.find(cycle_num) # ゴミと通知時間を作成する trash = @user.trashes.create!( name: trash_name, cycle: cycle, collection_days: [collection_days].flatten ) Notification.create!(trash: trash, notify_at: text) @response = <<~TEXT 登録したよ! 「#{trash.name}」の収集日は 「#{trash.cycle.name_i18n}」の「#{trash.collection_days_list}」 「#{l trash.notification.notify_at}」に通知するからね! TEXT @user.top! else @response = '正しく入力してね!' end end end end 最後に ここまで読んでいただき、ありがとうございます。 以上が私の実装したコードの一部です。 段々長くなっていくコードで読みづらいとは思いますが、、、みなさまの参考になれば幸いです。 参考 今更ながらRails5+line-bot-sdk-ruby+HerokuでLineBot作成してみたら、色々詰まったのでまとめました。 【LINE×Rails】Rails初学者も作れるLINE Botアプリケーション
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

gemを使ってスクレイピングしてみた

はじめに 本記事は、2021 RUNTEQアドベントカレンダー5日目の記事になります! 現在ポートフォリオを作成しており、その作成過程でスクレイピングを用いて必要な情報を取得しDBに格納しました。今回はそこで使用したgem Mechanizeについて書いていこうと思います! この記事でわかること gem Mechanizeについて できること 提供しているメソッド PFで用いたDBに格納する方法 できること まず概要を公式より見てみます Mechanizeライブラリは、ウェブサイトとの対話を自動化するために使用されます。Mechanizeは、自動的にクッキーを保存、送信し、リダイレクトを行い、リンクをたどり、フォームを送信することができます。フォームフィールドは入力して送信することができます。また、Mechanizeは、あなたが訪問したサイトを履歴として記録します。 ざっくりとした解釈ですが、自動的にwebサイトに訪問して、フォームがあれば入力もできちゃうよ〜ってことですね。 webサイトを自動で訪問できるので、そこでスクレイピングしたいページにとび、取得したいデータのみ抽出するという処理も書けちゃうわけです 提供しているメソッド 下準備 メソッドの説明に入っていくのですが、gemをinstallすると、mechanizeクラスが使えるようになります。 公式では下準備としてインスタンス化してくださいとあるので、下記のように設定します # 公式には下記の記載がありますが、Ruby1.9以降では必要ないのでコメントアウトします # require 'rubygems' require 'mechanize' class Scraping agent = Mechanize.new end get スクレイピングしたいwebサイトのHTMLを取得してくれます。ここでは試しにマクドナルドのサイト情報を取得してみましょう require 'mechanize' class Scraping def self.mcd agent = Mechanize.new page = agent.get("https://www.mcdonalds.co.jp/") end end コンソールで実行してみます irb(main):001:0> Scraping.mcd => #<Mechanize::Page {url #<URI::HTTPS https://www.mcdonalds.co.jp/>} {meta_refresh} {title "マクドナルド公式サイト | McDonald's Japan"} {iframes #<Mechanize::Page::Frame nil ... #<Mechanize::Page::Link "ホーム" "/"> #<Mechanize::Page::Link "\n" + "メニュー\n" + "\n" + "\n" "/menu/"> #<Mechanize::Page::Link "おすすめ" "/menu/"> #<Mechanize::Page::Link "バーガー" "/menu/burger/"> #<Mechanize::Page::Link "セット" "/menu/set/"> #<Mechanize::Page::Link "サイドメニュー" "/menu/side/"> #<Mechanize::Page::Link "ドリンク" "/menu/drink/"> #<Mechanize::Page::Link "ハッピーセット" "/menu/happyset/"> #<Mechanize::Page::Link "朝マック" "/menu/morning/"> #<Mechanize::Page::Link "夜マック" "/menu/dinner/"> #<Mechanize::Page::Link "スイーツ" "/menu/dessert/"> #<Mechanize::Page::Link "マックカフェ" "/menu/barista/"> #<Mechanize::Page::Link "キャンペーン" "/campaign/"> #<Mechanize::Page::Link "ファミリー" "/family/"> #<Mechanize::Page::Link "私たちの責任" "/scale_for_good/"> #<Mechanize::Page::Link "お店・サービス" "/shop/"> ... これ以上は長くなってしまうので省きますが、これだけでもざっくりページの情報を得られているのがわかると思います〜〜 search cssを指定するのと同じ要領で要素を指定できます。タグはそのまま指定。 classを指定する際は、「.(ドット) class名」。idを指定する際は、「#(シャープ) id名」といった感じですね。返り値は配列の形式で返ってきます。 試しにli a を指定し、格納した配列を出力してみます class Scraping def self.mcd agent = Mechanize.new page = agent.get("https://www.mcdonalds.co.jp/") elements = page.search('li a') puts elements end end コンソール irb(main):001:0> Scraping.mcd <a href="/" class="no-underline block h-xs line-height-md p-2:lg my-0 font-semibold active">ホーム</a> <a href="/menu/" class="no-underline block h-xs line-height-md p-2:lg my-0 font-semibold flex justify-between items-center"> <span>メニュー</span> <span class="header-submenu-toggle-btn"></span> </a> <a href="/menu/" class="no-underline">おすすめ</a> <a href="/menu/burger/" class="no-underline">バーガー</a> <a href="/menu/set/" class="no-underline">セット</a> <a href="/menu/side/" class="no-underline">サイドメニュー</a> <a href="/menu/drink/" class="no-underline">ドリンク</a> <a href="/menu/happyset/" class="no-underline">ハッピーセット</a> ... 先程とは違い、HTMLの情報を取得できています! at searchメソッドと同じ要領で要素を指定し、該当する1件のみ取得することができます 先程の文法のまま、searchの部分をatメソッドに変更すると、コンソール上では1件のみ取得できるのがわかります! irb(main):001:0> Scraping.mcd <a href="/" class="no-underline block h-xs line-height-md p-2:lg my-0 font-semibold active">ホーム</a> get_attribute タグの属性値を取得することができます。属性値とは例えばaタグの中の、href属性に指定されてるURLのことを指します。先程searchメソッドで取得した配列のうち、get_attributeメソッドを使用して、URLの情報を取得してみます class Scraping def self.mcd agent = Mechanize.new page = agent.get("https://www.mcdonalds.co.jp/") elements = page.search('li a') urls = [] elements.each do |element| urls << element.get_attribute(:href) end puts urls end end コンソール irb(main):001:0> Scraping.mcd / /menu/ /menu/ /menu/burger/ /menu/set/ /menu/side/ /menu/drink/ /menu/happyset/ /menu/morning/ /menu/dinner/ /menu/dessert/ /menu/barista/ /campaign/ /family/ /scale_for_good/ /shop/ /order /recruit/crew_recruiting/ /shop/mobile/ inner_text searchメソッドやatメソッドではタグも含めて全て取り出していましたが、inner_textメソッドではタグの中身のテキストだけを取り出すことができます。 searchで取得した情報にinner_textメソッドを使用してみましょう class Scraping def self.mcd agent = Mechanize.new page = agent.get("https://www.mcdonalds.co.jp/") elements = page.search('li a').inner_text puts elements end end コンソール irb(main):001:0> Hoge.mcd ホーム メニュー おすすめバーガーセットサイドメニュードリンクハッピーセット朝マック夜マックスイーツマックカフェキャンペーンファミリー私たちの責任お店・サービス モバイルオーダー 会員登録なし! スマホでスムーズにご注文・お支払い 採用情報公式アプリ 2020.04.07 「マックシェイク®」と「プッチンプリン」が史上初のコラボ 江崎グリコのプッチンプリン担当者お墨付きの味の再現性! マックシェイク® “プッチン”できないけど プッチンプリン 4月13日(月)から期間限定販売! 自分で“プッチン”出来ちゃう?!「ちょい足しカラメルソース付」を特別限定で実施 ... テキストだけ取得することができました。 このような形で、サイトに応じてメソッドを使用すればDBに必要な情報を好きなように取得し、格納することもできそうです PFで用いたDBに格納する方法 上記のメソッドを活用して、実際にDBにスクレイピングしたデータを格納していきます。 執筆時のマクドナルドのハンバーガー一覧ページから、簡易的ですが商品名(name)、価格(price)、説明(description)のカラムを持ったfoodsテーブルを作成し、こちらに格納していきます。テーブル作成は割愛します require 'mechanize' class Scraping def self.mcd agent = Mechanize.new links = [] page = agent.get("https://www.mcdonalds.co.jp/menu/burger/")  # elementsには商品詳細へのHTMLが格納されています elements = page.search('.product-list-card a')    # each doメソッドで各HTMLに対し処理を実行。get_attributeメソッドを活用してリンクを取得しlinksに格納しています elements.each do |ele| unless (ele.get_attribute(:href) == '/shop/mobileorder/') links << ele.get_attribute(:href) end end  # 取得した各リンクを引数としget_foodメソッドを実行します links.each do |link| get_food("https://www.mcdonalds.co.jp/#{link}") end end まず第一段階で一覧ページから、各商品詳細情報のリンクを取得し、linksの配列に格納していきます require 'mechanize' class Scraping def self.mcd ... end def self.get_food(link) agent = Mechanize.new page = agent.get(link) name = page.at('.pdp__product-info h1').inner_text price = page.at('.items-baseline span:nth-child(3)').inner_text description = page.at('.pdp__product-info p').inner_text Food.create(name: name, price: price, description: description) end end 第二段階で、取得した各商品詳細情報から、必要な情報を指定して、取得し、最後にcreateします コンソール上で実行すると以下のようにDBに格納できていることがわかります! 終わりに 最後までご一読いただきありがとうございました!  同じように、ポートフォリオ作成を考えていらっしゃる方の参考になれば幸いです! また、もし間違っている点等あれば、ご指摘いただけると嬉しいです。ありがとうございました! 参考URL Github 公式 Rails スクレイピング手法 Mechanizeの使い方 スクレイピングでサイト情報を取得し、データベースにストアするまでの流れをまとめてみた[Rails]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

現役ミュージシャンが実務未経験から実務案件に挑戦。コードを書く事だけがエンジニアの仕事ではないと気付かされる!

自己紹介 初めまして!現在音楽講師をしているhirokiと申します。 未経験からエンジニアへの転職を目指し日々学習をしております。 楽器歴はもう17年と日々演奏技術を磨きながら最新の音楽情報をキャッチアップしております。 そんな私がプログラミングを始めたのは、別のミュージシャンの方が自分のホームページを持っていたので「僕も作ってみたいな」という気持ちからでした。 そこからプログラミングについて調べみるとそのページにはログイン機能などがあり、これはなんだと?と思い調べてみました。 調べていくと、Webアプリケーションが作れ、雛形が揃っていて尚且つ学びやすいというフレームワークがあるという記事を見つけました。そこで出会ったのがRuby on Railsでした。まずは始めないと正解・不正解も分からないので、何事も触れてみようと思い学習をスタートしました。 独学で勉強し少しずつ理解が深まるごとにどんどんプログラミングにハマっていきました。 ある出来事で転職したいと思うようになりました。それは、目の前でWebサービスを使っている生徒さんの困っている姿でした。 生徒さんから『バンドを組んでライブをしたいのにメンバーが見つからないです』っという相談を頂きました。私自身バンドメンバー募集サイトを利用し、新たなメンバーと出会えた経験があることから、そのサービスを勧めました。 しかし生徒様から、『自分で探さなくても自動で紹介してくれる機能が欲しい、探しにくいな』と感想を頂きました。 『そのような機能をがあるのかな?』と思い調べていくとある機能に注目しました。 それはプロフィールや求める人物を自動でマッチングしてくれるようなシステムです。きっかけは恋愛マッチングアプリのシステムからです。 しかし、構想があってもスキルがなければ実現できません。 『私がサービスを改善する事で問題解決し、役に立ちたいな』と思うようになりました。 目の前に困っている生徒さんがいるのに、改善出来ないことへの悔しさが込み上げてきました。 悔しい経験から、技術探求し、IT技術を通し、『人の役に立てようになりたい』と思うようなりました。 この経験から私自身エンジニアとして成長し、IT技術を通じ、人々の役に立ちたいと思う様になりエンジニアへの転職を決意しました。 案件の概要 実務案件を頂けたのですが、今回クライアントから依頼があった内容は、医院紹介サイト(Rails)のSEOの改善とCore Web Vitalsの改善をしてほしいという案件内容でした。 チームメンバーでタスクを分けしたのですが、私が担当させて頂いたのはCore Web Vitalsの改善でした。(Core Web Vitalsの詳しい内容は後述) メンバー構成と実務期間は、リーダーであるY氏と、私含め3名の未経験者が2ヶ月間実務に取り組みました。 実務案件を申し込んだ理由と経緯 応募したきっかけは、入社前後のギャップを埋めたいと思い応募しました。実務を体験をすることによって独学でプログラミングに触れている時と実務とのギャップを少しでも埋めることができ、入社後の成長、心構えを知る事が出来るのではないかと考えたからです。 もう一つは書いてあることしかできない(言われたことしかできない)人間ではなく、自走して課題を解決できる人間であることを少しでも証明したいと思ったため、今回の実務案件に挑戦させていただきました。 実務経験を積みたいと思い検索する中で、実務の募集を見つけました。どうしても実務経験を積みたいと思い2度も応募フォームを送信し気持ちが届いたのか実務案件に参画させて頂くことになりました。 1. 実装準備 実装を始める前に、初めて聞く用語の理解や、計測ツールを使っての問題の洗い出し方法を理解してから着手しました。まずは実装準備をどの様にしてきたのかを説明していきたいと思います。 Core Web Vitalsとは? Core Web Vitalsの知識が無いと何も始まりませんので実務ではしっかり用語の意味を理解してから着手しました。 ここでは閲覧して頂いている皆様に簡潔にお伝えさせて頂きますm(_ _)m Core Web Vitalsとは ユーザー体験を向上させるためのGoogleが定めたガイダンス 一言で表すとユーザーが感じる使い勝手を評価する指標 Core Web Vitals参考URL https://webtan.impress.co.jp/e/2020/06/05/36210 内容を深ぼると指針が分かりやすく定められていました。 Core Web Vitalsの指針 LCP(Largest Contentful Paint) 読み込みパフォーマンスを測定して数値化したもの。ユーザーがそのWebページのなかで最も有意義なコンテンツをどれだけ早く見ることができるかを表す指標。一言で言うと読み込み時間の事。ページの読み込み開始から2.5秒以内にそのページが描画されることが望ましいとされる。 FID(First Input Delay) ユーザーがWebページを閲覧する際に ページのレスポンスが良いかどうかを測定した数値。 ユーザー体験(UX)の最適化にはこのFIDの数値が 100ミリ/秒未満であることが望ましいとされる。 CLS(Cumulative Layout Shift) ユーザーがページを閲覧する際、 テキストや画像などのコンテンツが快適に表示されているか否かを示す指標。 ユーザー体験(UX)の最適化には、このCLSの値を 0.1未満に維持しなければならない。 参考URL https://mtame.jp/seo/corewebvitals/ 何を改善するのか? Core Web Vitalsの3つの指針を理解したのですが、今回どこの指針の部分を改善するのかを決めないといけません。 Core Web Vitalsの改善方法を調べていくと、ウェブページの読み込み速度をスコア測定してくれるツールである『PageSpeed Insights』というツールをがある事を知りました。ツール内で今回依頼を頂いたサイトURLを入力すると計測してくれます。計測結果で表示された内容で、適切な画像サイズの画像、使用していないJavaScriptの削減、使用していないCSSの削減の3項目が改善の余地があると指摘を受けました。 今回私が施策提案させて頂いたのは、使用していないCSSの削減と、適切な画像サイズの変更の2項目です。 前もって説明させて頂きますが、適切な画像サイズの画像の施策については、実装する事が出来ませんでした、、、 理由は、 指摘のあった画像部分だけを圧縮すればいいのだと施策を勘違いしてしまったこと 使用していないCSSの削減*の施策に時間が掛かってしまったこと の2点です。 こちらに関しては力不足を痛感しました。とても悔しい気持ちでした、、、 しかしこの悔しい気持ちをバネに今後エンジニアとして更に『成長していきたい』と気持ちが強くなりました!! PageSpeed Insights URL https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect&hl=ja 指摘を受けた内容 適切なサイズの画像 使用していないJavaScriptの削減 使用していないCSSの削減 原因特定 CSS削減の余地があると指摘を受けたのですが、まずは現状どのようにCSSが読み込まれている状況なのか確認しました。すると、assets/stylesheet/apllication.cssに全ファイル読み込まれている記述がありました。 assets/stylesheet/apllication.css @import 'bases/_variable'; @import 'bulma/bulma'; @import 'bases/_base'; @import 'partials/*'; @import 'pages/*'; 更に全ページの共通のレイアウトファイルであるviews/layout/application.html.slimにstylesheet_link_tag 'application'、 media: 'all'で全てのCSSファイルが読み込まれている現状でした。 views/layout/application.html.slim = stylesheet_link_tag 'application' media: 'all' このコードを見てわかったことは、全ページで共通のCSSを読み込んでしまっている事が原因で、ページ表示速度が遅くなっている、ということです。 原因を解決する為の学習 全ページで共通のCSSを読み込んでしまっている事が原因だったのですが、CSS設計の基礎を知らないと解決策の模索が出来ないなと思いました。そこでCSSの事をもっと詳しくなりたいと思い書籍を購入しました。 書籍を読んだ内容を元に今回のCSS設計時に重要となる観点をまとめ、その観点に基づいて最適な設計案を作成しました。目を通して特に重要であると思われる内容を絞り出しました。 参考書籍URL https://www.amazon.co.jp/dp/B0856YMH7L CSSの問題点と原因 CSSの問題点は、ページ数が増えるとCSSもどんどん複雑になり、管理しきれなくなってくる事です。数ページだけのシンプルなサイトであれば大した問題ではありませんが、世の中で使われているWebサイトは、決して小規模なものだけではありません。1ページのみでもWebサイトと呼べますが、上限は限りなく、100ページ、1,000ページ、10,000ページ超のWebサイトも珍しくありません。 そんな状況で何も考えずトップページではp要素を「大きくしたいから、fontsizeを18pxから20pxに変更しよう」とするとどうなるかというと、もちろんトップページだけ見れば意図した通りにp要素は20pxになります。しかしCSSの「スタイリングの内容がCSSファイルを読み込んでいるすべてのページに反映される」という仕様上、他のページのすべてのp要素も20pxになってしまいます。きちんとスタイリングの規則を決めた上でCSSが作成されているのであれば、まだよいですが、規則をきちんと決めていないと、「ページ数が増えると、CSSもどんどん複雑になり、管理しきれなくなってくる」という問題が発生し始めます。 規則のないCSSは、ページ数が10ページを超えただけでもすべてを把握するのは難しいです。そしてWebサイトは、制作して、公開し、終わり、ではありません。その次には情報を更新したり、新たなページを作成したり運用し続けていかないといけません。数ヶ月後の自分が、あるいは他の人が読み解いて、想定外の影響がないように運用していくのは、とても骨が折れる作業です。そしてそんな状態を避けようと規則を定めたとしても、すぐに破綻することがほとんどです。なぜこのようなことが起こってしまうのでしょうか? その原因は「CSSはすべてがグローバルスコープ」です。グローバルスコープとは読み込んだCSSファイル全てが同じスコープで管理されてしまう事。 原因を回避する為のCSS設計とは ではどの様な設計によってCSSを管理し壊れにくくすることができるのかと言うと、具体的には、「予測できる」、「再利用できる」、「保守できる」、「拡張できる」の4つ設計指針がある様です。これはGoogleのエンジニアであるPhilip Walton氏が「CSS Architecture」という記事で提唱した考え方です。 4つのCSS設計指針とは 予測できる スタイリングが期待通りに振る舞うかどうか スタイリングの影響範囲が予測できるか 再利用できる 既存のパーツを別の箇所でも使用したいとき、コードをいちいち書き直したり上書きする手間がない状態 保守できる 新しいモジュールや機能を追加・更新、あるいは配置換えしたとき、既存のCSSをリファクタリングする必要がない状態 拡張できる CSSに携わる人が1人であっても複数からなるチームであっても、問題なく管理できる状態 自分とその他の開発者にとってメンテナンス・管理がしやすくする事 施策提案の設計 上記の4つの設計指針と問題点を元に、現状のクライアントの開発人数が少ないこと、また今後実際に運用するのはクライアントである為、最終的にこのような設計方針で検討する事にしました。 ルールが複雑でない 拡張しやすい 影響範囲がみだりに広すぎない 現状からの修正コストが大きすぎない 何故このように考えたのか ルールが複雑でない 実際に運用し続け、複雑なルールを設定してしまうと今後変更したい時に修正しにくいのでシンプルな設計が必要だと思いました。 拡張しやすい Webサイトは「公開して終わり」ではなく、公開後も運用が続き、その中で既存のページやモジュールに対する変更が発生することも珍しくありません。今後もサービスが大きくなる可能性があると考えたからです。 影響範囲がみだりに広すぎない 影響範囲の広いCSSを修正しようとしても、影響範囲が広いので、どこでレイアウト崩れなどが発生するかわかりません。一度影響範囲の広いコードを書くと、修正と確認の作業コストにずっと悩まされ続けてしまうと考えたのでこの様な方針にしました。 現状からの修正コストが大きすぎない あまりに大きな修正ををしてしまうと依頼の納期に間に合わなくなってご迷惑おかけしてしまうと考え、大きな修正コストは掛けられないと判断しました。 実装方法を模索 設計指針に基づいて、分かりやすく複雑でなく、現状からの修正が大きすぎないというテーマを元にCSSの設計について調べてみました。調べてみるとファイル分割に焦点が当てられている記事を見つけました。 参考記事の内容 ViewファイルとCSSファイルを1対1になるようにファイルパスを揃えて、スコープ用にdata属性を書きます。修正したいViewファイルがあった場合、対となるCSSファイルを修正するだけで他のページに影響を与えず修正出来るのでとても管理しやすくなります。 次の手順で、各ページで必要なCSSファイルだけを呼び出す Viewファイルごとのルート要素に、自身の app/views/ 以降のファイルパス(拡張子抜き)を data-scope-path というデータ属性で設定。 対となる CSS 側では [data-scope-path="..."] という属性セレクタで絞って参照。 ファイルはapp/assets/stylesheets/エントリー名/scopesに格納。 参考記事URL https://tech.basicinc.jp/articles/166 何故この案にしようとしたのか この記事を読んでいくと、 設計を理解しているメンバーがプロジェクトから離れるとCSSの影響範囲を把握するのが大変です。CSS設計の場合、グローバルスコープなので全ページ確認しないといけないという大変な作業が待っています。新しいプロパティを追加する事によって、他のページのスタイルを崩してしまわないかと、複数のページを確認しなければなりません。どれだけCSSが得意な人がプロジェクトに入ったところで、解決は大変です。 とありました。 今後設計を理解しているメンバーが離れる事もあると思います。前任の方がプロジェクトから離れ新しいメンバーがプロジェクトに参加し、新規にプロパティを追加した事によってどこのページに影響しているのか把握出来ず、複数のページを確認しないといけない確認作業が大変になってしまいます。 そこでViewファイルとCSSファイルを1対1になる様に設計しておけば『このページはこのCSSファイルを変更するだけでOK 』と分かりやすいので、メンバーの入れ替わりがあっても管理しやすいのではと考えました。 この方法を使用し、全ページで同時に読み込まれているCSSファイル分割してページ毎にCSSファイルを読み込ませたら、分かりやすく、管理しやすいのではと思いこの案で実装していこうと思いました。 実装方針の提案書 今回の案件に対しクライアントに以下の様に提案書を提出しました。 CSSの設計方針 viewsの各ファイルに対して、以下方針で対応するCSSファイルを作成します ページファイル: CSSと1:1対応させる パーシャルファイル CSSと1:多対応させる 施策提案書を提出し確認を取る 実装方法を確認したところ、大まかな流れですが承諾頂けました。 一つクライアントから、『ページ単位での分割は実装/移行コストが少し高いように感じるのでコントローラー単位での分割に切り替えて欲しい』という依頼を頂きました。 私が提案した内容は、コントローラ単位での分割にも応用出来る内容でした。そこで開発方針を「ページ単位での分割」から「コントローラー単位での分割」に切り替えました。実装方針を固める事が出来たので本格的に実装開始する事にしました。 まず最初にユーザーがアクセスし、表示されるトップページで使用されるコントローラーから施策をスタートしました。順次流入数が多いページで使われるコントローラーの順番で進めていく方向で決まりました。施策内容と施策順序の許可を頂けましたので、ここから実際に手を動かし実装開始となります。 2. 実装開始 まずは全ページ読み込まれてしまっているのでコントローラー毎に必要なCSSファイルを読み込めるようにする為の基盤作りから進めていきました。 全ページの共通のレイアウトファイルであるviews/layout/application.html.slimに対し 1. if文の条件分岐で値が入っていたら個別のCSSを読み込み、なかったら既存のapplication.cssを読み込む stylesheet_link_tag yield(:stylesheet_scope)でビューテンプレートに対応するCSSファイルを呼び出す views/layout/application.html.slim - if content_for?(:stylesheet_scope) = stylesheet_link_tag yield(:stylesheet_scope), media: 'all' - else = stylesheet_link_tag 'application', media: 'all' 2. 設定したいコントローラで扱われるビューファイル全部にvirtual_pathを指定 各ページテンプレートの最上位の要素に記載 app/views/hoge/hoge.html.slim - stylesheet_scope(@virtual_path) 3. メソッドを定義しスコープを受け取れるようにする app/helpers/application_helper.rb STYLESHEET_PATH_PATTERN = /^(?<controller>[a-z_]+?)\/(?<method>[a-z_]*)$/ def stylesheet_scope(path) controller_name = path.match(STYLESHEET_PATH_PATTERN)&.[](:controller) content_for :stylesheet_scope, controller_name end 4. app/assets/stylesheets/直下にCSSファイル作成 コントローラー名の CSSファイルを作成し、コントローラで使われているビューファイルのCSSを全て読み込ませる app/assets/stylesheets/hoge.css @import 'bases/_variable'; @import 'bulma/bulma'; @import 'bases/_base'; @import 'partials/_footer'; @import 'partials/_header'; @import 'pages/_hoge'; @import 'partials/_fuga'; 3. 実装結果 数値を確認した結果、ページの読み込みスピード改善ができていました。 下記の検証手順で確認してみると、現在読み込まれているCSSファイルが確認できます。 今後サービスが大きくなり別の方がアサインされた場合でも拡張しやすく、新しいモジュールや機能を追加し、配置換えしたときでも保守性も保たれると思います。特にコントローラーとCSSファイルを1:1にする事によってどこのCSSファイルを読み込んでいるか分かりやすくなったと思い、今後の運用しやすくする為の基盤が作られたと思います。 個別読み込みと読み込みスピード改善の検証方法 Coverage機能による検証手順 Google Chromeの検証ツールからCoverage機能を使用 a. 「Coverage」という機能を使用するのですが、標準では表示されていないので初回は追加設定します。 b. 「開発者ツール」右上に表示されている「…」が縦に並んだ設定ボタンをクリックします。 c. 「More tools」から「Coverage」を選択し追加します。 d. 「Coverage」が追加されると、開発者ツールの下に表示されます。 Coverageで表示されるURLを確認 a. 対象ページ:設定したCSSファイルが読み込まれている b. 対象外のページ:application.cssが読み込まれている 読み込みスピードの改善数字 a. Before: LCP 1.5秒 b. After : LCP 0.8秒 計測結果と確認一覧 実装後にPageSpeed Insightsでページ読み込みスピードが改善されているか数値確認し、Coverage機能を使い現在読み込まれているCSSファイルの確認をしました。 確認項目 読み込み箇所の確認は以下の通りです。 個別読み込みを設定し必要なCSSが読み込まれている 個別で設定したCSSファイルだけがしっかり読み込まれています。 個別読み込みを設定していないので全ファイルのCSSが読み込まれている @import 'pages/*':のようにディレクトリ内の全ファイルが読み込まれています。 計測結果 計測結果は以下の通りです。 コントローラ毎に個別のCSSが読み込まれている状態の計測数値 LCPの計測値が0.8秒と基準値より上回っています。 個別読み込みを設定していない状態の計測数値 LCPの計測値が1.5秒と基準値より下回っています。 実務を始める前と終えた後の変化 実務経験前と経験後でプログラミングに対しての考え方や取り組み方が大きく変わりました。 具体的に3つです。 1. エンジニアとしての心構え 実務を経験する前は書いてある事をそのままやる事しかしてこなかったと思います。教材があり、そこに書いてある事をそのままやるだけで自分で考えて取り組んでいませんでした。 今回実務体験をさせていただき、課題に対してどうやって解決出来るか思考し、それに対しての解決策を導き出す大切さを知る事ができました。書いてある事をそのままやるのではなく自分で思考して取り組む大切さを知る事ができました。 2. コードに対しての品質の意識 これは本当に反省です。最も意識が変わった事だと思います。実務経験前の私は動けば大丈夫くらいな気持ちでコードを書いていました。 コード品質の良し悪しがサービスの良し悪しにも直結します。しっかり理解したコードを書き、他の人が見ても分かる様なコードを書き品質を落とさない大切さを知る事ができました。 3. 相手が言っていることを理解する力と伝え方 仕事は基本相手がいて成立するものなので、自分から提案する力、正確に伝える文章力、相手が本当に必要としていることを汲み取る力が大切だと気づけました。 今回の実務を終えて一つ毎日続けようかなと思うことが一つあります。 それは読書です。 元々読書はしていたのですが今後はアウトプット前提の読書をしていきます。 アウトプットとは読書をしたら感想文を書くという事です。感想文を書くという事は、何となく読書してたら感想は書けないので集中して読む+作者の意図を正確に理解する力がついていくと思います。今後エンジニアとして働くときに相手の言っている事の理解と背景を汲み取る力をつける事によって、一番良い結果をクライアントやお願いしてくれたメンバーにお返しが出来ると思いました。ビジネスマンとして成長する為に、今後『読解力』と、『ロジカルシンキング』の二つの力を付けていきます。 実務を終えての感想とプログラミングに対しての思い 今回の経験を踏まえて、自分に改めて足りていないもの、学習しなければならないこと、エンジニアという職業がコードを書くだけの職業ではないこと、技術以外に必要となるスキル、エンジニアになるってどんなことなのか等、本当に多くのことを学ばせていただきました。 実務を通し、改めてエンジニアという職業の魅力を感じました。エンジニアの技術と現職の楽器の演奏技術は似ているなと改めて感じました。 僕は音楽講師を目指した時も技術面に関して何度もつまずき悩まされた事がありました。 そんな僕でも自分の弱点をしっかり分析し一つずつ解消する事によって講師テストに合格する事ができました。 今回も状況がよく似ていると思っています。 エンジニアという立場で仕事をするとは、音楽に置き換えるとライブ出演したような感覚でした。 最初は周りに迷惑をかけてしまう事があると思いますが、誰よりも情熱を持って取り組んでたらその差は埋まると思っています。 エンジニア転職した後も、一つ一つ毎日技術や知識を積み上げて成長し、会社で必要とされ、将来リーダー的なポジションを目指し、メンバーを引っ張っていける様なエンジニアを目指して行きたいと思います。 今回リーダーのY氏に褒められた部分が明るく、ポジティブなのでチームに居るとチームが明るくなると言っていただけました。とても嬉しかったです。技術面では未熟ですが、エンジニアではチーム開発する時の雰囲気作りも大切なんだなと学べました。将来的にチーム開発に携わる時は雰囲気作りのサポートもしていきたいです。それと僕は教える事は仕事柄得意な方だと思うので、新人教育などにも携わっていきたいなと思い、段階的に各ポジションに就いてみたいと思っています。 学習が大変という意見もありますが、好きな事を「学習する」という考えは、違和感があります。 僕は楽器の練習を練習と思ってなく、好きな事だから自然と追求するものだと思っています。 プログラミングに対しても同じ思いでいます。まだ分からない事だらけで自然に追求していけるレベルまで到底達していませんが、そのレベルまでいったら僕は凝り性なのでどんどん追求できる自信があります。 そして何より感謝したいのは、リーダであるY氏と、クライアントです。 私に何度もコードレビューや、施策提案の進め方を丁寧に指導していただく事によって、今回の実務をやり遂げる事ができました。まだまだ自分の力だけでは出来ていないことばかりですが、今後しっかり成長し、あの時育ててよかったなと思ってもらえる様なエンジニアに成長していきます。 同じミスをしない対策としては、読解力を鍛え、何をして欲しいか理解し、技術+知識+理解力を付けて同じミスをしない様にしていきます。 一緒に実務に挑戦した仲間たちにもとても感謝しています。大変な時に励まし合える仲間がいる事は本当に素晴らしいなと実感しました。 エンジニアとしてまだまだ至らない部分が多くありますが、学習を継続するとともに、今後の転職活動に力を入れたいと思います。ご覧いただきありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】newメソッドとbuildメソッドの使い分け方【初学者の疑問点を簡潔に解説】

はじめに  本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。  そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。  間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。 今回の疑問点  今回の疑問点は、   newとbuildの使い分け    です。   以前、フォロー/フォロワー機能の実装の際に出てきてnewメソッドとの使い分けについて疑問を抱きました。  今回、調べて見てわかったことをまとめます。 疑問点についての解説 結論  インスタンスを生成するメソッドという点では共通しているが、モデルの関連付けの際にはbuildを使用する。 buildメソッドの記述方法  モデルの関連付けの際に使用すると記載しましたが、アソシエーションの状況によって記述の仕方が異なるようです。 アソシエーションが1対1の場合 @user = User.new @card = @user.build_card アソシエーションが1対1の場合には、build_関連付けのメソッド名と記述します。 アソシエーションが1対1の場合 @user = User.new @card = @user.build_card アソシエーションが1対多の場合 @user = User.new @card = @user.cards.build アソシエーションが1対多の場合には、関連付けのメソッド名.buildと記述します。 アソシエーションが1対多の場合 @user = User.new @group = @user.groups.build アソシエーションが1対多の場合には、1対多と同様に関連付けのメソッド名.buildと記述します。 まとめ 最後にポイントをまとめます。 buildアクションはモデルの関連付けの際に使用する。 buildアクションの記述方法は以下の通り。 アソシエーションが1対1:build_関連付けのメソッド名 アソシエーションが1対多又は多対多:関連付けのメソッド名.build
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む