Rails6のバージョンアップについて

最近WEB+DB PRESS vol.111を読んで今さらながらRais6に気づいたので、Rails6の新機能をブログにまとめようと思います

ていうかバージョン上げよう...

 

・ActionMailbox

名前の通りメールができる機能、

メールの受信はもちろん転送や返信、

プロバイダの指定、

取得した情報をデータベースに保存などが出来る

 

・ActionText

テキストの編集機能を追加出来る新機能、

wordとかexcelとかhatenablogみたいな書式編集が出来る、

ドラッグアンドドロップで画像の追加が出来る、

form.rich_text_areaで簡単に作成、本当にリッチ

 

・複数データベース

database.ymlで指定することで指定された複数のデータベースに保存されるようになる

 

Zeitwerk

Zeitwerkという効率的で早いオートロードシステム

実行順序に依存するオートロード定数のエッジケースも解消

名前空間にあるものは遅延される

 

ActiveRecord: :Relation#pick

whereやlimitを使っていた検索をpickで行える

例えばUserテーブルからageが20より多いのもののidを取得する時rails6では

User.where("age>20").limit(1).plunk(:id).first が

User.where("age>20").limit(1).pick(:id) となる

 

・create_or_find_byメソッド

レコードがなければ作成を行い、レコードがあれば作成しないメソッドに従来は find_or_create_by メソッドを使っていたが、 find_or_create_by ではSQLのSELECTからINSERTを行う際に時間差があるため、その間にSELECTで取得したレコードが古くなってしまう問題があった

create_or_find_byメソッドではINSERTを行い、ユニーク制約のエラーが発生した場合は、SELECTでレコードを取得する

create_or_find_byの注意点としてメソッドを使用する際には、あらかじめユニーク制約を設定する必要があること、レコードの作成よりも参照が多い場合は処理自体が遅くなる可能性があること、また、レコードが作成できない場合の例外がある

 

 

・insert_allメソッド

複数件のレコードを一括でINSERTできるメソッド

今まではBULK INSERTという方法を使っていた

 

他にもまだまだアップデートした点はある様

変更点の多さから今回は特に大きなアップデートだったとわかる

Railsはどんどん便利になっていくと感じた



 

AltJSについて

AltjsとはJavascriptの弱点(文法の複雑さ、動的型付け)を補うために、Javascriptコンパイルして代替される言語のこと

Altjsのメリット...Javascriptよりコードが読みやすい、変更しやすく再利用しやすい(保守性が高い)

デメリット...Javascriptコンパイルする手間がある、エラーが発生した時のjavascriptがAltjsのどこに相当するのか調べないといけない

 

<主なAltjsの例>

・Typescript

中〜大規模開発の際jsに代替されるaltjs。オブジェクト指向AngularJSで採用。javascriptとの互換性を持つ。javascriptとの大きな違いはjsが動的型付けなのに対しtypescriptは静的型付けであること。静的型付けであることにより大規模開発の際、変数の型によるバグを防ぐことでより堅牢なアプリケーション作成を可能にする。

・CoffeScript

文法がRubyPythonっぽくてコード量が少なくて済み、コンパイル後のjsも綺麗。Railsで標準的にサポートされている(rails newで自動的に生成される、$rails new --skip-coffeeで作成されない)、Asset Pipelineという機能によって、自動でコンパイルされる。関数スコープに従って適切な位置で変数の自動生成される。

・PureScript

javascriptオブジェクト指向と異なり関数型言語Haskellっぽい。mapやfilter、reduceなどのメソッドをもつ。

・Elm

わりかし新しい言語。2019年わざわざ学ばなくていいプログラミング言語1位。jsの他html,cssコンパイルされる。Haskellベースで協力な静的型付け言語で純粋関数型言語。Reactなどと同じでフレームワークとなるがJSフレームワークに比べて描画が速い、SPA(SinglePageApplication)に向いてる。型検査されるためコンパイル後に壊れない

 

他にもDartHaxe、JSXとかがあるっぽい

 

 

 

 

Barba.js触ってみた

pjaxの流れでBarba.js触ってみた

ざっくり言うとBarba.jsとはpjaxの簡単バージョン

はっきり言ってそこまで差わかってない

 

メリット...ページ遷移が早くて楽しい、アニメーション楽しい
デメリット...読み込み時のscriptが動かない、実態は最初に閲覧したページのため、相対パスがずれる、meta情報が変わらない、学習コスト高め
けどBarbaの方がpjaxより学習コスト低い


$(function(){
$.pjax({
areas: ['#container','side'],
link : 'a:not([target])',
update: {head: 'base, meta'},
wait : 500
});
});
areas...更新する範囲の指定。複数ある場合はコンマ区切り
link...pjaxを適用させるリンクを設定
update...更新させたいものを指定できます。baseタグ、metaタグ、linkタグ、scriptタグを指定する事ができます。
wait...リンクをクリックしてからの遅延時間

goチャット概要

クライアントリクエストをwebsocketでサーバーに接続し、goroutine関数でハンドリングしてメッセージの送信を受信する
受信されたメッセージはchannel型の変数に送り、別のgoroutine関数でメッセージを拾ってそれをすべてのクライアントに送信する(このとき送信処理とbot処理を分ける)
別のモジュールに処理を切り分けることでロジックを明白にする

f:id:yusukeisizaki:20190621204912j:plain



pjax初心者

pjaxをちょっと触ったのでまとめて見ました

フロントやってた人に聞いた話じゃアメリカではajaxよりpjaxらしい

 

Pjax = pushState + Ajax  のjQeuryのプラグインのこと

pushStateとはHTML5から追加されたHistory APIのメソッドで、ざっくり言うと「履歴の変更」ができる。ブラウザの履歴情報をページ遷移せずに変更するメソッドのこと

history.pushState(state,title,url); のように使い

第1引数stateで履歴に関するオブジェクト

第2引数titleで履歴のタイトルを指定

第3引数urlで履歴のurlを指定絶対パス相対パスどちらでもOK

AjaxとはAsynchronous JavaScript + XMLのこと

ページ遷移をさせず(非同期処理で)コンテンツを書き換えられる、他の処理と同時並行で、サーバとやりとりができる、サクサク動くページの動きを再現できる

以上のことよりpjaxとは「非同期ページ遷移」の「履歴あり」のこと

 

 

<a class="pjaxLink" href="ルーティング"> ←遷移させるボタンとか

ここからhead要素に書く
<script src="/static/javascript/main.js"></script>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.pjax/1.9.6/jquery.pjax.js"></script>
<script src="pjax.min.js"></script>
<script src="/static/javascript/base.js"></script>

遷移元<section id="pjaxContent" class="pjax-test">に書くid class

(これだと変化させたい部分をsectionで挟む)


jsファイルで指定したid classを変化させる
url: 遷移先パス,
container : 遷移部分,
fragment : 遷移部分,
timeout : 時間
をjsに書く

 

<おまけ>ラクスルの価格表ページがpjaxらしい

某フリマサイトの検索まとめ(後編)

某フリマサイトのコピーをRailsにて作成した際にransackによる検索をする方法をまとめました

URL:https://github.com/yusuke-ishizaki/freemarket_sample_50b


Ransackによる条件検索


——————————————————
・必要なもの
Gem”ransack” gem”active hash”


—————————————————
・詳細検索作成手順
1. ransack 導入
2. コントローラー記述
3. フォーム制作
4. ActiveHash導入(gem,モデル) ←ここから
5. ActiveHash導入(アソシエーション)
6. フォーム作成2
↓詳細

————————————————

4.ActiveHash 導入

検索する際にセレクトボックスやチェックボックスの記述があるが、ここでデータベース内の値を引っ張ってきたい

このときにActiveHashを用いる

Activehashを用いる状況として

・基本的に’select option’使いたくない

・セレクト数が多くviewに記述したくないとき(ex.都道府県セレクト)

・テーブルを作るほどでもないセレクトメニュー(ex.メルカリのサイズ、状態など)

導入手順

gem 'active_hash'  →bundle install  rails s

・モデルの作成(ここにデータを記述)

$rails g model”コマンドを使わずに/app/model/~.rbを作成

→class モデル名(任意) < ActiveHash::Base

  self.data = [

   {id: 1, name: ’’}, {id: 2, name: ''}

  ]

end

データはハッシュでベタ打ち

今回は/app/models/size.rb status.rb

 

 

 

5.ActiveHash導入(アソシエーション)

Activehashに必要なアソシエーションを組んでいく

入力検索フォームで値を引っ張りたいモデル(Product) と activehashでデータを格納してるモデル(Size)  でアソシエーションを組みデータを引っ張れるようにする

新しく作ったactivehashモデルにはアソシエーションは書かず、値を引っ張る側にアソシエーション を記述する

/app/models/product.rb

class Product < ApplicationRecord

   extend ActiveHash::Associations::ActiveRecordExtensions

   belongs_to_active_hash :hash先モデル

end

 

 

 

6.フォーム作成2

フォームのセレクト欄とチェックボックスを作成していく

セレクトフォーム…= f.collection_select

チェックボックス…= f.collection_check_boxes

 

・セレクトフォーム

= f.collection_select(オブジェクト名, オブジェクトの配列, value属性の項目, テキストの項目 [, オプション])

 オブジェクト名属性名:フォームの対象モデルの中の該当する属性名

 オブジェクトの配列配列名:セレクトメニューの選択するのに使用するデータの配列。連想配列かオブジェクト

 value属性の項目valueになるカラム名:セレクトメニューで値として扱うカラムの名前※optionvalueの値になる

 テキストの項目表示されるカラム名:セレクトメニュー表示名として扱うカラム名

今回は”= f.collection_select :size_eq, Size.all, :id, :name, { include_blank: 'すべて'}, { class: "search-box__detail-search__form-group__input" }

[search.html.haml L27]

productviewの中なのにSize.allが使用できるのはクラスメソッドはどこからでも呼び出せるため

 

チェックボックス

= f.collection_check_boxes オブジェクト名, オブジェクトの配列, value属性の項目, テキストの項目 [, オプション] do |b|

  = b.check_box

       = b.text

今回は”= f.collection_check_boxes :status, Status.all, :name, :name, prompt: '--' do |b|

[search.html.haml L39]

某フリマサイトの検索まとめ(前編)

某フリマサイトのコピーをRailsにて作成した際にransackによる検索をする方法をまとめました

URL:https://github.com/yusuke-ishizaki/freemarket_sample_50b


Ransackによる条件検索


——————————————————
・必要なもの
Gem”ransack” gem”active hash”


—————————————————
・詳細検索作成手順
1. ransack 導入
2. コントローラー記述
3. フォーム制作
4. ActiveHash導入(gem,モデル)
5. ActiveHash導入(アソシエーション)
6. フォーム作成2
↓詳細

————————————————

1. Ransack 導入
gemfileに gem’ransack’記述
→bundle install
rails s

 


2.コントローラーに記述
検索対象コントローラーにsearchアクションを作成
今回は ’products controller’
→検索オブジェクト作成
@search = Product.ransack(params[:q])
・@search…検索オブジェクト、検索するということの定義、名前なんでも良き
・.ransack…Productのデータを検索するよーという命令メソッド
・params[:q]…検索結果パラメータ、公式より:qにするみたい
→検索オブジェクト結果作成
@products = @search.result
・@products…検索結果オブジェクト、結果の定義、こっちをviewに反映する、名前なんでも良き
・.result…resultメソッド、検索オブジェクトの検索結果を出力する
→まとめ
class ProductController < ApplicationController
def search
@search = Product.ransack(params[:q])
@products = @search.result
end
●[product_controller.rb L64]
<おまけ>distinct: trueや.to_a.uniqを使うことで重複を避けることができる
@search.result(distinct: true) @search.result.to_a.uniq

 

3.フォーム雛形作成
通常の入力・検索フォームではform_with, form_for, form_tag使う”search_form_for”を用いる
“= search_form_for 検索オブジェクト, url: 検索結果表示ページのpath do |f| “
検索オブジェクトにはcontrollerで定義したもの(今回は@search)を用いる
パスは url: で結果表示先を示す
|f| はform_with系と同様に f.label のように使う
今回は “= search_form_for @search, url: search_product_index_path do |f|”
●[search.html.haml L5]
<おまけ> “= search_form_for(@q, format: :pdf) do |f|” “= search_form_for(@q, format: :json) do |f|” とすることで形式をpdfやjsonに指定できる


キーワード検索フォーム ransack版
“= search_form_for 検索オブジェクト, url: 検索結果表示ページのpath do |f| “のネスト中に
“= f.search_field :カラム_cont, class:クラス名”
search_field…検索入力バーを作成する
カラム_cont…指定カラムに対してLIKE句検索(あいまい検索)を行う
今回は “= f.search_field :name_cont, class: "search-box__detail-search__form-group__input"
●[search.html.haml L15]
★今回name_contとした理由…controllerで@search=Product.ransack とProductモデルに検索をかけるよう指定しているので “nameカラム”に”_cont”しても正確にProduct.nameを検索する(Brand.nameなど他のモデルには手を出さない)
<おまけ>複数カラムあいまい検索…= f.search_field :カラム1_or_カラム2_or_カラム3_cont(orのとこandでもおっけい) 1にname、2にstatus、3にtextなど

 

検索結果表示

- @products.each do |product|

検索結果の表示には、controllerにて定義した検索結果オブジェクト@products

 

 

検索結果をソートさせたい

= sort_link(検索オブジェクト, :カラム, ‘ソートのラベル’, default_order: :desc)”

今回は”= sort_link(@search, :name, '名前順', default_order: :asc)”

[search.html.haml L6]

 

 

価格帯検索したい

= f.number_field :カラム_gteq, placeholder: 説明, class:クラス名”

= f.number_field :カラム_lteq, placeholder: 説明, class:クラス名”

_gteq で~以上の検索

    _lteq で~以下の検索

今回は

= f.number_field :price_gteq, placeholder: " Min", class: "search-box__detail-search__form-group__price-min search-box__detail-search__form-group__input””

= f.number_field :price_lteq, placeholder: " Max", class: "search-box__detail-search__form-group__price-max search-box__detail-search__form-group__input””

[search.html.haml L32]

 

 

 

—————————————————————

追記

今回使わなかったけどransackでできること

Predicate検索(カラム名と述語(Predicate)で検索する方法)

*_eq   equal(=)を使った検索

*_matches    LIKE検索

*_does_not_match    LIKE検索で除外されるもの

*_cont   LIKE検索(部分一致)

*_start   LIKE検索(前方一致)

*_end   LIKE検索(後方一致)

*_gt   より大きい(>)検索

*_gteq   以上(>=)検索

*_lt   より小さい(<)検索

*_lteq   以下(<=)検索

*_true  trueのものを検索

*_false   falseのものを検索

*_null    null(存在しない)ものを検索

*_present   present?メソッドに近い NULLでも空文字でもなければマッチ

*_blank      blank?メソッドに近い  NULLか空文字だったらマッチ

*_not_???   述語の前にnotをつけることで、否定が可能

*_???_all       末尾にallをつけることで、複数の値に対してANDで連結して検索

*_???_any 末尾にanyをつけることで、複数の値に対してORで連結して検索

 

 

= f.attribute_fields do |a|

    = a.attribute_select associations: [:アソシエーションしてるモデルのカラム]

でアソシエーションしてるモデルのカラムをセレクトに選ぶことができる

 

動的に追加されるフォームを作成する方法

/app/helpers/application_helper.rblink_to_add_fieldsメソッドを作成

    module ApplicationHelper

               def link_to_add_fields(name, f, type)

・フォームのあるhtml

= link_to_add_fields “クラス”, f, :カラム

javascriptで動かす