20200809のRubyに関する記事は14件です。

[Rails]deviseを使ったウィザード形式での新規登録機能の実装

はじめに

フリマのコピーサイトを作る際に、構造をやや難しくしてしまったために苦労したので記録として残そうと思いました。もっと綺麗にかけるなどご指摘あればお願いします。

実装方法

開発環境

  • Ruby 2.5.1
  • Rails 5.0.7.2
  • devise

前提

DB設計

usersテーブル

Column Type Options
name string null: false, unique: true, index:true
email string null: false, unique: true, index:true
password string null: false

profilesテーブル

Column Type Options
first_name string null: false
family_name string null: false
first_name_kana string null: false
family_name_kana string null: false
introduction string null: true
year integer null: false
month integer null: false
day integer null: false

sending_destinations(住所)テーブル

Column Type Options
first_name string null :false
family_name string null: false
first_name_kana string null: false
family_name_kana string null: false
post_code string null: false
prefecture string null: false
city string null:false
house_number string null: false
building_name string -
phone_number string unique: true, null: true
user_id references null: false, foreign_key: true

コード

controllerの作成

  • devise管理下のusersコントローラーを作成する
ターミナル
$ rails g devise:controllers users
  • どのコントローラーを参照するのかルーティングを設定
routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { registrations: 'users/registrations' }
  root to: 'items#index'
end

モデルにアソシエーションを記述する

  • UserProfileSending_destinationそれぞれのモデルにアソシエーションを記述
    ※バリデーションは省略しています。
user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_one :profile
  accepts_nested_attributes_for :profile
  has_one :sending_destination
end
profile.rb
class Profile < ApplicationRecord
  belongs_to :user, optional: true
end
sending_destination.rb
class SendingDestination < ApplicationRecord
  belongs_to :user, optional: true
end

optional: trueは外部キーがnullであることを許可するオプションです。

newアクションと対応するビューを編集する(1ページ目)

  • users/registrations_controller.rbにnewアクションを記述
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  # 省略
  def new
    @user = User.new
    @user.build_profile
  end 
  # 省略
end

  • newアクションに対応するregistrations/new.html.hamlを編集
devise/registrations/new.haml.html
= form_for(@user, url: user_registration_path) do |f|
  = render "devise/shared/error_messages", resource: @user
  = f.text_field :nickname
  = f.email_field :email
  = f.password_field :password
  = f.password_field :password_confirmation
  = f.fields_for :profile do |p|
    = p.text_field :family_name
    = p.text_field :first_name
    = p.text_field :family_name_kana
    = p.text_field :first_name_kana
    = p.select :year
    = p.select :month
    = p.select :day
  = f.submit "次へ"

実際はdivやlabel、classの記載がありますが、簡素に書いています。
2つのモデルを扱うためにfields_forを利用しています。以下の記事を参考にしています。
【Rails】deviseのフォームで2つのモデルに同時に値を送る方法(例: UserモデルとProfileモデル)
【Rails】1つのform_forで複数モデルへデータ登録をする方法

createアクションを編集

  • 1ページ目で入力した情報のバリデーションチェック
  • 1ページで入力した情報をsessionに保持させる
  • 次の住所情報登録で使用するインスタンスを生成、当該ページへ遷移する 以上の3点がcreateアクションでやることになります。
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  # 省略
  def create
    @user = User.new(sign_up_params)
    @user.build_profile(sign_up_params[:profile_attributes])
    unless @user.valid?
      flash.now[:alert] = @user.errors.full_messages
      render :new and return
    end
    session["devise.regist_data"] = {user: @user.attributes}
    session["devise.regist_data"][:user]["password"] = params[:user][:password]
    session[:profile_attributes] = sign_up_params[:profile_attributes]
    @sending_destination = @user.build_sending_destination
    render :new_sending_destination
  end
  # 省略
  protected
  # 省略
end

valid?メソッドでパラメータがバリデーションに違反しないかどうかチェックします。
ページが遷移しても情報が消えることが無いように、クライアント側で保持をさせておく機能sessionを用いています。
sessionにハッシュオブジェクトの形で情報を保持させるために、attributesメソッドを用いてデータを整形しています。また、paramsの中にはパスワードの情報は含まれていますが、attributesメソッドでデータ整形をした際にパスワードの情報は含まれていません。そこで、パスワードを再度sessionに代入する必要があります。
build_sending_destinationで今回生成したインスタンス@userに紐づくsending_destinationモデルのインスタンスを生成します。
そして、住所情報を登録させるページを表示するnew_sending_destinationアクションのビューへrenderします。

new_sending_destinationアクションと対応するビューを編集する(2ページ目)

  • 住所登録をするページを表示するnew_sending_destinationアクションのルーティングの設定
  • 住所を登録するcreate_sending_destinationアクションのルーティングの設定
routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { registrations: 'users/registrations' }
  devise_scope :user do
    get 'sending_destinations', to: 'users/registrations#new_sending_destination'
    post 'sending_destinations', to: 'users/registrations#create_sending_destination'
  end

  root to: 'items#index'
end
  • 該当するビューファイルであるnew_sending_destination.html.hamlを作成
devise/registrations/new_sending_destination.html.haml
= form_for @sending_destination do |f|
  = render "devise/shared/error_messages", resource: @sending_destination
  = f.text_field :family_name
  = f.text_field :first_name
  = f.text_field :family_name_kana
  = f.text_field :first_name_kana
  = f.text_field :post_code
  = f.text_field :prefecture
  = f.text_field :city
  = f.text_field :house_number
  = f.text_field :building_name
  = f.number_field :phone_number
  = f.submit "登録する"  

create_sending_destinationアクションを編集する

  • 2ページ目で入力した住所情報のバリデーションチェック
  • バリデーションチェックが完了した情報と、sessionで保持していた情報とあわせ、ユーザー情報として保存する
  • sessionを削除する
  • ログインをする
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  # 省略
  def create_sending_destination
    @user = User.new(session["devise.regist_data"]["user"])
    @profile = @user.build_profile(session[:profile_attributes])
    @sending_destination = SendingDestination.new(sending_destination_params)
    unless @sending_destination.valid?
      flash.now[:alert] = @sending_destination.errors.full_messages
      render :new_sending_destination and return
    end
    @user.build_sending_destination(@sending_destination.attributes)
    @user.save
    @profile.save
    session["devise.regist_data"]["user"].clear
    session[:profile_attributes].clear
    sign_in(:user, @user)

    redirect_to root_path
  end

  protected

  def sending_destination_params
    params.require(:sending_destination).permit(
      :first_name,
      :family_name,
      :first_name_kana, 
      :family_name_kana, 
      :post_code, 
      :prefecture, :city, 
      :house_number, 
      :building_name, 
      :phone_number
    )
  end
end

@user@prfileそれぞれのインスタンスにsessionで保持した情報を代入しています。 
2ページ目の住所情報をvalid?でチェックします。 
build_sending_destinationを用いて送られてきたparamsを、保持していたsessionが含まれる@userに代入します。そしてsaveメソッドを用いてテーブルに保存します。
clearメソッドを用いてsessionを削除します。
sign_in(:user, @user)でログインし、redirect_to root_pathでトップページに遷移します。

おわりに

以上の方法で実装できます。1ページ目でfields_forを用いたことでsessionへの代入にかなり四苦八苦しましたが、おかげでしっかり仕組みなどを考えることができました。細かな説明はしていませんが、アウトプットも兼ねて記事にしてみたので少しでも参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

〇〇/〇〇.rb:1: Invalid char `\x08' in expression が出てきたけど、速攻で解決した。

本題

Rubyを再学習してる時に、謎のエラーが出てきた。
見たこともないエラーなので良く調べたが、一瞬で解決・・・

解決方法

該当の行をもう一度打ち直そう!!

内容

エラー分を翻訳してみると・・・
test/gate_test.rb:1: Invalid char \x08' in expression
→式に無効な文字 \ x08 'があります



といったところで勘付きました。また誤字しているんだなと。

そんでもって、該当行を書き直したところ・・・エラーは出なくなりました。

他の方のサイトを拝見させていただいたところ、不可視文字が原因のようです。
このエラーについては、速攻で打ち直すのが吉ですね。

参考にさせていただいたサイト

https://tattaka-s.hatenablog.com/entry/2019/07/06/153703
かな〜り詳しく書いていただいているので気になる方はご覧ください??‍♂️

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kinx Tips - 実行形式ファイルを作る

Kinx Tips - 実行形式ファイルを作る

はじめに

「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。今回は Tips です。

皆さん、実行ファイルを作る時どうしてますか? ...そう、普通は C や C++ で書いてコンパイルしますね。もっと簡単に作れるといいですね。

Kinx は独立した exe を作ることはサポートしていませんが、Kinx のワールドの中であれば exe にして単体実行コマンドのように見せかけて実行できるモジュールを作れるようにしています。

その辺を少々。

コマンド kxrepl.exekxtest.exe

実は v0.13.1 リリースより kxrepl.exekxtest.exe というコマンドが同梱されています。Linux 版では .exe はついて無くて kxreplkxtest です。

kxrepl を実行してみましょう。

$ kxrepl
kinx[  0]> .quit

REPL が動作しましたね。

次は kxtest です。

$ kxtest -v -T declaration.md
Test Cout = 11
Entry: doc/spec/statement/declaration.md
    Suite: Declaration statement
        Case[ 0]: Normal case ................................... successful (  0.10s)
        Case[ 1]: With initializer .............................. successful (  0.09s)
        Case[ 2]: With initializer of expression ................ successful (  0.09s)
        Case[ 3]: Multiple variable declaration ................. successful (  0.10s)
        Case[ 4]: Constant value (1) ............................ successful (  0.07s)
        Case[ 5]: Constant value (2) ............................ successful (  0.10s)
        Case[ 6]: Constant value (3) ............................ successful (  0.07s)
        Case[ 7]: Constant value (4) ............................ successful (  0.07s)
        Case[ 8]: Constant value (5) ............................ successful (  0.09s)
        Case[ 9]: Destructuring assignment (1) .................. successful (  0.09s)
        Case[10]: Destructuring assignment (2) .................. successful (  0.07s)


<Test Result>
    Total Test Cases:       11
        Successful  :       11
        Failed      :        0
        Warning     :        0

SpecTest が動作しましたね。

もう一つ、試しにやってみましょう。

$ diff -s kxrepl kxtest
Files kxrepl and kxtest are identical

「ファイルは同一です」 というメッセージがでました。というか、そうなんです。この 2 つは バイナリとして全く同じ です。

--exec オプションの話

この話の前に、一つ Kinx のオプションに関する情報を書いておきます。--exec というオプションです。README にも書いてある通り、このオプションによって以下の 2 つのオプションがサポートされています。

  • --exec:repl ... REPL を実行する。
  • --exec:specttest ... SpecTest を実行する。

このメカニズムは、以下の通りになっています。

  1. --exec:xxx を認識したら、Kinx の実行ファイルのあるフォルダから見て lib/exec/xxx.kx、または lib/exec/3rdparty/xxx.kx を探す。
  2. そのファイルがあったら、そのファイルがスクリプトファイルとして指定されたとみなして実行する。

なので、REPL と SpecTest はそれぞれ lib/exec/repl.kxlib/exec/spectest.kx ファイルを探してそれを実行する、という動作をしているのです。この仕組みによって、REPL と SpecTest の修正はバイナリを修正せずに実施できるようにもなっています。

kxrepl

さて、kxrepl のバイナリ(= kxtest のバイナリ)ですが、どういう作りになっているのでしょう(概ね見当は付くと思いますが)。答えはこうです。

  1. 自分自身の実行ファイル名(name としましょう)を取得(argv[0] から取得できます)。
  2. コマンドライン引数の先頭に --exec:name を割り込ませて引数リストを更新。
  3. Kinx のメインロジックに制御を渡す。

するとどうでしょう。自動的に lib/exec/name.kx(または lib/exec/3rdparty/name.kx)を参照して実行してくれるのです!

ということで、kxrepllib/exec/kxrepl.kx を、kxtestlib/exec/kxtest.kx を自動的に実行してくれるという寸法です。

ん?、そんなファイルあったっけ?はい、追加したんです(=あります)。中身を見てみましょう。

lib/exec/kxrepl.kx
using exec.repl;
lib/exec/kxtest.kx
using exec.spectest;

これだけです。中で using するだけのファイルを用意して実現しました。using の検索パスに従って repl.kxspectest.kx を見つけてくれるので、これで正しく動作します。というわけで、kxrepl.exerepl.exe に書き換えても同様に動きます。

ということで、もうお分かりですね。

オリジナル exe を作ろう

オリジナル exe ファイルの作り方は以下の通りです。動作には Kinx の dll と各種ライブラリが必要なので、kinx.exe と同じ場所に、作成した exe を置かなくてはなりませんが、やりたいことをコマンド一発でできるようにはなります。

具体的な例で。

kxcat.exe

cat コマンドみたいなものとして、kxcat コマンドを作ってみましょう。指定されたファイルを指定された順に出力します。cat コマンドと名前が重ならないように kxcat にしておきましょう。一先ずオプションは無しで、ファイルだけ複数受け付けるようにします。

lib/exec/3rdparty/kxcat.kx
$$.each {
    // Ignoring the script file name.
    if (_2 > 0) {
        System.print(File.load(_1));
    }
};

さて、そうしたら kxtest.exe をコピーして名前を変えましょう。Windows でも Linux でもコマンドは違いますが、やりたいことは同じです。

Windows
$ copy /y kxtest.exe kxcat.exe
Linux
$ cp -f kxtest kxcat

コピーしたらそのまま kxcat コマンドを実行!

$ ./kxcat README.md ChangeLog.md
<p align="right">
    <img src="https://github.com/Kray-G/kinx/workflows/Unit%20Test/badge.svg?branch=master"/>
    <img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat"/>
</p>

...(省略)

## V0.1.0 (1st Preview Release)

*   Initial Release.

できましたね。

インストールされたもので実行したい場合、Linux では以下の場所に kinx コマンドのバイナリがあるので、例えば上記の場合、kxcat コマンドは同じ位置に配置してください。kxreplkxtest も同じ場所に配置してあります。

$ which kinx kxrepl kxtest
/usr/bin/kinx
/usr/bin/kxrepl
/usr/bin/kxtest

おわりに

C でがっつり書いてコンパイルして実行ファイルを作る、でもいいんですけど、スクリプトでササっと書いたのを実行形式ファイルにしたいですよね。かといって、必要なライブラリとか dll とかを全部含めると結構なサイズになったりするので、ここは割り切って Kinx 自体が存在する前提でコマンド化できるようにしてみました。

これはこれで便利かなー、と思います。

あと、やればすぐできるんですけど、例えば kinx.dll の位置を環境変数で指定したり、オプションで渡したりできると、.exe ファイル自体はどこにおいても良くなるのでそのくらいの対応は今後するかも入れません(要望があれば)。xxx.exe と同じ場所にある xxx.kx を実行するとかね。そのほうが便利かなー。dll の場所は何かしらの方法で指定しておく必要はありますが。

ではでは、また次回。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MinGWにプルリクエストを送ってlibgrのバージョンをアップデートした話

はじめに

こんにちは。MinGWのパッケージをアップデートしたので記事にします。

どうしてMinGWのパッケージのアップデートしなきゃならないの?

パッケージマネージャーって、みんな利用していると思うんですけど、そのメンテナンスに関わったことがある人は意外と少ないと思います。私もMinGWのパッケージをアップデートするのははじめてです。

1年程前から趣味と実益を兼ねてRuby向けのグラフ描出ソフトGR.rbを作っています。
image.png

GR.rbはlibgrのバインディングです。私は普段Windowsを使っていません。しかし、ありがたいことに是非Windowsに対応してほしいという要望があって、詳しい方にPKGBUILDの作成からMinGWにlibgrのパッケージ登録まで全部やって頂きました。

それから少し時間が流れて、本家libgrのバージョンも少しずつ上がっていくので、そろそろアップデートしないといけないなと思い、重い腰を上げて 0.50.0 → 0.51.2 にアップデートしました。

MingGWのパッケージのアップデート、結果的には難しくなかったのですが、MinGWのパッケージをアップデートした日本語の体験記事が全然なくてとても心細い思いをしました。誰かの役に立つようにQiita記事を書きます。

やり方

基本的な方法はhomebrewなどと変わりません。

MSYS2公式ページ
https://www.msys2.org/wiki/Creating-Packages/

に必要な情報が載っていますので、Google翻訳などを使ってざっと目を通すと良いと思われます。

git clone

git clone https://github.com/Alexpux/MINGW-packages
cd MINGW-packages/mingw-w64-gr

あとから origin を変更してもいいのですが、最初からForkしてしまった方が作業が楽ですね。

git clone https://github.com/YOURNAME/MINGW-packages
cd MINGW-packages/mingw-w64-gr

PKGBUILDの編集

パッケージのバージョン番号を更新します。

PKGBUILD
pkgver=0.51.2

sha256sumを更新します

PKGBUILD
sha256sums=("E6A3D0ED911F6E59CC2293B5694EE18A0620849E666143870A9EDA71C02BB833")

また、今回は、前回適応されていたパッチが不要のようだったので取り除きました。

ビルドとインストール

makepkg-mingw -sCLf
pacman -U mingw-w64-*-gr-*-any.pkg.tar.xz

でできます。

プルリクエストを送る

大丈夫そうだったらブランチを切ってプルリクエストを送りましょう。
忘れずに

git pull --rebase

ブランチの名前はなんでも良さそうですが、gr-0.51.2 としました。
プルリクエストのコミットは、皆さん大文字、小文字が入り乱れていますが、gr: Update to 0.51.2 もしくは gr: update to 0.51.2 とすればよいようです。

プルリクエストを提出したら、ちゃんとCIが通過しているか確認しましょう。
通過していればメンテナンスをされている方がチェックしてマージしてくれるはずです。

今回のPRは数時間のうちに無事にmergeされました。かなり活発にメンテナンスが行われているようです。

おわりに

MinGWもバージョンをアップデートするだけなら怖くない!

この記事は以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails reference型 作成 追加

はじめに

今回はrailsでのマイグレーション時にreference型を扱うことがことがあったのでまとめる。

外部キーとは

reference型を扱うにあたって外部キーについて知っておかなくてはならない。

外部キーとは、リレーショナルデータベース(RDB)で、テーブルのある列に、別のテーブルの特定の列に含まれる項目しか入力できないようにする制約。また、その際に指定する列
http://e-words.jp/w/%E5%A4%96%E9%83%A8%E3%82%AD%E3%83%BC.html#:~:text=%E5%A4%96%E9%83%A8%E3%82%AD%E3%83%BC%E3%81%A8%E3%81%AF%E3%80%81%E3%83%AA%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB,%E3%82%92%E7%94%A8%E3%81%84%E3%81%A6%E8%A8%AD%E5%AE%9A%E3%81%A7%E3%81%8D%E3%82%8B%E3%80%82

今回はarticlesテーブルにreference型のuser_idという外部キーを設定する。

前提

sampleとしてuserテーブルとariticleテーブルを準備する。

class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string   :name
      t.string   :email
    end
  end
end
class CreateArticles < ActiveRecord::Migration[6.0]
  def change
    create_table :articles do |t|
      t.string   :title
      t.string   :content
    end
  end
end
$ rake db:migrate

reference型のカラムの作成

reference型で作成するとuserそのまま追加されるわけではなくuser_idというカラム名で追加される。また、index:trueを追記することなく自動でインデックスをはってくれるというメリットもある。

class CreateArticles < ActiveRecord::Migration[6.0]
  def change
    create_table :articles do |t|
      t.string   :title
      t.string   :content
      t.references :user, foreign_key: true
    end
  end
end

*foreign_key: trueをつけないと外部キー制約はつけることができない。
foreign_key: trueを書き忘れたことで設定できないこtがあった。

add_foreign_keyを使っての追加も可能。

class CreateArticles < ActiveRecord::Migration[6.0]
  def change
    create_table :articles do |t|
      t.string   :title
      t.string   :content
    end
      add_foreign_key :articles, :users
  end
end

reference型のカラムの追加

class AddReferenceColumn < ActiveRecord::Migration[6.0]
  def change
    add_reference :articles, :user, foreign_key: true
  end
end

この際にもforeign_key: trueを忘れずに。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby テキスト変換

Ruby を使って PHP のプログラムを変換します。
PHPの文字コードは、EUC_JP と CP51932 が混在しています。
Python は、CP51932 を取り扱えないので、Ruby で記述しました。

str_src を str_target に置き換えます。
str_src がない時は、何もしません。

file_filter.rb
#! /usr/bin/ruby
# -*- coding: utf-8 -*-
#
#   file_filter.rb 
#
#                       Aug/09/2020
#
#
# --------------------------------------------------------------------
# [2]:
def read_proc(file_in)
    lines = []
    File.open(file_in) do |io|
        lines = io.readlines()
    end
#
    return lines
end
#
# --------------------------------------------------------------------
# [4]:
def convert_proc(lines)
    flag_convert = false
    str_src = '$var = $dict["aa"];'
    str_target = 'if(array_key_exists("aa",$dict)){$var = $dict["aa"];}'
    llx = str_src.size

    lines_new = []
    for line in lines do
        if line.slice(0,llx) == str_src then
            puts line
            lines_new.push(str_target)
            flag_convert = true
        else
            lines_new.push(line)
        end
#
end
#
    return flag_convert,lines_new

end
# --------------------------------------------------------------------
# [6]:
def out_proc(file_out,lines_new)
    File.open(file_out, mode = "w") do |f|
        lines_new.each{ |line| f.puts(line)}
    end
    STDERR.puts file_out + " written ***"
end
# --------------------------------------------------------------------
STDERR.puts "*** start ***"
file_in = ARGV[0]
#
lines = read_proc(file_in)
#
flag_convert,lines_new = convert_proc(lines)
#
if flag_convert then
    out_proc(file_in,lines_new)
end
#
STDERR.puts "*** end ***"
# --------------------------------------------------------------------

実行

./file_filter.rb in01.txt
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コンテナ上のデバッグ環境構築 - DockerでRailsチュートリアルのローカル開発環境構築 -

はじめに

Dockerでローカル開発環境構築を行い、Railsチュートリアルを再走しております

  • Railsチュートリアル最新版(2020.8.6現在)に対応のRails 6
  • Dockerを使用し、開発環境の再現が可能
  • なるべくローカル環境にインストールしない

今回はRailsチュートリアルの7章に相当する部分で、
Dockerコンテナ上で開発を行っている場合にデバッグを行う内容を紹介します

第一回
DockerでRailsチュートリアルのローカル開発環境構築(Rails 6 + PostgreSQL + Webpack) - Qiita

第二回
DockerでRailsチュートリアルのローカル開発環境構築 - RSpec導入 & CircleCIでHerokuデプロイ- - Qiita

第3回
DockerでRailsチュートリアルのローカル開発環境構築 - WebpackでBootstrapとFont Awesomeを導入 - - Qiita

個人開発アプリ
mdClip <オンラインmarkdownエディタ>

Dockerのコンテナ上で操作する場合はターミナルのコマンドを適宜

$ docker-compose run app ...

もしくは

$ docker-compose exec app ...

で置き換えてください。

Dockerコンテナ上の開発環境でRailsのデバッグを行う

方法1 Railsのコンテナにアタッチ -> デタッチ

参考サイト
Docker と Rails 5.2 の開発環境でデバッグを行えるようにする - ココナラよもやまブログ

Railsのコンテナにアタッチする

$ docker attach $(docker-compose ps -q app)

これでデバッグコンソールが使用できます

コンテナからデタッチする

デバッグをquitで抜けると
コンテナが終了してしまうのでrails serverも落ちる
これではすごく使い勝手が悪いなと思ったら

コンテナからデタッチ(Control P -> Control Q)するだけなら、コンテナを終了しなくて済むとのこと

ただ、VS Codeのコンソールで操作していると
Control P , Control Qは他のショートカットに割り当てられない

これはコンテナでタッチキーを置き換えることで解決方法とのことです

参考記事
docker で Ctrl-p 2回押し問題 (detach-keys の問題) を解決するには - Qiita

~/.docker/config.jsonに設定を記述します

vi ~/.docker/config.json
{
  # ...省略
  "detachKeys": "ctrl-e"
}

私は control + eでデタッチできるように設定しました

方法2 VS Codeでデバッグ用のコンテナを動かす

VS codeのデバッグ機能から、デバッグ用のコンテナを立ててデバッグする方法もあるようです

Developing inside a Container using Visual Studio Code Remote Development

シームレスで便利そうだと思ったのですが
ここまででちょっと時間を使ってしまったのでまた別の機会に追記します

自分用メモ

Get started with development Containers in Visual Studio Code

[VS Code - Remote Containers で Docker Compose で動いている Rails アプリに接続する - さめたコーヒー](

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

テクトロジーによる実践的組織構造学

今回の記事では、ソ連の革命家、医師、哲学者、小説作家であったアレクサンダーボグダノフが提唱したテクトロジーと呼ばれる実践的組織構造学について紹介する。
テクトロジーでは組織が安定、成長、破綻する環境、条件について詳細に解説し、安定した組織を生成する手法について解説している。
テクトロジーの概念を拝借し、創造的な組織創造の手法を紹介したいと思う。

テクトロジーにおける組織の定義

テクトロジーでは、組織をオープンクローズ型の成長する有機体システムと定義している。
組織とは以下の要素で構成されている。
ビジョン・・・組織の目指すべき方向性。
経済・・・組織のボディ。巨大であるほど収容できる人の人数が増加する
金融・・・組織を循環する血液。
生産・・・もの、サービスを生産し、組織の経済を巨大化する手段。

これらの有機的な要素が相互作用し、成長することで組織という有機体が構成されていると考える。

テクトロジーにおける成長する有機体システムとは

テクトロジーでは、組織をオープンクローズ型の成長する有機体システムと定義している。
テクトロジーにおける組織の定義を中国の陰陽論によって説明することができる。
陰陽論とは、原初は混沌(カオス)の状態であると考え、この混沌の中から光に満ちた明るい澄んだ気、すなわち陽の気が上昇して天となり、重く濁った暗黒の気、すなわち陰の気が下降して地となった。この二気の働きによって万物の事象を理解し、また将来までも予測しようというのが陰陽思想である。
組織が外部からエネルギーを取り入れ、出力するインプット、アウトプットの運動を陰陽論における陽の気と捉えることができる。
逆に組織内部に沈殿し、成長し、ヒエラルキーを形成する秩序生成を担う運動を陰陽論における陰の気と捉えることができる。

テクトロジーにおける生産の定義

テクトロジーでは、組織における生産活動は以下の3つに分類されている。
人の生産・・・人に教育を施し、組織活動に従事する生産者を作成する
モノ、サービスの生産・・・外部から取得した資材を用いて、モノ、サービスの生産を行う。
アイデア・・モノ、サービスを生成するための知識、アイディアを作成する。
組織における生産活動を高めることで、組織の経済を成長させることができる。

テクトロジーおける組織のフォーム(形態)について

現実の世界で、人が活動を行う場合、必ず外部からの影響、抵抗を受ける。
外部からの影響、抵抗を抑えるために、組織は環境に合わせた最適なフォーム(形態)を取る必要がある。
魚やイルカなど、魚と哺乳類で種族は異なるが、水の抵抗を抑えるために同様の流線形フォルムを取っている。
組織のフォーム(形態)は外部環境によって決定される。
外部環境からの抵抗を最小限にするために、外部との接触の最小化、不要な組織的機能の削除などが求められる。
最適なフォーム(形態)によって、組織は外部からの抵抗を減少させ、健全に成長することができる。

テクトロジーにおける組織が不安定化する条件

テクトロジーにおける組織が不安定化する条件として以下の2点が挙げられる。
・外部からのエネルギー取得の減少・・外部から人、モノ、金の循環が減少することで組織のサイズ、経済を維持することできなくなる。
・ヒエラルキーシステムの固定化・・・ヒエラルキーシステムが巨大化し、組織が硬直化してしまう。
組織不安定化を回避する手法として以下の手段が有効とされている。
生産手段を研究、開発、更新を行い、組織の経済成長のスピードを増加させる。
組織が硬直化の原因になっているヒエラルキーシステムを解体し、適切なサイズに組み替える。

まとめ

アレクサンダーボグダノフテクトロジーに関するアイディアを発表した時期は1920年代である。
独学で組織が破綻する条件、環境を発見し、持続可能な成長のコンセプトを提唱したアレクサンダーボグダノフの先見性は恐るべきものである。
ソ連は軍事、IT、経済においてアメリカと張り合うことができた超大国だった。
ソ連時代に考えられたアイディア、思想などは現代においても見直されるべきものだと思われる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リファクタリングしてみた①

バージョン

・ruby 2.5.7
・Rails 5.2.4.3

ポートフォリオのコードをリファクタリング

まず、現状はというと下記の通り。ひどい、、。ほぼ同じ事を書いているアクション名が8つ存在している。まず、そのdate1からdate8のアクションをリファクタリングしてみる。
スクリーンショット 2020-08-09 14 27 08
スクリーンショット 2020-08-09 14 27 26
スクリーンショット 2020-08-09 14 27 40

それぞれの処理で分ける処理は何か?同じ処理は何か?の視点で考える

まずこのdate1からdate8のアクションの処理内容を大まかに分類すると、
date1は新しくレコードをnewする処理。
date2からdate7は新しくレコードをnewする処理+前のページから渡ってきたカラムを受け取って、レコードを保存する処理。
date8は前のページから渡ってきたカラムを受け取って、レコードを保存する処理+また別のレコードを保存する処理。
なので、date2〜date7はまとめれそうだと考えた。

同じ処理をまとめるにはどうしたらいいか

今回の場合、リファクタリングしたくてもそれを阻んでいたのはこのpageカラムの存在。
date2~7はpageの値が変わっているだけで、後の処理はredirect先が違うくらいでコードは一緒だった。
スクリーンショット 2020-08-09 14 53 04

ページ遷移するごとに値を増やしていく

pageの値を自分で書くのではなく、ページが変わるごとに値が+1ずつされるようにコードかけばいいのではと考えた。
その為にまずdate1で@conto_page = 1とインスタンス変数を作る。
スクリーンショット 2020-08-09 15 12 13
次に、ビュー側で値を受取り、form_withでconto_page: @conto_pageでdate2に@conto_pageを渡す。
スクリーンショット 2020-08-09 15 18 46
最後に、受け取ったparams[:conto_page].to_i == 8 ならdate8に行くようにredirectして、それ以外ならconto_pageが+1ずつ増えて行く処理をして
スクリーンショット 2020-08-09 15 15 10

リファクタリング完成!

無事にdate3~date7のアクションは消す事が出来ました。
さっきよりコード量が4割ほど削減が出来ました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【クエリ爆減】update_allで一定条件下の複数データをまとめて更新する【Ruby on Rails】

入荷から一定期間経過した商品には割引(30日以上→500円・60日以上→1000円・90日以上→1500円)を適用する為、以下の様なロジックを書きました。

items = Item.where("created_at < ?", Time.zone.now - 30.days)
items.each do |item|
  created_at = item.created_at
  today = Time.zone.today
  three_month = 90.days
  two_month = 60.days
  one_month = 30.days

  if today >= created_at + three_month
    discount = -1500
  elsif today >= created_at + two_month && today < created_at + three_month
    discount = -1000
  elsif today >= created_at + one_month && today < created_at + two_month
    discount = -500
  end

  item.discount = discount
  item.save
end

しかし上記のコードでは、itemsの数の分処理が走ってしまう所謂 N+1問題 が発生し、処理速度やメモリに大きな影響を与えてしまいます。

そこで活躍するのがupdate_all
以下の様に条件をhashに纏めて配列に格納、各条件に当てはまるデータを纏めて更新します。

today = Time.zone.now
conditions = [
  { upper_limit: today - 30.days, lower_limit: today - 59.days, amount: -500 },
  { upper_limit: today - 60.days, lower_limit: today - 89.days, amount: -1000 },
  { upper_limit: today - 90.days, lower_limit: today - 365.years, amount: -1500 }, 
]
conditions.each do |condition|
  Item.
    where("created_at between ? and ?", condition[:lower_limit], condition[:upper_limit]).
    update_all(discount: condition[:amount])
end 

するとクエリは条件分のたった3つだけに収まります?

Item Update All (8.8ms)  UPDATE `items` SET `items`.`discount` = -500 WHERE (created_at between '2020-04-27 00:00:00' and '2020-05-26 00:00:00')
Item Update All (3.2ms)  UPDATE `items` SET `items`.`discount` = -1000 WHERE (created_at between '2020-03-28 00:00:00' and '2020-04-26 00:00:00')
Item Update All (19.4ms)  UPDATE `items` SET `items`.`discount` = -1500 WHERE (created_at between '1920-06-25 00:00:00' and '2020-03-27 00:00:00')

※ActiveRecordオブジェクトを経由しない更新方法のため、バリデーションやコールバックは実行されない点にご注意ください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでのカラムの追加

カラムの追加

新しいカラムの追加(基本)
$rails g migration (行う処理+テーブル名)(追加したいカラムとデータ型など)
$rails g migration AddColumnToUsers  name:string age:integer

新しいカラムにインデックスを追加
$rails g migration AddColumnToUsers name:string:index

カラムの削除
$rails g migration RemoveNameFromUsers name:string

テーブルの作成と同時にカラムの作成
$rails g migration CreateUsers name:string age:integer

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Mac ruby 2.0.0におけるDEFAULT_CERT_FILEのディレクトリ情報

過去記事でopenssl、curl、rubyをソースビルド、インストールしたMacとは別のMacがある。
MacOSX 10.11はhomebrewが動作するが削除し概ねクリーンにした。

ruby 2.0.0に戻る。すると
$ ruby -ropenssl -e "p OpenSSL::X509::DEFAULT_CERT_FILE"
"/System/Library/OpenSSL/cert.pem"

OpenSSL $ ls -la
total 8
drwxr-xr-x 6 root wheel 204B 2 5 2016 .
drwxr-xr-x 82 root wheel 2.7K 8 28 2018 ..
drwxr-xr-x 2 root wheel 68B 2 5 2016 certs
drwxr-xr-x 8 root wheel 272B 2 5 2016 misc
-rw-r--r-- 1 root wheel 9.2K 2 5 2016 openssl.cnf
drwxr-xr-x 2 root wheel 68B 2 5 2016 private
OpenSSL $ cd certs
certs $ ls -la
total 0
drwxr-xr-x 2 root wheel 68B 2 5 2016 .
drwxr-xr-x 6 root wheel 204B 2 5 2016 ..
certs $

以上、メモ書き。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

openssl、curl、rubyインストールについての印象や覚え

●備忘録 メモ書き 証拠のログは殆ど無し

2020年08月上旬にautoconfからopenssl、curl、rubyまでソースインストール出来た。
openssl curl(wget)Ruby等々のSSL通信に悩まされてきたが殆ど解消したかもしれない。

kindai.rbを使い始めた時期(2015〜2017?)は記憶にない。
qiitaでの質問は2017年が最初。(他に5chで質問したかも?)2020年07月までに行ったopenssl curl(wget)Ruby等の環境構築でログが残ってないが、覚えていることを書いておく。

●事象

homebrewのImageMagick インストールをみていると大量のコマンドとライブラリがインストールされる。依存関係もあるらしく自分ではソースビルドが出来ないと考えていた。
ー>実際は簡単だった。手間と時間がかかるだけ。

homebrewはリンク切れや不具合を起こす。数年に一回程度。homebrewの再インストールの経験が「たしか3,4回数/一台のMac」ある。

openssl又はcurlインストールにおいて、homebrewビルドでもソースビルドでもSSL通信の不具合が起きた。バージョンアップだけでも起きた。
証拠のログがない。
ー>homebrewビルドのほうが成功率は高かった。

rbenvインストールにおいて、homebrewビルドでもソースビルドでも不具合が起きた。
証拠のログが一部ある。
今回(08月上旬)も問題が起きた。
ー>不具合が嫌でstowで管理した。
ー>sotwではリンク変更とパス変更、source bash_profile やsource .zshrcが必要なのでやや手間だが、stow管理の方がopensslやcurl連携しSSL通信出来るようになるまで短時間で済む気がする。

●印象や覚え

rbenvがするrubyインストールにおいて、./configureオプションはネット上であまり検証されてないように思う。
homebrewがするrubyインストールにおいて、./configureオプションはネット上で検証されてないように思う
homebrewがするcurlインストールにおいて、./configureオプションはネット上で検証されてないように思う
homebrewがするopensslインストールにおいて、./configureオプションはネット上で検証されてないように思う

全てソースビルドされた場合。
openssl作者の意図(./configureオプション)
curl作者の意図
ruby作者の意図

だけならともかく、加えてhomebrewの理解と意図がある場合。
homebrew作者が上記の意図を理解した(かもしれないので間違いがあるかも?)上での
opensslの./configureオプション
curlの./configureオプション
rubyの./configureオプション
(rbenv、ruby-buildなし)
最も問題が少なそう?

さらに加えて、rbenv(ruby-build)ビルドされた場合。
rbenv(ruby-build)作者が意図する
opensslの./configureオプション理解(インスト済みの環境を把握する)
curlの./configureオプション(インスト済みの環境を把握する)
rubyの./configureオプション

さらに場合分けで、全てhomebrewビルドされた場合。
rbenv(ruby-build)の意図する
opensslの./configureオプション理解(インスト済みの環境を把握する)
curlの./configureオプション(インスト済みの環境を把握する)
rubyの./configureオプション
この場合だけは二番目に問題が少なそうではあるが、疑問が残った結果だ。

ツールが多ければ問題の切り分けが難しいのは分かってもらえると思う。

一番下の全てhomebrewに任せる場合も不具合がある。
組み合わせはともかく、kindai.rb動作に至るまでにSSL関連の失敗、不具合(不明瞭?)今までopenssl、curl、rubyのインストールを何度やり直したか分からない。

インストール(configureオプション)と使い方で
opensslの質問
curlの質問
rubyの質問
等々、それぞれがネットに大量にある状態だ。(ありすぎて問題だ。)

数年間、筆者はqitta以外でもインストール記事を読んできたが、今まで上記の点を指摘か注意した記事を一つも見当たらなかった。(linuxでなくMacだからかもしれないが。)

今回で筆者はソースビルドが一番早いと考えを改めるようになった。

記憶と推測だけで申し訳ない。
過去のインストールログが残っておらず突っ込み所は多数があるが、ご容赦を。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

openssl、curl、ruby、homebrew、rbenvインストールについての印象や覚え

●備忘録 メモ書き 証拠のログは殆ど無し

2020年08月上旬にautoconfからopenssl、curl、rubyまでソースインストール出来た。
openssl curl(wget)Ruby等々のSSL通信に悩まされてきたが殆ど解消したかもしれない。

kindai.rbを使い始めた時期(2015〜2017?)は記憶にない。
qiitaでの質問は2017年が最初。(他に5chで質問したかも?)2020年07月までに行ったopenssl curl(wget)Ruby等の環境構築でログが全て残ってないが、覚えていることを書いておく。

●事象

homebrewのImageMagick インストールをみていると大量のコマンドとライブラリがインストールされる。依存関係もあるらしく自分ではソースビルドが出来ないと考えていた。
ー>実際は簡単だった。手間と時間がかかるだけ。

homebrewはリンク切れや不具合を起こす。数年に一回程度。homebrewの再インストールの経験が「たしか3,4回数/一台のMac」ある。

openssl又はcurlインストールにおいて、homebrewビルドでもソースビルドでもSSL通信の不具合が起きた。バージョンアップだけでも起きた。
証拠のログがない。
ー>homebrewビルドのほうが成功率は高かった。

rbenvインストールにおいて、homebrewビルドでもソースビルドでも不具合が起きた。
証拠のログが一部ある。
今回(08月上旬)も問題が起きた。
ー>不具合が嫌でstowで管理した。
ー>stowではリンク変更とパス変更、source bash_profile やsource .zshrcが必要なのでやや手間だが、stow管理の方がopensslやcurl連携しSSL通信出来るようになるまで短時間で済む気がする。

●印象や覚え

rbenvがするrubyインストールにおいて、./configureオプションはネット上であまり検証されてないように思う。
homebrewがするrubyインストールにおいて、./configureオプションはネット上で検証されてないように思う
homebrewがするcurlインストールにおいて、./configureオプションはネット上で検証されてないように思う
homebrewがするopensslインストールにおいて、./configureオプションはネット上で検証されてないように思う

全てソースビルドされた場合。
openssl作者の意図(./configureオプション)
curl作者の意図
ruby作者の意図
(rbenv、ruby-buildなし)
最も問題が少なそう?

だけならともかく、加えてhomebrewの理解と意図がある場合。
homebrew作者が上記の意図を理解した(かもしれないので間違いがあるかも?)上での
opensslの./configureオプション
curlの./configureオプション
rubyの./configureオプション
(rbenv、ruby-buildなし)

さらに加えて、rbenv(ruby-build)ビルドされた場合。
rbenv(ruby-build)作者が意図する
opensslの./configureオプション理解(インスト済みの環境を把握する)
curlの./configureオプション(インスト済みの環境を把握する)
rubyの./configureオプション

さらに場合分けで、全てhomebrewビルドされた場合。
rbenv(ruby-build)の意図する
opensslの./configureオプション理解(インスト済みの環境を把握する)
curlの./configureオプション(インスト済みの環境を把握する)
rubyの./configureオプション
この場合だけは二番目に問題が少なそうではあるが、疑問が残った結果だ。

ツールが多ければ問題の切り分けが難しいのは分かってもらえると思う。

一番下の全てhomebrewに任せる場合も不具合がある。
組み合わせはともかく、kindai.rb動作に至るまでにSSL関連の失敗、不具合(不明瞭?)今までopenssl、curl、ruby、rbenvのインストールを何度やり直したか分からない。

インストール(configureオプション)と使い方で
opensslの質問
curlの質問
rubyの質問
等々、それぞれがネットに大量にある状態だ。(ありすぎて問題だ。)

数年間、筆者はqitta以外でもインストール記事を読んできたが、今まで上記の点を指摘か注意した記事を一つも見当たらなかった。(linuxでなくMacだからかもしれないが。)

openssl、curl、ruby、rbenvのインストールを何度もやり直し失った時間を考えると
今回で筆者はソースビルドが一番早いと考えを改めるようになった。

記憶と推測だけで申し訳ない。
過去のインストールログが全て残っておらず突っ込み所は多数があるが、ご容赦を。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む