Rails 5.0からRails 5.1へのアップデート(1/?)
こんにちは。時間の合間に作成しているサービスのRailsを5.0から5.1へアップデートしていまして その内容を書いています。rails upgrade guideが、まだ作成中で、issueを読んで対応していました。
テスト, jsの移行は、まだ終わっていなくて順次移行中です。
環境
Gemfile
Gemのversionをあげます。(環境によって異なります)
# Gemfile gem 'rails', '5.1.0' # Use sqlite3 as the database for Active Record gem 'puma', '~> 3.7' gem 'webpacker' gem 'coffee-rails', '~> 4.2' group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] # Adds support for Capybara system testing and selenium driver gem 'capybara', '~> 2.13.0' gem 'selenium-webdriver' end group :development do # Access an IRB console on exception pages or by using <%= console %> in views gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' end
参考: https://github.com/kikeda1104/9syoku/blob/master/Gemfile
bundle install or bundle update
./bin/rails app:update
rails 5.0でも使われていた、binファイルや設定ファイルを更新してくれる./bin/rails app:updateがありますのでこれを利用します。 config、routeが上書きされるので、差分をとって編集しましょう。
./bin/rails app:update
secret.ymlの暗号化
./bin/rails secrets:setup
secrets.yml.keyが作成され、gitignoreに追加されます。 secrets.yml.encを編集したい場合は、`./bin/rails secrets:edit'です。
上のメッセージが出たら、EDITOR=vi bin/rails secrets:edit
EDITORは、好みで変えてください。
productionのsecret_key_baseをこちらに設定して保存します。
webpacker
これは、新規だった場合に、rails new rail_app --webpack
–webpackオプションを指定すると、自動でwebpacker gemがGemfile bundle installによりgemがインストールされます。
./bin/rails -T 一部省略
namespaceにwebpackerとついているのは、webpacker gemが導入されることにより追加されるタスクです。 vueを含めてみます。
./bin/rails webpacker:install:vue
migrationファイル
ActiveRecord::Migration => ActiveRecord::Migration[5.0 or 5.1]に修正
./bin/rails db:drop RAILS_ENV=production && ./bin/rails db:create RAILS_ENV=production && ./bin/rails db:migrate RAILS_ENV=production
RAILS_ENV=production ./bin/rails assets:precompile
puma起動
RAILS_ENV=production ./bin/rails s
まとめ
気が向いたら、細かい改善点を更新していきます。
近況
前職の会社を辞めてから、フリーランス(個人事業主)として働き始めて コードを書く機会が増えてきたので、知見を少しずつブログに書きためようかと思います。 友人の紹介による仕事ですが、色々と新しい経験を積める環境にあって感謝しています。
参考
A Guide for Upgrading Ruby on Rails — Ruby on Rails Guides
rails/5_1_release_notes.md at 39a2e1465e15d1da56ba1f4ed14fd38740bd86d4 · rails/rails · GitHub
circle.ymlの設定(bunlderのみ)
FormObject実装(2回目)
前回からの引き続き。viewとcontrollerの実装を進めていきます。
前回まで
FormObject実装(1回目) - kikeda1104's blog
controllerの実装
# controller/sample_forms_controller.rb class SampleFormsController < ApplicationController def new @offer_form = OfferForm.new end def create @offer_form = OfferForm.new(job_offer_form_params) if @offer_form.save redirect_to :create, notice: '保存に成功しました' else render :new end end private def job_offer_form_params params.require(:job_offer_form).permit(JobOfferForm.attributes.keys) end end
viewsの実装
続いて、viewsのフォームを作成します。
# views/sample_forms/new.html.haml # ... 省略 : bootstrap利用しています。cssの定義については省略します - form_for(@offer_form, polymorpic_path(@offer_form.job_offer)) do |f| # polymorpic_path([:admin, @offer_form.job_offer])も可能 %fieldset %legend フォーム .form-group = f.label :title, class: 'col-md-2 control-label' col-md-10 = f.text_field :title, placeholder: '例: ', class: 'form-control' .form-group = f.label :description, class: 'col-md-2 control-lable' .col-md-10 = f.text_area :description, class: 'form-control' .form-acitons .row .col-md-12 %button.btn.btn-default{ type: 'submit' } 戻る %button.btn.btn-default{ type: 'submit' } %i.fa.fa-save 確定
ここまでです。次は、1回目の記事のサンプルコードを更新してから、form_objectsの実装をより進めていきます。
参考
FormObject実装(1回目)
form_objectの実装を進める際に、gem virtus
を使って実装を進めたので、何度かに分けて書いていきます。
環境
gemの導入
Gemfile
に追加します。
# Gemfile ... gem 'virtus' ...
$ bundle install
app/forms
app/forms
のディレクトリを作成します。
mkdir app/forms
config/initialze/forms.rb
を作成して,下記を追加します。
# forms.rb # require_dependecy 'parent_class' Dir.glob('app/forms/**/*.rb') do |f| require_dependency(Rails.roots.join(f)) end
formクラス作成します。
## vim app/forms/offer_form.rb class OfferForm include Virtus.model include ActiveModel::Model attr_accessor :errors attribute :id, Integer attribute :title, String attribute :description, String attribute :main_image, String attribute :side_image_left, String attribute :side_image_right, String attribute :status, Integer, default: 0 attribute :type_of_job_id, Integer attribute :company_id, Integer attribute :adoption_of_shape_id, Integer attribute :confirming, Boolean, default: false attribute :type_of_job_id, Integer attribute job_of_offer, JobOffer validates :title, :status, :type_of_job_id, :adoption_of_shape_id, presence: true def persisted? job_offer.persisted? end ... end
virtus
のREADME
に記載されていて、1:多の関係にある構造も実現できますので、accepts_nested_attributes
を利用せずに
実装をこちらに変更することができます。
余談ですが、Optimistic locking
を実装する上で、accepts_nested_attributesでは、実現できない(仕様が通れば...)ケースがあり
formObjectを通して、lock_version
をコントロールする設計を実現するのに、virtus
を採用(しようとした)経緯がありました。
補足: 誤解を与えそうな表現になっていたので、訂正。virtusは、属性の型、タイプキャスト、初期値を実現します。 virtusを使わずに、form objectを作成することもできます。
今回は、ここまでです。
参考
GitHub - solnic/virtus: Attributes on Steroids for Plain Old Ruby Objects
肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳)
Rails4でFormオブジェクトを作る際に気をつける3つのポイント|江の島エンジニアBlog
postgre sql サーバの起動方法(Cent7.x)
自宅のrailsアプリでは、posgreを使っていてサービス起動/停止する際にコマンドを忘れないためのメモです。
環境
- Cent OS 7.x
- PostgreSQL 9.2.15
起動方法
インストール方法により、サービス名も変わります。
# systemctl start postgresql
株式会社リューノスを退職しました。
SNSに投稿するには長文になっていたので、 重複しますが報告と退職の理由について書いていきます。
正確には記事の投稿している日は、まだ在籍中で、1月10日で退職します。
報告
最終日なのに15時位まで、コードを書き、マージまでして、17時過ぎても質問され続けていて疲れもしましたが、まあ、最終日も貢献することができ嬉しく思っています。
挨拶の後には、お花とプレゼントまで頂いて、退職することを感じつつ、嬉しい一日になりました。 (帰り際に牛乳をこぼすという不手際がなければ。。)
今の会社では、2年間、在籍することになり、在籍中に若手の教育と開発全般で、活躍できたと自負しています。関係者の皆さまありがとうございました。
今後は、フリーで働きながら、エンジニアのキャリアを積んでいきます。
退職ついて
実は退職の理由に、後ろめたい理由があるんじゃないかと疑われる方がいました。その方は、心配してくれて聞いてくれたんだと思っています(優しい方なので)
上司に退職の意思を伝える際に、きみは影響力があるからと言われて (正直そんな自覚はなかったのですが) 開発メンバーに対して積極的は発言や行動(もくもく会、プライベートのイベント)は控えていました。 できるだけ、まわりや若手の意見を優先して採用して欲しかったですし、そうすることで 退職するインパクトが下がると思っていたからです。
上に書いた事をやっていることと、社内で親しい方々に、私からでなく、所属している部長から退職1ヶ月前に私が退職する旨を発表する形になってしまったことが原因だと思っています。 私からはまだ言わないで欲しいと言われていることもあり、そちらを優先していましたが。別の方から退職を伝えるのではなく、私から直接伝えておけば、印象が違ったなと反省しています。
実際に退職理由はこれですと一言で言えなくなっていまして。 上司に退職する際に伝えた言葉は、マネジメントと開発を両立するのは、難しいので、開発に専念したい旨を伝えていました。それだけではなく、お金の面、経験の面、時間の面で より自分にとってより良い環境や条件で働きたいと願望があり、そちらを優先した次第です。
エンジニアとして、まだまだ技術力も知識を伸ばしていきたいです。 承認欲求も強くあります。若手の教育係としての仕事もしていましたが、若手の成長を優先してばかりいれるほど大人でもなかったので 自分にとって成長できる幅が大きい、自分にとって好条件かつ効率の良い生き方を優先したいというのが今回の退職理由です。
以上です。だらだら書きましたが、改めて関係者の方々、暖く見送っていただきありがとうございました。
仕事のご依頼は下記のメールアドレスにお願いいたします。
ActiveRecord::Base.establishによる複数回切り替え時の不具合
掲題の件、テスト書いていることで発見できまして、APIリファレンスを読むと割と合点はいきましたが 間違えなどあれば、指摘いただきたいです。
環境 - rails 5.0.0.1(puma) - ruby 2.3.1
ActiveRecord::Base.establish
を何度も読み出すことで、query
を発行した際に事前に切り替えたDBではなく
切り替え前のDBのままquery
を実行する不具合がテストで見つかりましてその改善策です。
def change_schema ApplicationRecord.remove_connection ActiveRecord::Base.establish YAML.load_file(Rails.root.join('config', 'database.yml')[Rails.env] end
clear_all_connection!
などを実行しても、上手くリセットされていなかったので、remove_connection
からconnection
をdisconnect
で切断してから
動作するようになりました。
テストは恩恵も大きいし、テストを定常的に書くのも重要ですね。
参考
Strong parameterで受け取れなかったparameter
Strong Parameterを使っていて、取れないケースあたってしまい、後回しにしたので、気になっている。 Workaroundや、Hackな対応をする予定なので、明日また書き直す。
{ hoge: { id: '1', name: '2', age: '29', '1': { ... }, '2': { ... } } }
class HogeController < ApplicationController private def set_params # 間違っています。 params.reuqire(:hoge).permit(:id, :name, :age, '1', '2') end end
ここで、まず無理でした。数値をシンボル化できず、Strong Parameterでセットできないため。
... def set_params params.require(:hoge).permit(:id, :name, :age).to_h.merge((1..2).each_with_object({}) { |i, h| h[i.to_s] = params[:hoge][i.to_s] }) end ...
- また明日、書き直します。
参考
http://api.rubyonrails.org/classes/ActionController/Parameters.html
Module名を切り出してclass_nameを取り出す。
Qiitaに同じ内容の記事が丁度あって悲しい気分になったが、コードを書いていたので記録として残しておく。
本ブログは、備忘録という面もありますので、読まれている方は気分を害さないでいただきたいです。
動的にSQLのテーブル、カラムの別名を定義したくなり、クラス名とメソッド名を利用していたが、
app/service
配下に置かれている訳でもなく、app/service/hoge/...rb
という形でclass
が置かれているので、直接class
をそのまま取るわけにもいかないので、即興で書いていた。
サンプルコード
module Hoge class BaseService def initialize end def class_name self.class.to_s.split('::').last.underscore end end end
動作
$ Hoge::BaseService.new.class_name => "base_service"
以上になります。
参考
Factory Methodの利用(Ruby)
Rubyによるデザインパターン
という本を借りたまま、持っているのですが、たまたま実務でFactory Method
パターンを利用するのに
良い機会が得られたので、本を思い出しながら設計/実装を進めました。周りを気にせず、実装に集中できるのは楽しいですね。
前提
Rails 5系
Ruby 2.3系
準備
class BaseService def test_method end end class UserService < BaseService def test_method puts "UserServiceから呼び出しています。" end end class MemberService < BaseService def test_method puts "MemberServiceから呼び出しています。" end end
呼出側
class SelectClass def initialize(option) @service = "#{option.capitalize}Service".constantize.new # Rails end def service_call @service.test_method end end
動作確認
SelectClass.new("user").test_method -> puts "UserServiceから呼び出しています。" SelectClass.new("member").test_method -> puts "MemberServiceから呼び出しています。"