- 投稿日:2019-09-29T23:57:51+09:00
Rails 5.2 + Docker, RAILS_MASTER_KEYをイメージ作成時に動的に入れる方法
ブログから移動したものです。
下記のような形でDockerfileを作成する。
FROM ruby:2.6.0-alpine3.8 ENV RAILS_ENV=production ENV APP_ROOT /usr/src/app ARG RAILS_MASTER_KEY ENV RAILS_MASTER_KEY ${RAILS_MASTER_KEY} WORKDIR $APP_ROOT RUN apk add --no-cache alpine-sdk \ nodejs-current \ nodejs-npm \ yarn \ mysql-client \ mysql-dev \ python2 \ tzdata COPY Gemfile $APP_ROOT COPY Gemfile.lock $APP_ROOT RUN bundle install --jobs=4 COPY . $APP_ROOT RUN bin/yarn install RUN bin/rails webpacker:compile VOLUME $APP_ROOT/public VOLUME $APP_ROOT/tmp下記の部分がポイントとなっている。
ARG RAILS_MASTER_KEY ENV RAILS_MASTER_KEY ${RAILS_MASTER_KEY}下記のような形でCI上で環境変数をARGとして渡してやれば(CI側の環境変数にRAILS_MASTER_KEYが設定されている前提)、上記のARGにRAILS_MASTER_KEYが設定され、ENVのRAILS_MASTER_KEYにARGのRAILS_MASTER_KEYを設定することができる。これにより、イメージ作成時にRAILS_MASTER_KEYを設定した状態でビルドすることができる。
docker build --build-arg RAILS_MASTER_KEY=${RAILS_MASTER_KEY} -t app . -f Dockerfile.production参考:
* https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39
* https://qiita.com/nacika_ins/items/cf8ceb20711bd077f770
- 投稿日:2019-09-29T22:31:54+09:00
Ruby勉強その4
引き続きRubyの勉強を推めています。
現在、第7章まで終了したところです。今回は前回の投稿の続きということで6章の感想等を書いていきたいと思います。○気になったこと
1.正規表現の便利さ
最初の率直な感想はこれでした。今まで少し使用したことがある...というレベルでしたので、
有用性などはあまり感じなかったのですが伊藤淳一さんの投稿などで勉強していくうちに便利さが理解できました。
余裕が出来たら、もっと勉強したいですね。○難しかったこと
1.正規表現に関するメソッドの多さ
regexpクラスとstringクラスの正規表現に関するメソッドが多く覚えるのが大変だなと感じています。
と同時使い分けの難しさを感じました。(scan?とsplitとmatchしかまだ覚えていないので...)説明の内容自体は大体理解出来ましたが、まだ全然覚えていないので繰り返し読んでしっかり覚えてたいですね。
(とはいえまだまだ正規表現の奥深さは感じています)少し短いですが、今日はこのへんで失礼します。
引き続き勉強していきます。
- 投稿日:2019-09-29T22:18:57+09:00
6&7/100日目 #100DaysOfCode #qiita #駆け出しエンジニアと繋がりたい #プログラミング初心者
やる予定だったもの
atomインストール等環境構築
rails2-3章 実機
予定見直しやったこと
Atomインストール
ローカル環境構築
⇨progateのrailsをローカル環境でできるようになった!!ローカルサーバーで画面出力
学習時間
1.0h
反省・改善点、気づき
初めての土日なのに全然時間確保できず、自分に甘いところが出てしまいました...
ネット上でもなんか繋がれるコミュニティがあるといいんだけど。
progateってコマンド操作ができず、使いにくさがいなめなかったのですがそれを解消できたのでよかった。明日やること
rubyの残りの章 読み込み
rails 2-3章 実機操作
html CSSの残りの章 読み込み
- 投稿日:2019-09-29T22:06:25+09:00
paizaの超初級問題で挫折したが、なんとか問題が解けるようになった方法
簡単な紹介
2019年5月からRubyの勉強を始めた初心者です。
処理や出力はできるのですが、最初の受け取りにかなり苦戦したので
初心者が受け取りで躓かないように、そして挫折しないように書いておきます。今回挫折しかけた問題
足し算
半角スペースで区切られた2つの正の整数を足し算して出力する問題です。解くためにやったこと
・受け取り方法をGoogle検索で調べる
・メソッドの意味や使い方をGoogle検索で調べる
・メソッドを使うことでどのような処理をされているのか調べた検索は『やりたい処理 メソッド Ruby』などで検索をかけて地道にコードに
埋め込んで、実行してみて思い通りの動きをするのか?また、書き方はあっているのかなど、まずは色々試してなんとか動くように必死で検索してトライしてみました。
練習問題は公開OKとのことなので、初心者の方の参考に残しておきます。
もっと良い書き方や処理の早い方法などあると思いますが、動くことを第一優先に下記のメソッドとコードを書いて通過することができました。使用したメソッド
gets
"文字\n"
文字列と改行文字を受け取りchomp
\n(改行)を取り除くsplit("")
文字列を分割して配列にするmap(&:to_i)
要素を一括で数値に変換sum
配列の要素を合計n = gets.chomp.split(" ").map(&:to_i).sum p n
最後に、私は検索しまくってなんとか自力で解けたのですが、基礎知識がなくてだいぶ苦しみました。しかし、調べていく中で徐々に知識がついていき解けるようになりました。この記事を参考にコピペではなく、実際に手を動かして色々やってみるといつの間にか成長することができるのだと実感しました。参考になれば嬉しいです。
- 投稿日:2019-09-29T21:27:43+09:00
ruby nkf メモ
Rubyのnkf のオプションを理解するためのメモ
require 'nkf' str = "あアぁアヴバパヴ0101abABabAB" # -w はUTF-8(BOMなし)で出力するオプション デフォで半角カナを全角カナ変換する NKF.nkf("-w", str) => "あアぁアヴバパヴ0101abABabAB" # -x をつけると半角カナはそのまま出力される NKF.nkf("-xw", str) # => "あアぁアヴバパヴ0101abABabAB" # ひらがなをカタカナに変換 NKF.nkf("-h1 -w", str) # => "ああぁあゔばぱゔ0101abABabAB" # カタカナをひらがなに NKF.nkf("-h2 -w", str) # => "アアァアヴバパヴ0101abABabAB"
- 投稿日:2019-09-29T19:20:55+09:00
█║▌ Distributed Fault-Tolerant Authentication Management & Identification Control System
At the rate at which technology today is moving forward with the Internet speeds increasing manifold, with IoT gaining prominence and organizations more distributed across the globe than before, the authentication software, systems and architectures remain fairly primitive.
Among the many reasons attributing to this is corporates that build these authenticating systems and software hold on to these products as their main source of income. The insight and research in these areas has also been fairly mundane. Though there's been enough research funding, what's missing has been the intellect and knowledge required to build large-scale distributed and decentralized authentication systems and architectures.
Large-scale authentication systems and architectures used in building them must allow both manned [computers, tablets, phones, virtual machines etc] and unmanned [IoT devices etc] to authenticate and authorize themselves without a centralized bottleneck, as seen in authentication systems like LDAP, Active Directory and others.
As experienced on a daily basis, these centralized authentication systems are not scalable or fault-tolerant without a sane fail-over MTBF [Mean Time Between Failure] causing business disruptions on a regular and long-lasting basis.
■ What can be done about this?
Let us acquaint ourselves with AuthControl. SynchroKnot designed and developed AuthControl as a result of realizing inadequacies in the centralized authentication systems [LDAP & Active Directory].
AuthControl was designed with the following flexibility in mind:
- Ability for authentication to be either centralized, distributed, decentralized or a combination of these.
- Ability to be seamlessly and transparently scaled on-demand across the globe with no downtime.
- Ability to be used by standard operating systems within their security framework without custom or proprietary software, enhancements, modifications or hacks.
- Ability to be used across all devices that can make a simple https call. and much more.
■ What is AuthControl?
AuthControl is SynchroKnot's unique Distributed Fault-Tolerant Authentication Management & Identification Control System that serves as a scalable, secure and simple alternative to LDAP, Active Directory and other authentication systems.
In AuthControl, the user[s] can be delegated and made responsible for managing their password. Furthermore, the user's password SHA512/GOST checksum is kept encrypted.
■ Password + Pin
The user[s] can log in to their virtual machines or physical hardware [eg. computers, tablets, mobile phones etc] with their standard username and password + 5 digit unique pin.
This 5 digit pin is not set by the user, but is rather auto or manually generated per the preference of the organization. Without having to manage separate pins for each user, and the ability to change them on a regular basis, makes logging into systems and authentication for various purposes more secure without adding the burden of lengthy procedures/steps.
Depending on the nature of the circumstance, user access can be restricted/limited by simply changing the PIN.
■ Algorithmically-ascertained decentralized numeric User and Group ID
Authcontrol also has the unique capability of creating operating system specific user and group identities that are unique. For example, AuthControl can create a Linux User ID and Group ID that are unique and always return the same numeric value for the ID.
This unique numeric user and group ID is algorithmically created in a decentralized manner without having to generate, store and poll centralized or distributed databases.
Due to the uniqueness of the user and group IDs, they can be instantly checked for changes/manipulations and reinstated automatically if changed without having to poll, check and compare with central or distributed databases. It can also report/alert in the similar manner.
AuthControl's strong security is strengthened with the use of inter-leaved mapping of Usernames to their Blockchain IDs and further using blockchain cryptography [not the blockchain network] to ascertain authenticity. This is another unique feature you will not find anywhere else but with SynchroKnot.
■ Fault Tolerant
AuthControl algorithmically checks for failures across multiple geographically-dispersed locations [configurable up to 10] before returning unreachable.
■ Load Balanced
Each user or groups of users can be assigned different geographically-dispersed locations for load balancing [with additional option of fault-tolerance].
■ Scalable
Enable AuthControl in virtual or physical machines, point more users to them, and scale seamlessly and transparently across the globe.
■ Simple
Very easy to set up and manage. Works transparently with Linux PAM without modifying standard PAM modules, and is end-to-end encrypted [uses standard HTTPS for communication].
Since this is just an article for getting acquainted with AuthControl, we refrain from getting into technicalities which might be better reflected in a whitepaper.
■ Below are examples of different methods that users can log in or access resources transparently with their standard Username and Password + 5 Digit PIN:
│
├─> Graphical Login
├─> Graphical Screen Saver Login [eg. screen lock]
├─> Non-Graphical Login
├─> SUDO - Execute a command as another user
├─> SU - Super User
├─> SSH - Secure Shell
├─> SCP - Secure Copy
├─> SFTP - Secure File Transfer Protocol
├─> SSHFS - Secure Shell File System
├─> FTP - File Transfer Protocol
├─> VNC - Virtual Network Computing
├─> RDP - Remote Desktop Protocol
├─> CUPs - standards based open source printing system
├─> CRON - Execution of scheduled commands
├─> SAMBA - Windows AD and SMB/CIFS fileserver for UNIX
├─> File Manager - Create Network Place with SFTP, SAMBA and FTP
├─> All password requirements via Control Center
├─> Practically anything that uses Standard PAM for authentication!Below is a direct link to the demonstration video:
http://synchroknot.tokyo/AuthControl.mp4
Description of the demonstration:
This is a very basic impromptu demonstration of AuthControl. Here both of the virtual machines are enabled with AuthControl and show the following:
■ Login via Graphical Interface
■ Login via Non-Graphical Interface
■ Run a command with SU as another user
■ Run a command with SUDO as another user
■ Login to a remote system via SSH
■ Mount a remote filesystem via SSHFS
■ Use File Manager to create a Network Place using SFTP
All these different types of logins use AuthControl with standard Linux users and password + 5 digit pin. The basic HTTPS traffic is captured using TCPDUMP to show realtime interaction with the SynchroKnot AuthControl when the password is entered in the virtual machines for the purposes of authentication.
Note: This demo was recorded on a severely resource-constrained system. It is up to you to determine the performance.
- 投稿日:2019-09-29T19:01:50+09:00
[初心者]Docker+Rails+MySQLでの環境構築の記録
はじめに
cloud9やvagrant以外にも
Dockerを使って環境構築してみたいと思い、勉強をしてみました!
Docker環境構築をする上で行った事を振り返ってまとめています。Dockerについて
- ホストOSのカーネルを使用している為、軽量で起動が高速
- 複数人で開発する時に開発環境を統一しやすい
- そのまま本番サーバーにデプロイする事ができる
などのメリットがあると知り、
様々の方のqiita記事など参考に環境構築に取り組んでみました。環境
- Mac OS
- Ruby 2.6.3
- Rails 5.2.3
- MySQL 8.0
【1】作業ディレクトリの作成、移動
$ mkdir sample $ cd sample【2】Dockerfileの作成
$ vi DockerfileDockerfileFROM ruby:2.6.3 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /sample WORKDIR /sample ADD Gemfile /sample/Gemfile ADD Gemfile.lock /sample/Gemfile.lock RUN bundle install ADD . /sample【3】Gemfile、空のGemfile.lockを作成
$ vi GemfileGemfilesource 'https://rubygems.org' gem 'rails', '5.2.3'$ touch Gemfile.lock【4】docker-compose.ymlの作成
$ vi docker-compose.ymldocker-compose.ymlversion: '3' services: db: image: mysql command: mysqld --default-authentication-plugin=mysql_native_password environment: MYSQL_USER: root MYSQL_ROOT_PASSWORD: password ports: - '3316:3306' volumes: - ./db/mysql/volumes:/var/lib/mysql web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/sample ports: - "3000:3000" depends_on: - db【5】Rails newを実行する
$ docker-compose run web rails new . --force --database=mysql【6】イメージを再ビルドする
$ docker-compose build【7】config/database.ymlの設定
config/database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: host: localhostdatabase.ymlが上記のようになっているので
下記のように書き換える。config/database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password host: db【8】サービスを起動する
$ docker-compose up -d【9】DBを作成する
$ docker-compose run web rails db:create【10】アクセスしてサーバーの起動を確認する
http://localhost:3000
にアクセスしてRailsのトップページが表示されたら完成です。その後、サーバーを止める時は
docker-compose stop
とします。感じたこと
まだまだDockerに関する知識は浅いですがとにかく環境を構築する事ができました!
環境構築中MySQLの認証プラグインのエラーが発生してかなり苦戦したのですが、
どうやらMySQL8.0は
【4】docker-compose.ymlの作成のところで
command: mysqld --default-authentication-plugin=mysql_native_password
を書かないとエラーが出てしまうようです。
このエラーを解決する為に様々な方法を試していくうちに
MySQLの権限エラーが新たに出るなどして泥沼にハマっていき
10時間ぐらいかかって解決して何とか環境構築できました(汗)環境構築はとりあえずできましたが
何がどうなっているのかなどまだまだDockerを理解できていない部分が多いので
今後更に深く学習してみようと感じました。参考
[Rails] DockerでRails + MySQLの開発環境をつくる手順
丁寧すぎるDocker-composeによるrails + MySQL on Dockerの環境構築(Docker for Mac)
Docker Composeのインストール方法(CentOS7.3)
- 投稿日:2019-09-29T19:01:50+09:00
【初心者】Docker+Rails+MySQLでの環境構築の記録
はじめに
cloud9やvagrant以外にも
Dockerを使って環境構築してみたいと思い、勉強をしてみました!
Docker環境構築をする上で行った事を振り返ってまとめています。Dockerについて
- ホストOSのカーネルを使用している為、軽量で起動が高速
- 複数人で開発する時に開発環境を統一しやすい
- そのまま本番サーバーにデプロイする事ができる
などのメリットがあると知り、
様々の方のqiita記事など参考に環境構築に取り組んでみました。環境
- Mac OS
- Ruby 2.6.3
- Rails 5.2.3
- MySQL 8.0
【1】作業ディレクトリの作成、移動
$ mkdir sample $ cd sample【2】Dockerfileの作成
$ vi DockerfileDockerfileFROM ruby:2.6.3 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /sample WORKDIR /sample ADD Gemfile /sample/Gemfile ADD Gemfile.lock /sample/Gemfile.lock RUN bundle install ADD . /sample【3】Gemfile、空のGemfile.lockを作成
$ vi GemfileGemfilesource 'https://rubygems.org' gem 'rails', '5.2.3'$ touch Gemfile.lock【4】docker-compose.ymlの作成
$ vi docker-compose.ymldocker-compose.ymlversion: '3' services: db: image: mysql command: mysqld --default-authentication-plugin=mysql_native_password environment: MYSQL_USER: root MYSQL_ROOT_PASSWORD: password ports: - '3316:3306' volumes: - ./db/mysql/volumes:/var/lib/mysql web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/sample ports: - "3000:3000" depends_on: - db【5】Rails newを実行する
$ docker-compose run web rails new . --force --database=mysql【6】イメージを再ビルドする
$ docker-compose build【7】config/database.ymlの設定
config/database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: host: localhostdatabase.ymlが上記のようになっているので
下記のように書き換える。config/database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password host: db【8】サービスを起動する
$ docker-compose up -d【9】DBを作成する
$ docker-compose run web rails db:create【10】アクセスしてサーバーの起動を確認する
http://localhost:3000
にアクセスしてRailsのトップページが表示されたら完成です。その後、サーバーを止める時は
docker-compose stop
とします。感じたこと
まだまだDockerに関する知識は浅いですがとにかく環境を構築する事ができました!
環境構築中MySQLの認証プラグインのエラーが発生してかなり苦戦したのですが、
どうやらMySQL8.0は
【4】docker-compose.ymlの作成のところで
command: mysqld --default-authentication-plugin=mysql_native_password
を書かないとエラーが出てしまうようです。
このエラーを解決する為に様々な方法を試していくうちに
MySQLの権限エラーが新たに出るなどして泥沼にハマっていき
10時間ぐらいかかって解決して何とか環境構築できました(汗)環境構築はとりあえずできましたが
何がどうなっているのかなどまだまだDockerを理解できていない部分が多いので
今後更に深く学習してみようと感じました。参考
[Rails] DockerでRails + MySQLの開発環境をつくる手順
丁寧すぎるDocker-composeによるrails + MySQL on Dockerの環境構築(Docker for Mac)
Docker Composeのインストール方法(CentOS7.3)
- 投稿日:2019-09-29T18:21:09+09:00
カレンダーの上で同一の時間帯のタスクの登録/更新をできないようにする
何がしたいか
環境
Rails v5.2.3
ruby v2.6.3p62gem
fullcalendar-rails v3.9テーブル構造概要
どうやって実現しよう...
modelにカスタムバリデーションを追加してエラーにしたい。
(controllerで行うと責務が増えすぎる気もした)
バリデーションでDBに保存済みの時間と画面から入力された時間を比較し、件数が0件か1件以上あるかで実装を頑張る。条件としては
DBに保存済みの開始時間<入力された開始時間or入力された終了時間<DBに保存されている終了時間
にエラーとするべきと考えた。
⇨SQLでの抽出条件:
"DBに保存済みの開始時間 < 画面から入力された開始時間
AND 画面から入力された開始時間 < DBに保存されている終了時間
OR DBに保存済みの開始時間 < 画面から入力された終了時間
AND 画面から入力された終了時間 < DBに保存されている終了時間"実装したソース
controller.rbdef create #新規登録 act_history = current_user.activity_historys.build( activity_name: @json_hash[:activity_name], from_time: @json_hash[:from_time], to_time: @json_hash[:to_time], remarks: @json_hash[:remarks], action: "create", #アクセサにセット current_user: current_user #アクセサにセット ) ...(略) end def update #更新 ...(略) respond_to do |format| if act_history.update( activity_name: @json_hash[:activity_name], from_time: @json_hash[:from_time], to_time: @json_hash[:to_time], remarks: @json_hash[:remarks], action: "update", #アクセサにセット current_user: current_user #アクセサにセット ) ...(略) endmodel.rb# アクセサ attr_accessor :action, :current_user # バリデーション validate :check_time ...(略) private def check_time ...(略) same_time_zone_exists end ...(略) # 画面から受け取った開始時間、終了時間をもとにすでにDBに存在しているか検証する def same_time_zone_exists exists_act_historys = current_user.activity_historys.where( #SQL抽出条件 "(from_time < ? AND ? < to_time OR from_time < ? AND ? < to_time)", from_time, from_time, to_time, to_time ) if action == "create" && exists_act_historys.count > 0 errors.add(:from_time, ": 同一時間帯の登録はできません") errors.add(:to_time, ": 同一時間帯の登録はできません") elsif action == "update" && exists_act_historys.count > 0 exists_act_historys.pluck(:id).each do |exists_ids| if exists_ids != id errors.add(:from_time, ": 同一時間帯の登録はできません") errors.add(:to_time, ": 同一時間帯の登録はできません") end end end end実装後
抽出条件が足りない模様。
入力された開始時間<DBに保存済みの開始時間〜終了時間<入力された終了時間
⇨SQLでの抽出条件:
"画面から入力された開始時間 < DBに保存済みの開始時間
AND 画面から入力された終了時間 < DBに保存されている終了時間"完成版ソース
model.rb# 画面から受け取った開始時間、終了時間をもとにすでにDBに存在しているか検証する def same_time_zone_exists exists_act_historys = current_user.activity_historys.where( #抽出条件追加 "(from_time < ? AND ? < to_time OR from_time < ? AND ? < to_time) OR (? < from_time AND to_time < ?)", from_time, from_time, to_time, to_time, from_time, to_time ) if action == "create" && exists_act_historys.count > 0 errors.add(:from_time, ": 同一時間帯の登録はできません") errors.add(:to_time, ": 同一時間帯の登録はできません") elsif action == "update" && exists_act_historys.count > 0 exists_act_historys.pluck(:id).each do |exists_ids| if exists_ids != id errors.add(:from_time, ": 同一時間帯の登録はできません") errors.add(:to_time, ": 同一時間帯の登録はできません") end end end end感想
とりあえず実装はできたので良いが、結構処理が複雑になっているように見えるので、もっとスリムにしたいです。他に方法があったらご指摘ください
- 投稿日:2019-09-29T17:52:59+09:00
Watirのgemを使ってSelenium::WebDriver::Error::WebDriverErrorのエラーが出た時の対処法
- 投稿日:2019-09-29T17:50:08+09:00
Angular8+Rails5でアプリを作ってみる
AngularとRailsを組み合わせてみる
前回の記事ではAngular+NestJSの組み合わせについてピックアップをしましたが、今回はRuby on Rails5とAngular8の組み合わせでwebアプリを作成している記事があり、読んでいてとても面白い内容だったので翻訳に挑戦しました!どちらも個人的に気に入っているフレームワークなので、世の中にこの組み合わせでの開発が増えてくると嬉しいです。
Angular8とRails5 (*以下記事の翻訳)
あたなはどうか知らないが、学びやすく、素早く書けて、オープンソースという理由で私はRuby on Railsが大好きだ。また、Ivyというクールな新しいレンダーエンジンを導入したAngularの新バージョン、Angular8のリリースにもワクワクしている。
もしあなたが私と同じでこれら2つのフレームワークに関する興味をわかってくれて、でも、その素晴らしい2つをどう始めたら良いのかさっぱりわからない場合は、ぜひこれを読んでほしい。
さっそく初めてみよう!
慣習的にJavascriptフレームワークと一緒にRailsを使う場合は、webpackが必要とされていた。しかし、Railsにはwebpackerと呼ばれるこれにうってつけのgemがあり、Angularプロジェクトを動かしてくれる。しかし、最新バージョン(7系以上)のAngularでは内部でwebpackシステムを持っており、そのようなプロジェクト構成が、素晴らしいAngularCLIを使う妨げとなってしまうのだ。
その代わりに私たちがしなければならないのは、Angularからの出力ファイルを受け取り、それらを提供するコントローラを備えたAPIとしてのRailsアプリを使うことだ。
始める前に下記をインストールしてほしい。
- node (8.9以上)
- NPM (5.5.1以上)
- Angular CLI
- Rails 5+ (インストールにRVMまたはRbenvを使うことをおすすめします)
- Postgresql
1. Angularプロジェクトを作成する
好きなディレクトリの場所でターミナルを開いて、Rails/Angularプロジェクトを作成する。
ng new rails-angular-project
Angular routingを使うか聞かれたら、迷わず「YES」を押しちゃってください!(かなり良いですよ!)
その次に、好きなスタイルシートの形式を選択して下さい。(個人的にはSCSSで進めてます)
そして、全て完了したら先ほど作ったプロジェクトにジャンプしましょう!
cd rails-angular-project
2. Railsプロジェクトを作成する
では、現在のディレクトリにRailsプロジェクトを作成しましょう!
rails new . -database=postgresql
これによって、Angularプロジェクトの内部にRailsプロジェクトを作成し始めるが、全てのマージを拒否した場合、コンフリクトが発生する。
Railsプロジェクトが作成されたなら、.gitignoreファイルにいくつかファイルを追加する必要があります。
.gitignoreファイルを開いて、下記をコピペして下さい。# Ignore bundler config. /.bundle # Ignore all logfiles and tempfiles. /log/* /tmp/* !/log/.keep !/tmp/.keep # Ignore uploaded files in development /storage/* !/storage/.keep .byebug_history # Ignore master key for decrypting credentials and more. /config/master.key # Ignore application configuration /config/application.yml3. 上記2つを合体する
今の段階で、Angularプロジェクトと一緒になったRailsアプリとなっており、これはAPIとしてのRailsを使用し提供している一方で、Angularフレームワークを用いたSPAの利益も享受していることと言える。しかしその前にRailsにAngularが提供するファイルにアクセスできるようにしなければならない。
通常はAngularアプリでは、
ng serve
を使用して開発を進めるのだが、今回はng build
を使用してRailsのパブリックディレクトリに出力するように設定する。ルートディレクトリにある
Angular.json
を開いて、出力先ディレクトリをdist/rails-angular-app
からpublic
に変更する。angular.json... "options": { "outputPath": "public", ...次に、app/controllersに
static_controller.rb
という名前のファイルを作成する。app/controllers/static_controller.rbclass StaticController < Rails::ApplicationController def index render file: Rails.root.join('public', 'index.html') end endstatic_controllerはAngularによって提供される
index.html
をレンダリングする役目を持ちます。そして、下記のコードを
routes.rb
に追加して下さい。routes.rbRails.application.routes.draw do get '*other', to: 'static#index' endこれで、Railsにルートをキャッチさせて、static_controllerにリダイレクトすることができます。また、上記のコードによってapiに必要となるどのルートも定義することができるのです。でもそれは次の機会に回しましょう!
4. Foremanを使って便利にする
Foremanを導入することによって、Webアプリを提供しやすくしましょう。
gemに
foreman
を追加することによってインストールして下さい。Gemfile... # Use foreman gem 'foreman' ...
bundle install
で新しいgemをインストールします。
bundle install
Procfileと呼ばれるファイルを新しくルートディレクトリに追加します。これは組み合わせされる全てのコマンドをforemanが読み込めるようにするためのファイルです。
Procfileweb: rails s -p 3000 client: ng build --watch=trueこれでforemanを起動できます。
foreman start
RailsアプリとAngularアプリが同時に起動されるはずです。そして、
localhost:3000
にアクセスすると以下のような画面が表示されるでしょう。完了です!これで自由にWebアプリを開発することができますし、apiにシンプルかつパワフルなフレームワークを与えるのと同時に、Angular CLIの力を用いることができます。
5.終わりに
今回、Rails5のバックエンドとAngular8のフロントエンドで、同じディレクトリに存在し、それぞれの力を最大限に活用するアプリケーションを作りました。このチュートリアルがあなたにとって役に立てれば幸いです。
参考記事
- 投稿日:2019-09-29T16:37:40+09:00
洋書多読コミュニティサイト「多読マラソン」をリリースしました!
はじめに
以前、こういうWebサイトをリリースしました。(リンクは外しています)
多読マラソンサイト名は、多読マラソンです。ネーミングセンスとかは突っ込まないでいただけると嬉しいですね!
制作経緯
僕は大学受験時代に洋書を読むことにハマり、そこから受験勉強そっちのけで英語の本を読みまくってきました。いわゆる多読というやつですね。洋書をとにかくたくさん読むと。
一時期、TOEICの勉強をやっていたこともあるんですが、あまりにつまらなすぎて1ヶ月立たずに挫折してしまいました。そんな僕ですが、この洋書多読にはハマりました。これがとにかく楽しい。
ちなみに、洋書多読にハマったおかげで、ぶっつけ本番で受けたTOEICでも900点突破できたので、本当、多読のおかげで人生変わったと言っても過言ではないです。僕の場合は。
で、この多読界隈では、読んだ洋書の量を「語数」で表すんですね。100万語突破とか、500万語突破とか。200〜300ページの洋書がだいたい50000語なので、100万語突破だと、普通の洋書を20冊読んだ計算になります。
多読実践者の間では、100万語読むことがベンチマークとされていまして、皆この数字を目標にがんばります。そして、この語数を記録するために、いろいろなサービスがあるわけなのですが、僕も例に漏れず、あるwebサイトを使用していました。
ところがこのサイト、ところどころ使いづらいんですね。あまりメンテナンスもされてなさそうで、正直なんだかなーという思いを感じていました。これが受験生の頃ですね。
それから数年が経ち、プログラミングを初めて1年半にもなりまして、あるときこう思ったわけなんですね。「ぶっちゃけ今の俺なら、もっと良いサイト作れるんじゃねーの?」と。
制作風景
制作期間は約3週間。2019年9月10日から制作を開始して、この記事を書いているのが9月29日。サイトの規模的に、10日ぐらいで完成させたかったんですが、インターンをしていたので思うように時間が取れなかったことと、サービスが完成に近づくにつれて、ここ直したい!、という箇所が増えて、3歩進んで3歩下がる的な状況に陥ってしまい、なかなか遠かったです。
ですが!
ひとまずMVP的なものにはなったので、一旦リリースしてみようか、って感じです。仕様
Amazon Product Advertising API
を使ったサービスとなっています。これがなきゃ成立しません。使用技術
- Amazon Product Advertising API
- Ruby on Rails
- HTML(Slim), CSS(Sass)
- DB
- Postgresql
- CircleCI
- Docker
- Heroku(独自ドメイン)
感想
ちょっとRailsに飽きてきた感がありましたw
中小規模のサービスをちゃちゃっと開発するのにはRails最強だと思うんですが、あまりに便利すぎて、なんか堕落してるような気分になるのが玉に瑕ですかねw
参考文献・サイト・ライブラリ
- 参考文献・サイト
- 投稿日:2019-09-29T11:15:00+09:00
[Rails]stringからenumに変更する
stringで保存されたデータをenumに変更します。
enumの設定
ゴールとなるenumの設定。
Reservation.rbclass Reservation < ApplicationRecord enum status: { applied: 0, accepted: 1, cancelled: 2, completed: 3 } endmigrationの設定
元データは、
Reservation.status
にstringで'applied','accepted','cancelled','completed'
が入っています。以下のようなマイグレーションで、カラム型をStringからIntegerに変更し、データも移行するところまで一括で行います。
class ReservationStatusConvertToEnum < ActiveRecord::Migration[6.0] # データベース操作の際にコールバックを呼ばないよう、テーブルを使うだけのTmpモデルを作る class TmpReservation < ApplicationRecord self.table_name = :reservations end def change # 元データのカラム名を変更 change_table :reservations do |t| t.rename :status, :old_status end reversible do |dir| dir.up do # 新しくenum用のintegerカラムを追加 add_column :reservations, :status, :integer, null: false, default: 0 # テーブル情報をリセットする TmpReservation.reset_column_information # stringで持っていた名前をenumと同じ順でarrayにし、旧データをインデックス番号で取る TmpReservation.find_each do |tr| tr.status = %w(applied accepted cancelled completed).index(tr.old_status) tr.save! end # 旧データを捨てる remove_column :reservations, :old_status end # upの逆 dir.down do add_column :reservations, :old_status, :string TmpReservation.reset_column_information TmpReservation.find_each do |tr| r = Reservation.find(tr.id) tr.old_status = r.status tr.save! end remove_column :reservations, :status end end end end参考: Rails Migration, converting from string to enum | stack overflow
Scopeの修正
条件をSQL形式で書いてしまっているところは、enumに変換後に期待するデータが取ってこれなくなりますので、修正します。
scope :applied_reservations, -> { where("status = 'applied'") } # NG scope :applied_reservations, -> { where(status: 'applied') } # OK
- 投稿日:2019-09-29T10:38:18+09:00
Ruby初心者がSinatraでじゃんけんしてみた
この記事の目的
パソコンで食っていきたいと思い立ってRubyの勉強をしている。いきなりRailsやるなっていうのは腐るほど言われてるのでSinatraから始めている。
ドットインストールとか入門Sinatra
軽く勉強した上で自分で何か作ってみたいと思い、じゃんけんしてみた。上述の入門Sinatraでもじゃんけんアプリはやっていたのだが、GETメソッドでurlで出す手を指定して、paramsでクエリ文字列を取得して〜〜という感じだった。
けど、たかがじゃんけんするのにurlどうこうとかはめんどくさいなと思い、ボタンを押したら結果が出るような形にしたかった。コード
ディレクトの構造はこんな感じ
.
├── janken.rb
└── views/
├── index.erb
├── layout.erb
└── result.erblayout.erbは大したアレじゃないので省略する。
index.erb
<h2>何を出しますか?</h2> <form action="/result" method="post"> <button type="submit" name="throw" value="rock">ぐー</button> <button type="submit" name="throw" value="sissors">ちょき</button> <button type="submit" name="throw" value="paper">ぱー</button> </form>出す手のbuttonをクリックすると、result.erbに何を出したのかがPOSTされるようにした
janken.rb
require 'sinatra' require 'sinatra/reloader' get '/' do @title = "janken" erb :index end post '/result' do @title = "result" @throw = params["throw"].to_sym @defeat ={rock: :scissors,scissors: :paper, paper: :rock} @computer_throw = @defeat.keys.sample erb :result end
- index.erbからPOSTされたvalue属性を受け取ってプレイヤーの手を決める
- 勝敗を決める相関図をハッシュで作成
- 上で作ったハッシュのきーをランダムで抽出することで、コンピュータが出す手を決める
- result.erbを表示する
result.erb
<h2> <% if @throw == @computer_throw %> Tied <% elsif @throw == @defeat[@computer_throw] %> You won <% else %> You lost <% end %> </h2> You : <%= @throw %> <br> Computer: <%= @computer_throw %> <br> <a href="/">again!</a>勝利条件は以下のようにした。
@defeat
から@computer_throw
(相手の出す手)で抽出した値が、@throw
(自分が出した手)と同じならば勝ち終わりに
index.erbからポストされた値を取得するのに手間取った。
出来上がってしまった今だと、何をそんなに手間取っていたのかもわからないのだが、@throw
が全然うまく行かなかった。
ターミナルのロゴを見たらなぜ想定通りの動きをしていないのかはヒントが落ちていたし、ログ見るって大事なんだなと。
結局なにがダメって、HTTPとかの知識が皆無でログも何が起きてるのかわからなかったのが問題。
Webを支える技術を読んでぼんやりとでも知識をつけられたおかげ化。知識が0と1じゃ大違いだ、
何はともあれ、自分で考えて作ったものが、想定通りに動かせた。嬉しい。参考
- 投稿日:2019-09-29T09:57:56+09:00
最新の Ruby を Mac にインストールする手順
Ruby のバージョン管理には「 rbenv 」を使うのが定番だと思いますが、
基本的に、最新版しか必要ないのであれば、Homebrew でインストールして、管理するのもアリかもしれません。
$ ruby -v ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]それなら「 最新の Git を Mac にインストールする手順 」と同じで、以下のようなコマンドを実行するだけで済みます。
$ brew install ruby $ echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.bash_profile $ source ~/.bash_profile普段から、複数のバージョンを使い分けるというわけでもないのであれば、特に問題もないのではないでしょうか。
$ ruby -v ruby 2.6.4p104 (2019-08-28 revision 67798) [x86_64-darwin18]
- 投稿日:2019-09-29T09:33:50+09:00
rails 条件付きでバリデーションを効かせる
こういうときはバリデーション効かせないで欲しい
ってときの対応。
通常のバリデーションは以下の感じ
class User < ApplicationRecord validates :name, presence: true validates :email, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false} validates :password, presence: true, confirmation: true has_many :questionsどういう状況で使う?
例えばSNSログインの場合、twitterでやろうとするとemailの値が取得できない(2019/08/10現在)のでバリデーションが効くとエラーになる。。。
⇨「SNSログインの際に取得するuidカラムに値が入っていないときは通常のログインとみなしてバリデーションを効かせたい。」時
if
やunless
で条件を指定して、目的の項目へ追加する。class User < ApplicationRecord validates :name, presence: true validates :email, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false}, unless: :uid? #email取れないからこんな感じ validates :password, length: {minimum: 6}, presence: true, confirmation: true, unless: :uid? #パスワードもSNSログインと別管理ならこんな感じ has_many :questionscallbackに対しても指定可能
以下はバリデーション用のヘルパーを定義してそのヘルパーの中で
unless
を使い処理をするかしないかを判定している。class User < ApplicationRecord validates :name, presence: true, length: {maximum: 50} #以下でヘルパーを呼び出す before_save :email_downcase VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: {maximum: 255}, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false}, unless: :uid? #こんな感じ validates :password, length: {minimum: 6}, presence: true, confirmation: true, unless: :uid? has_many :questions #email用にヘルパーを定義 def email_downcase unless uid? self.email.downcase! end endとりあえず、こんなけ。
- 投稿日:2019-09-29T06:40:59+09:00
[Ruby]Google News RSSからニュースを取得してJSONで返す
はじめに
趣味で作っているWebアプリケーションでニュースAPIを叩きたくて調べてみました。
日本語のニュースを取得できるAPIは、newsAPI(日本語版)などがありますが、取得方法everything
に対応しておらず、top-headlines
だと20件のみしかとってきてくれないようです。取得方法
everything
はエラーになります。$ curl 'https://newsapi.org/v2/everything?country=jp&apiKey={YOUR_API_KEY}' {"status":"error","code":"parameterInvalid","message":"The country param is not currently supported on the /everything endpoint."}一方、
top-headlines
は取れますが、20件までしか取得できないです。$ curl 'https://newsapi.org/v2/top-headlines?country=jp&apiKey={YOUR_API_KEY}' {"status":"ok","totalResults":30,"articles":[{"source":{"id":"engadget","name":"Engadget"},"author":"Ittousai","title":"速報:マイクラアースは10月配信開始、アーリーアクセスの事前登録を受付 #MinecraftEarth - Engadget 日本版","description":"マイクロソフトが基本無料のスマホAR版マインクラフト Minecraft Earthの...(略)なので、category指定とかもできますが、どのカテゴリも2, 3件しかない状態なので、使いづらいなと思っていました。
大量のニュースを取得できて、かつカテゴリ指定や検索ができるAPIがないかなと思っていたのですが、なさそうなので、タイトルの通りGoogle News RSSからとってきてJSONで返すAPIを自作すればいいのかなと思いました。
コード
試しで書いてみたら取得することができました。
クエリストリングでカテゴリや検索ワードを指定できるみたいです。
ここでは一旦カテゴリだけ指定してみます。news_to_json.rb# frozen_string_literal: true require 'rss' require 'active_support' require 'active_support/core_ext' category = ARGV[0] base_url = 'https://news.google.com/rss/search' query_string = "?hl=ja&q=#{category}&hl=ja&gl=JP&ceid=JP:ja" rss = RSS::Parser.parse(base_url + query_string) news_hash = Hash.from_xml(rss.to_xml) news_json = news_hash.to_json puts news_json$ ruby news_to_json.rb health {"rss":{"version":"2.0","xmlns:content":"http://purl.org/rss/1.0/modules/content/","xmlns:dc":"http://purl.org/dc/elements/1.1/","xmlns:itunes":"http://www.itunes.com/dtds/podcast-1.0.dtd","xmlns:trackback":"http://madskills.com/public/xml/rss/mod...(略)おわりに
こんな感じのAPI自作して、フロントエンドで呼び出せばWebで便利に使えるのかなと思いました。
ただ、Google News RSSはニュースの画像を返してくれないので、画像が欲しい場合はスクレイピングして、OGP画像のリンクを取得する。OGPがなければフロントエンドでデフォルトの画像を表示する、といった実装が必要そうです。スクレイピングは、【rails】urlからサイトの情報を引き出す。【スクレイピング】を参考に、
<meta property="og:image">
をとってくればできそうです。
- 投稿日:2019-09-29T01:43:11+09:00
Bundlerのdefault 1.17.2の時にbundle execが機能しない時の対処法
bundle exec rails g ~
が全く機能しなかったので、調査した件。
今回の実行環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G95
今回起きたエラー内容は以下の通りです。
$ bundle exec rails g controller StaticPages home help about /Users/iori_jp/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/runtime.rb:319:in `check_for_activated_spec!': You have already activated bundler 1.17.2, but your Gemfile requires bundler 2.0.2. Since bundler is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports bundler as a default gem. (Gem::LoadError)適用されている
bundler gem
のバージョンが1.17.2
なので、2.0.2
に変更してくださいとのことでした。
上記の参考ページ曰く、bundlerバージョンが1.17.2
だと色々面倒らしく、1.17.3
に変更した方が良いとのこと。
途中、試行錯誤で試したものが影響を持っている可能性があるため、メモ書き程度で参考にすることをオススメします...
まず、
Gemfile.lock
のBUNDLED WITH
を確認します。$ cat Gemfile.lock | tail RUBY VERSION ruby 2.6.1p33 BUNDLED WITH 1.17.2
Gemfile.lock
は、bundle install
した時点で作成されます。
(ここでバージョンが1.17.3
であれば、問題は別にありそうです。)
この後の作業として、bundlerのdefaultバージョンを1.17.3
、
実行バージョン2.0.2
をインストールしてから、bundle install
します。次にbundlerのバーションを確認します。
$ gem list bundler *** LOCAL GEMS *** bundler (2.0.2, default: 1.17.2) $ bundle -v Bundler version 1.17.2
gem update --system
を実施して、defaultのbundlerバージョンを1.17.3に変更します。$ gem update --systembundlerバージョン 2.0.2 をインストールします。
ここでgem install bundler -v 1.17.3
のように指定することも可能
今回は最新版である2.0.2
を使用するため、指定はしません。$ gem install bundler Successfully installed bundler-2.0.2 Parsing documentation for bundler-2.0.2 Done installing documentation for bundler after 1 seconds 1 gem installed次に
Gemfile.lock
を削除します。$ rm Gemfile.lockやっと、
bundle install
。
ここでpathをオプションに入れることで、bundlerのバージョンをglobal
でなく、
local
で持つことができます。$ bundle install --path=vendor/bundle最後に、catで
BUNDLED WITH
のバージョンを確認して終わりです。$ cat Gemfile.lock | tail RUBY VERSION ruby 2.6.1p33 BUNDLED WITH 2.0.2これで無事、
bundle exec rails g controller ~~
できるようになりました。
- 投稿日:2019-09-29T01:43:11+09:00
Bundler 2.X系でbundle execがdefaultバージョンを参照してしまう時の対処法
bundle exec rails g ~
が全く機能しなかったので、調査した件。
今回の実行環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G95
今回起きたエラー内容は以下の通りです。
$ bundle exec rails g controller StaticPages home help about /Users/iori_jp/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/runtime.rb:319:in `check_for_activated_spec!': You have already activated bundler 1.17.2, but your Gemfile requires bundler 2.0.2. Since bundler is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports bundler as a default gem. (Gem::LoadError)適用されている
bundler gem
のバージョンが1.17.2
なので、2.0.2
に変更してくださいとのことでした。
上記の参考ページ曰く、bundlerバージョンが1.17.2
だと色々面倒らしく、1.17.3
に変更した方が良いとのこと。
途中、試行錯誤で試したものが影響を持っている可能性があるため、メモ書き程度で参考にすることをオススメします...
まず、
Gemfile.lock
のBUNDLED WITH
を確認します。$ cat Gemfile.lock | tail RUBY VERSION ruby 2.6.1p33 BUNDLED WITH 1.17.2
Gemfile.lock
は、bundle install
した時点で作成されます。
(ここでバージョンが1.17.3
であれば、問題は別にありそうです。)
この後の作業として、bundlerのdefaultバージョンを1.17.3
、
実行バージョン2.0.2
をインストールしてから、bundle install
します。次にbundlerのバーションを確認します。
$ gem list bundler *** LOCAL GEMS *** bundler (2.0.2, default: 1.17.2) $ bundle -v Bundler version 1.17.2
gem update --system
を実施して、defaultのbundlerバージョンを1.17.3に変更します。$ gem update --systembundlerバージョン 2.0.2 をインストールします。
ここでgem install bundler -v 1.17.3
のように指定することも可能
今回は最新版である2.0.2
を使用するため、指定はしません。$ gem install bundler Successfully installed bundler-2.0.2 Parsing documentation for bundler-2.0.2 Done installing documentation for bundler after 1 seconds 1 gem installed次に
Gemfile.lock
を削除します。$ rm Gemfile.lockやっと、
bundle install
。
ここでpathをオプションに入れることで、bundlerのバージョンをglobal
でなく、
local
で持つことができます。$ bundle install --path=vendor/bundle最後に、catで
BUNDLED WITH
のバージョンを確認して終わりです。$ cat Gemfile.lock | tail RUBY VERSION ruby 2.6.1p33 BUNDLED WITH 2.0.2これで無事、
bundle exec rails g controller ~~
できるようになりました。