大学生がプログラマーを目指すはなし

ruby, python, AIの話が多いです

cssだけでアコーディオン表示

HTML

<div class="hidden_box">
    <input type="checkbox" id="label1" />
    <label for="label1">クリック</label>
    <div class="hidden_show">
        <!--非表示ここから-->
        <p>こんにちは</p>
        <!--ここまで-->
    </div>
</div>

CSS

/*全体*/
.hidden_box {
margin: 2em 0;
padding: 0;
}

/*ボタン装飾*/
.hidden_box label {
padding: 15px;
font-weight: bold;
background: #efefef;
border-radius: 5px;
cursor :pointer;
transition: .5s;
}

/*アイコンを表示*/
.hidden_box label:before {
display: inline-block;
content: '\f078';
font-family: 'FontAwesome';
padding-right: 5px;
transition: 0.2s;
}

/*ボタンホバー時*/
.hidden_box label:hover {
background: silver;
}

/*アイコンを切り替え*/
.hidden_box input:checked + label:before {
content: '\f00d';
-ms-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
color: #668ad8;
}

/*チェックは見えなくする*/
.hidden_box input {
display: none;
}

/*中身を非表示にしておく*/
.hidden_box .hidden_show {
height: 0;
padding: 0;
overflow: hidden;
opacity: 0;
transition: 0.8s;
}

/*クリックで中身表示*/
.hidden_box input:checked + label + .hidden_show {
padding: 10px 0;
height: auto;
opacity: 1;
}

 

上記のコードのみで、

ボタンクリックで姉妹要素がスルスルっと出てきて、同時にボタンのデザインも⬇︎から✖︎に変わる。

 

参考サイトはCSSだけでアコーディオンを作る方法(レスポンシブ&矢印付)です。

 

rubyのversionをrbenvで切り替える

まずrbenvを最新にする。

$ brew update
$ brew upgrade rbenv ruby-build

 

その後、現在ダウンロードできるversionを確認する。

$ rbenv install -l

 

新しいバージョンのインストールをする。

$ rbenv install 任意のバージョン

 

インストールできたら、切り替える。

$ rbenv local 任意のバージョン
$ rbenv global 任意のバージョン

 

確認する。

$ ruby -v

 

 これでバージョンが表示されれば完了。

 

 

rails5, puma, nginx, debianを使ってデプロイ!最初から最後まで!

何度やっても忘れるので今度こそ最初から最後まで備忘録を書きます。

デプロイまとめ

ローカルで本番環境に流す

1-1. 今回のアプリケーションに必要になる本番環境でのDBと、ユーザー名とパスワードを設定する。

mysql> CREATE USER 'railsuser'@'localhost' IDENTIFIED BY 'mypassword';

mysql> GRANT ALL PRIVILEGES ON *.* TO 'railsuser'@'localhost';

 以上でユーザ作成は完了です。

ちなみに上記の場合は全てのデータベースとテーブルに対する全権限をrailsuserに付与していますが、特定のデータベースや処理を限定して権限を付与することも可能です。

1-2. データベース設定ファイル修正

今回は本番環境のMySQLRails用のMySQLユーザとしてユーザ名がrailsuser、パスワードがmypasswordであるユーザを作成したのでこの情報をconfig/database.ymlに記述します。

1-3. 開発, テスト, 本番環境のデータベース、テーブル、seed-fuを作成

続いて開発, テスト, 本番環境のデータベース、テーブルを作成します。

$ rake db:create #開発, テストのデータベース作成

$ rake db:create RAILS_ENV=production password=mypassword #本番環境のデータベース作成

上記コマンドを実行により、

  • development環境用にRails_developmentという名前のデータベース
  • test環境用にRails_testという名前のデータベース
  • production環境用にRails_productionという名前のデータベース

がそれぞれ作成されます。

ここでproduction環境のコマンド実行時に1-1で設定したmypasswordをオプションとして付け加えること。

そうしないとエラーが発生する。

$ rake db:migrate

$ rake db:migrate RAILS_ENV=production password=mypassword

$ rake db:seed_fu RAILS_ENV=production password=mypassword

上記コマンドでマイグレイト, seedファイルの挿入。

1-4. assetファイルのコンパイル

コンソールで以下のコマンドを叩いてapp/assets以下のファイルをコンパイルします。

$ RAILS_ENV=production rake assets:precompile assets:clean

assets:cleanも一緒に入れておくと古いファイルも消しておいてくれて便利。

そして、動的にコンパイルできるようにセッティングします。

Rails.root/config/environments/production.rbを少し編集します。

config.assets.compile = true

上記に編集します。

こうすることにより、

サーバがリクエストを受け取った際、コンパイル済みのファイルが見つからない場合にその場でコンパイルを行う設定が可能です。
これならリポジトリへの登録は不要です。しかし動的コンパイルなので初回リクエスト時にはレスポンスが犠牲になります。
それが嫌なら、capistranoを使いましょう。

 

ここまでできたら確認しましょう。

$ rails server -e production

これで無事に繋がれば第一段階は完了です。

2. nginxpumaでデプロイする。

2-1. nginxの設定

upstream rails_name {

  server unix:/Users/user-name/workspace/projects/rails_name/tmp/sockets/puma.sock;

}

server {

    listen  80;

    server_name  localhost;

    root  /Users/user-name/workspace/projects/rails_name

      location / {

         proxy_set_header Host $host;

         proxy_pass http://rails_name;

      }

      error_page   500 502 503 504  /50x.html;

      location = /50x.html {

         root   html;

      }

}

2-2. pumaの設定

rails-root/config/puma.rb このファイルに

bind "unix://#{Rails.root}/tmp/sockets/puma.sock"

これを足すだけだ

ここまでできたら確認しましょう。

$ sudo nginx

$ rails server -e production

これでnginxで設定したポートで開ければここまでは完了です。

. debianにデータを移す

3-1. railsアプリをdebianにコピーします。

$ scp -i ~/.ssh/client_rsa -r -P ポート番号 /Users/user-name/workspace/projects/rails_name リモートユーザー名@ipアドレス:/home/リモートユーザー名/workspace

これでデビアンにローカルファイルが全てコピーされました。

4. 本番環境の更新をする。

4-1. gitでバージョンを合わせる。

$ git pull origin master

4-2. databaseを作成して、シードファイルを流す
$ rake db:drop db:create db:migrate db:seed_fu
4-3. プリコンパイル
RAILS_ENV=production rake assets:precompile assets:clean
4-4. サーバー起動
$ rails server -e

 これで完成!

ドメインを確認してください。

 

 

 

 

 

スはスペックのス(model)をRspec3, Rails5でやってみた。

こちらの「スはスペックのス」なのですが、とても古い記事でして2018年にrubyの勉強をし始めた僕にとってはversionの観点から少し分かりづらい内容でした。さらにネットの情報も様々なversionで書かれた記事が混在しており、さらにやりにくかったです。   

そんな中、頑張ってとりあえず全部やったのでメモとしてブログに上げます。

スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)

スはスペックのス(model編)

環境

  • Rspec → version 3.8
  • ruby → version 2.5.1
  • Rails → version 5.2.0

0. 準備

インストール

RSpec のリリースバージョンは RubyGems で提供されています。

$ gem install rspec

RSpec が無事にインストールされて、実行できることを確認しましょう。

$ spec -v

1. 簡単な配列のテスト

まず最初にRailsを使ってテストをする前に簡単な配列のテストをして、雰囲気を感じましょう。

適当なディレクトリに array_spec.rb という名前のファイルを用意します。 RSpec によるテストコードのファイル名は接尾辞を _spec とする のが一般的です。なお、RSpecで振舞を記述したファイルのことをスペックファイルと呼びます。

スペックファイルには、次のようにスペックを書きます。

array_spec.rb

describe Array, "when empty" do #ここに何を対象としてテストをするのか書く。
  before do #テスト前準備
    @empty_array = []
  end

  it "should be empty" do #ここにテストの内容を書く。
    expect(@empty_array).to be_empty
  end

  it "should size 0" do #ここにテストの内容を書く。 
    expect(@empty_array.size).to eq 0
  end

  after do #テスト後の後片付け
    @empty_array = nil
  end
end

 こちらのテストを読んでいくと、

まず最初にテストの内容です。

describe Array, "when empty" do #ここに何を対象としてテストをするのか書く。

これは"配列が空のとき"と読めます。

次に、 テスト内容です。

it "should be empty" do #ここにテストの内容を書く。
  @empty_array.should be_empty
end

これの"it"の部分から読んでみると、"それは空であるべきだ"と読めます。

次もテスト内容です。

it "should size 0" do #ここにテストの内容を書く。 
  expect(@empty_array.size).to eq 0
end

 これの"it"の部分から読んでみると、"それは0サイズであるべきだ"と読めます。

まとめると、

 - 配列が空のとき、 describe 〜

 - それは空なのか、 it "should be empty" do

 - 配列の数は0なのか、 it "should size 0" do

これらをテストしているということになります。

RSpec を実行してみます。

$ rspec
..
2 examples, 0 failures

 examplesがテストの数で、failuresがそのうち失敗した数です。つまり、全てのテストは成功したということです。 

2. Railsでmodelテストの作成

railsアプリケーションを作ります。

$ rails new rspec_sample_model
 ...(中略)
 $ cd rspec_sample_model

 Blog modelを作成します。

$ rails g model Blog name:string
 exists  ...
 create  ...
 ...
...

 たくさんファイルができます。

マイグレーションファイルを編集する。

ブログに名前が無いと困るので必須項目にしておきましょう。blogs テーブルの name 属性を null 不可にします。

db/migrate/001_create_blogs.rb

class CreateBlogs < ActiveRecord::Migration[5.2]

  def change

    create_table :blogs do |t|

      t.string :name, :null => false # Not null

 

      t.timestamps

    end

  end

end

DBを作成する。

$ bundle exec rake db:migrate

フィクスチャを編集する。

少し先回りになりますが、こちらを編集しておきます。

kubota:
  id: 1
  name: rspec_practice
kobayashi:
  id: 2
  name: css_practice

3. Blogのバリデーションのスペックを定義する。

spec/models/blog_spec.rb

require 'rails_helper'
describe Blog do before(:each) do @blog = Blog.new end

  it 'is not be valid without name' do
    expect(@blog).not_to be_valid
  end
end 

ここで実行すると失敗するはずです。なぜならまだ Blogクラスにname属性を検証するような実装をしていないからです。

一応、実行してみます。

rspec spec/models/blog_spec.rb

 

F

 

Failures:

 

  1) Blog is not be valid without name

     Failure/Error: expect(@blog).not_to be_valid

       expected #<Blog id: nil, name: nil, created_at: nil, updated_at: nil> not to be valid

     # ./spec/models/blog_spec.rb:11:in `block (2 levels) in <top (required)>'

 

Finished in 0.05637 seconds (files took 1.71 seconds to load)

1 examples, 1 failure 

予想通り失敗しました。

Blogクラスに期待される振舞を実装する。

name 属性の存在を検証するように Blog クラスを実装します。

app/models/blog.rb

class Blog < ActiveRecord::Base

  validates_presence_of :name

end

blog.rb の修正を保存して、再度 rspec を実行します。DBに変更は無いので、そのまま rspecコマンドを叩きます。

rspec spec/models/blog_spec.rb

.

 

Finished in 0.05556 seconds (files took 1.71 seconds to load)

3 examples, 0 failures

予想通り成功しました。 

3. Entryモデルの作成。

次は Blog に投稿された記事を表現する Entry モデルを作成します。 ジェネレータの利用からフィクスチャの設定までは Blog クラスの場合と同様です。

Entryモデルを生成する。

Entry の属性にはタイトル、本文、投稿日を用意します。Blog と関連づけるため の外部参照キーや、管理用の属性として、タイムスタンプも定義します。

$ rails g model entry title:string body:text posted_at:date created_at:timestamp updated_at:timestamp blog_id:integer

exists app/models/

exists spec/models/

create spec/fixtures/

create app/models/entry.rb

create spec/fixtures/entries.yml

create spec/models/entry_spec.rb

exists db/migrate

create db/migrate/002_create_entries.rb

マイグレーションファイルを編集する。

 必須属性を null 不可にします。

db/migrate/002_create_entries.rb

class CreateEntries < ActiveRecord::Migration[5.2]

  def change

    create_table :entries do |t|

      t.string :title, :null => false

      t.text :body, :null => false

      t.timestamp :posted_at

      t.timestamp :created_at

      t.timestamp :updated_at

      t.integer :blog_id, :null => false

 

      t.timestamps

    end

  end

end

投稿日 (posted_at) を created_at や updated_at といった Rails が標準でサポート するタイムスタンプで代用せずに独立させて定義しています。

これは「Blog の記事の投稿日」として扱いたい日付が必ずしもデータベースレコードの作成・更新タイムスタンプと同じとは限らないためです。 

DBを移行する。

$ bundle exec rake db:migrate

development環境のデータベースを変更しましょう。

フィクスチャを編集する。

テスト用の投稿記事を用意しておきます。

spec/fixtures/entries.yml

$ bundle exec rake db:migrate

kubota_earliest:

   id: 1

  blog_id: 1

  title: "昨日は台風"

  body: "せっかくエンジニアの人とランチの約束があったのにダメになった。"

  posted_at: 2001-07-06

kubota_latest:

  id: 2

  blog_id: 1

  title: "最近はRspecにハマっている。"

  body: "なんだかかれこれ1週間くらいやっているなぁ。"

  posted_at: 2007-09-12

kobayashi:

  id: 3

  blog_id: 2

  title: "全然休みがない"

  body: "金もない。"

  posted_at: 2007-06-24

4. BlogとEntryを絡み合わせたspecを定義する。

では実装に入ります。今回作成するブログアプリケーションのモデルを確認しておきます。

両者の関連を確認しておくと:

  • Blog は複数の Entry を所有する (Blog has_many Entry)
  • Entry は特定の Blog に属する (Entry belongs_to Blog)

となります。この 2 つをスペックとして記述します。

せっかく Entry モデルを作成したので、まずは Entry 側の関連からスペックを定 義しましょう。

「Entryは特定のBlogに属すること」をスペックとして定義する。

 Entry から Blog を参照できるという期待をスペックとして記述します。

spec/models/entry_spec.rb

require 'rails_helper' 

describe Entry do

  fixtures :entries, :blogs

  before(:each) do

    @entry = entries(:kubota_earliest)

  end

 

  it 'belongs to a specific blog.' do

    expect(@entry.blog).to eq blogs(:kubota)

  end

end

RSpec on Rails では振舞を記述する際に、Rails 標準のテスティング環境と同様 に fixtures メソッドを使用できます。Rspec on Rails の fixtures と Rails 標準の fixtures との違いは、Rspec on Rails では「fixture_path」が 「$RAILS_APP/spec/fixtures」に設定されていることです。

spec を実行する前に、rake の db:test:prepare タスクを実行します。 entries テーブルを作成した際に、development 環境のデータベーススキーマは 変更しましたが、この変更をまだ test 環境のデータベースには反映していないからです。

$ bundle exec rake db:test:prepare

 ここでテストを実行すると失敗するはずです。なぜならまだEntry.blogを定義していません。

一応実行してみます。

$ rspec spec/models/entry_spec.rb

F

 

Failures:

 

  1) Entry belongs to a specific blog.

     Failure/Error: expect(@entry.blog).to eq blogs(:kakutani)

     

     NoMethodError:

       undefined method `blog' for #<Entry:0x00007f868f774828>

       Did you mean?  blog_id

     # ./spec/models/entry_spec.rb:18:in `block (2 levels) in <top (required)>'

 

Finished in 0.03105 seconds (files took 1.71 seconds to load)

1 example, 1 failure

予想通り失敗しました。 

Entryにbelongs_toを実装する。

振舞の期待通りに Entry を実装しましょう。

app/models/entry.rb 

class Entry < ApplicationRecord

  belongs_to :blog

end

spec を実行します。 

$ rspec spec/models/entry_spec.rb

.

 

Finished in 0.04034 seconds (files took 1.7 seconds to load)

1 example, 0 failures

予想通り成功しました。

とりあえずここまで。 

Rubyでgemを作って公開するまで

0. 準備

まずは準備のためにgemのアップデートとbundlerのアップデートを行います。

# gem自信のアップデート
gem update --system

# bundler未インストールの場合はインストール
gem install bundler

# bundlerインストール済の場合はアップデート
gem update bundler

 

1. ヒナ形の作成

今回はtest_gemという名前のGemを制作していきます。

※実際にRubyGemsで公開する場合はまだ存在していないGem名にしないといけません。

# test_gemのひな形を作成(Rspec付き)
bundle gem test_gem --exe -t

2. 作成されたファイルの確認

今回作成されたファイルの簡単な説明。

bundle gem test_gem -t
  create  test_gem/Gemfile
  create  test_gem/Rakefile
  create  test_gem/LICENSE.txt
  create  test_gem/README.md => このgemの説明や使い方を記述
  create  test_gem/.gitignore
  create  test_gem/test_gem.gemspec => このgemの説明や依存関係などを記述
  create  test_gem/lib/test_gem.rb => プログラムを記述
  create  test_gem/lib/test_gem/version.rb => このgemのバージョン情報を記述
  create  test_gem/.rspec
  create  test_gem/spec/spec_helper.rb
  create  test_gem/spec/test_gem_spec.rb
  create  test_gem/.travis.yml => travisを使う際の設定を記述
    create   test_gem/exe/test_gem => 実行コマンドを追加する際に記述

3. test_gem.gemspecの修正

test_gem.gemspecの中身は以下のようにになっています。

# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'test_gem/version'

Gem::Specification.new do |spec|
spec.name = 'test_gem'
spec.version = TestGem::VERSION
spec.authors = ['kubota-ryotaro']
spec.email = ['kubota@mail.com']
spec.summary = %q{TODO: Write a gem summary}
spec.description = %q{TODO: Write a gem description}
spec.homepage = 'http://namae.github.io'

spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']

spec.add_development_dependency 'bundler', '~> 1.7'
spec.add_development_dependency 'rake', '~> 10.0'
spec.add_development_dependency 'rspec'
end

最低限修正が必要な部分を抜き出すと次のようになります。

# このgemの説明をダブルクオートで囲って書き直す
spec.summary       = "Make gem for summary."
spec.description   = "Make gem for description."

# このgemのHomepageを書く(GitHubのURLを入れてください) spec.homepage = "https://github.com/kubota-ryotaro/"
# 依存するgemが存在する場合のみ、次のように指定 spec.add_dependency 'xxxx', '~>x.x' # 開発時だけに必要な依存gemが存在する場合のみ、次のように指定 spec.add_development_dependency 'yyyy', '~>y.y'

4. Gemの実装

今回はテスト的にHello World!と出力するようにします。lib/test_gem.rbを開いて次のように変更します。

require 'test_gem/version'

module TestGem
def self.greet
'Hello World!'
end
end

5. 実行してみよう

では先ほど作成したgemを実行してみます

# gem のインストール
bundle install

# rubyの対話型インタプリタを起動
bundle exec irb [2.1.4]
irb(main):001:0> require 'test_gem'
=> true

irb(main):002:0> TestGem.greet
Hello World!

ということで無事実行できました!

6. RSpecを書こう

先ほどのTestGem.greetのテストをRSepcで書いていきます。spec/test_gem_spec.rbを次のように書き換えます。

require 'spec_helper'

describe TestGem do
it 'has a version number' do
expect(TestGem::VERSION).not_to be nil
end

describe '#greet' do
it 'returns "Hello World!"' do
expect(TestGem.greet).to eq('Hello World!')
end
end
end

7. 実行コマンドを追加

コンソール上でtest_gemというコマンドを使うとgemの内容を実行できるようにしたいので、exe/test_gemに次を書いていきます。

#!/usr/bin/env ruby

require 'test_gem'

puts TestGem.greet

8. Gemをパッケージ化する。

次にGemをパッケージ化します。コマンドとしては、gem build test.gemspecです。

gem build test_gem.gemspec
=> Successfully built RubyGem
=> Name: test_gem
=> Version: 0.0.1
=> File: test_gem-0.0.1.gem
gem install test_gem
=> Successfully installed test_gem-0.0.1
=> 1 gem installed
test_gem
=> "Hello World!"

9. 公開

GitHubと連携して管理するようなので以下のことは前提となります
GitHubアカウントを持っていること
GitHub用にSSHキーの設定を行う:GitHubへssh接続する

rubygems.orgのアカウントを取得
  作ったgemをリリースするまで
  1.「sign up」からアカウントを作成
  2. アカウント作成後、Edit profile(https://rubygems.org/profile/edit) に移動
  3. APIアクセス用の鍵を作成(以下のコマンドが用意されている)

curl -u your_name https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials

GitHub上のリモートリポジトリの設定
現在の作業用ディレクトリをリモートリポジトリに反映させます
Githubにgem名と同じ名前の新規リポジトリを作成する

git init$
git add -A
git commit -m "initial commit"
git remote add origin https://github.com/namae/test_gem.git

git push --set-upstream origin master

③リリース
あとは、releaseするだけ。

bundle exec rake release

 

これでできたはず!

 

 

rakeの基本

前提 rubyプログラムの中でC言語コンパイルして実行する。
1. まず最初に適当な作業ディレクトリを作成し、そこにRakefileを作る。

ここでお約束的な感じでRakefileの頭文字は大文字にしておく。

2. 今回使用するC言語プログラムを作っておく。

今回実行するプログラムはamidakuji.c

3. RakefileにCプログラムをビルドして実行するためのコードを書いていく。

f:id:rk0822ps4:20180707155733p:plain

 $ rake としたらdefaultでamidakujiが呼ばれるようにしておく。

4~6行目で実行プログラムで、8~10行目でビルドだ。

このように芋ずる式で書いていくと良い。

$ rake

で実行できる。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

8時間かけて作ったソースファイル達を rm ./* してしまった。

2日かけて計8時間ほどかけて作ったプログラムがありました。

それをGitHub上にpushしようと思ったんですよね。

だからまずローカル環境で、作業用ディレクトリからpush用のディレクトにコピーしました。そしてそこで一応中身を確認していたのですが一部気に入らない箇所があり、もう一度作業用ディレクトリの中で訂正しようと思ったんですよね。んで、そのファイル達を一旦消しました。

そしたら...

 

「あれ?」

作業用ディレクトリの中にさっきまで開いていたファイルがないお??

あれ、どこ行ったんだろ...

 

...

.......

「ない.......」

 

 

コマンドの履歴を確認してみたところ作業用ディレからpush用ディレにmvしていたようでした。

そして移動させたファイルを綺麗に削除したみたいでした。

 

解決策は基本的になく、もう一回作り直すしかないらしい...。゚(゚´ω`゚)゚。

 

 

その後誰かに聞いたら「そのためのgitじゃね? コミットしーや。」

とのことで解決しましたとさ。