コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

MySQL5.7のTEXT型とBLOB型にはデフォルト値を設定できない

基本的にはdefaultを設定したい衝動に駆られるができないというただのメモ

環境

$ mysql --version
mysql  Ver 14.14 Distrib 5.7.17, for osx10.12 (x86_64) using  EditLine wrapper

どういうことか

何故かぐらいは調べようと思ったのだが短い時間では特段それっぽいものは見つからないので、ドキュメントに書かれている

BLOB および TEXT カラムにはデフォルト値を割り当てられません。

が全てなのかもしれない…

参考リンク

Railsのrequest.domainはデフォルトの場合、セカンドレベルドメイン相当まで

domainって書かれているのでサブドメインもまるっとひっくるめてもってくるのかと思いきやそうではなかったのでメモ

環境

rails (5.2.0)
  actionpack (= 5.2.0)

実装

request.domainを深掘りすると以下のコードに突き当たる

# /actionpack-5.2.0/lib/action_dispatch/http/url.rb
def extract_domain_from(host, tld_length)
  host.split(".").last(1 + tld_length).join(".")
end

ホスト名に対してトップレベルドメイン長さ(tld_length)分だけ取得して抽出する。

で引数に使われている数値は同ファイル内で定義されていて

#  /actionpack-5.2.0/lib/action_dispatch/http/url.rb
mattr_accessor :tld_length, default: 1

ってことなので基本はセカンドレベルドメイン相当しか取得ができない。

ちなみに host は以下の内容で抽出される

def raw_host_with_port
  if forwarded = x_forwarded_host.presence
    forwarded.split(/,\s?/).last
  else
    get_header("HTTP_HOST") || "#{server_name || server_addr}:#{get_header('SERVER_PORT')}"
  end
end

参考URL

シンプルにするということ

こんなツイートがあった

超絶機械翻訳で見た感じ、不必要な機能を削る、みたいな話ですね。

きのこ本にもあるんですけど、「間違って使うことを困難に」という話があって、間違えようのないインターフェイスを作れば、誤った使い方はされなくなるという話で、これはつきつめると、シンプルに一つのやりたいことに対して一つの機能を実装するということだなと思っています。

これは設計、コーディング等々いろいろつかえる思考法で、できるだけシンプルにするとモジュール化されまくるので使い勝手がとてもよろしくなるので大事にしていきたい考え方だと思って雑記として。

関連リンク

フルスタックと枯れた知識の水平思考

ただの日記です。

忙殺されていた仕事も落ち着きの様相を見せ、そろそろRuby以外のカテゴリのこともちゃんと取り組んで行きたいなと思いながら身体を通常生活に戻すことにパワーを割いてしまっている日々です。(なのでちょっと更新時間の次元が歪んでいます…)

コードを書き、仕様書も作り、誰かの話を噛み砕いて形にする、しかもフルスタックエンジニアの振る舞いを要求されることがおおいので、携わる知識のアップデートは結構アンテナ高くいないとすぐに取り残されてしまいます。

そんな感じなので一番大切にしているのは、どの事柄にでもつかえるコアな部分の考え方だと思っています。

具体的には設計論や、使われている技術がどう意図で培われてきたのかというバックグラウウンド、どういう仕組で動いているかなどです。

車輪の再発明をして無駄に時間を過ごしたくないというのもありますが

  • 車輪はいかにして生まれたか
  • 車輪はどういう仕組で動いているか

みたいなことを知ることにより車輪とはまた違うものを開発するときにスライドしてつかえるものがあるのではないかと思っています。

なので枯れた知識の水平思考という考え方を(原典とはちょっと違う確度ですが)大事にしています。

もっとジャンル問わずいろいろと知識を付けていって、ここにアウトプットできればと思う今日このごろでした。

関連リンク

リダイレクト時のHTTPステータスコードの使い分けの昨今

ただしく使うべきコードとは何が良いのかという話

結論

  • 「恒久的なリダイレクト」は301
  • 「一時的なリダイレクト」は302

というのがベターの様子

それぞれのリダイレクトの選択の意味

特段、どれがいいとか悪いとかはあまりない。一番懸念されるのは各種検索エンジンの読み取られ方である。

Googleの昨今の見解では

しかし現在の Google は 301 と 302 のどちらであっても永続的な URL の移転として処理してくれます。 ゲイリーによれば、どちらを使うべきだと Google から勧めることはないとのことでした。 自分にとって適切だと思う方を使って構いません。

とのことなので、普通に利便性を考えて使い分ければ問題なさそう。

参考URL

Rails で has_one の関係を作るとレコードの状態も has_oneを維持しようとする

has_oneにするとちゃんと維持しようとするんだと関心したのでメモ

環境

rails (5.1.6)

以下のようなモデルがあるとする

# == Schema Information
#
# Table name: users
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)      default(""), not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class User < ApplicationRecord
  has_one :profile
end
# == Schema Information
#
# Table name: profiles
#
#  id         :bigint(8)        not null, primary key
#  user_id    :bigint(8)
#  birthday   :datetime         not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Profile < ApplicationRecord
  belongs_to :user , optional: true

end

こんな感じで変数としてcreateして

user = User.create(name:"test1")
   (0.4ms)  SET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.2ms)  BEGIN
  SQL (0.3ms)  INSERT INTO `users` (`name`, `created_at`, `updated_at`) VALUES ('test1', '2018-07-06 13:26:56', '2018-07-06 13:26:56')
   (0.7ms)  COMMIT
=> #<User id: 1, name: "test1", created_at: "2018-07-06 13:26:56", updated_at: "2018-07-06 13:26:56">

profile1 = Profile.create(birthday:Time.new(1990,1,10))
   (0.2ms)  BEGIN
  SQL (0.3ms)  INSERT INTO `profiles` (`birthday`, `created_at`, `updated_at`) VALUES ('1990-01-09 15:00:00', '2018-07-06 13:27:01', '2018-07-06 13:27:01')
   (1.2ms)  COMMIT
=> #<Profile id: 1, user_id: nil, birthday: "1990-01-09 15:00:00", created_at: "2018-07-06 13:27:01", updated_at: "2018-07-06 13:27:01">

代入すると入る

user.profile = profile1
  Profile Load (1.1ms)  SELECT  `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 1 LIMIT 1
   (0.2ms)  BEGIN
  SQL (2.0ms)  UPDATE `profiles` SET `user_id` = 1, `updated_at` = '2018-07-06 13:27:07' WHERE `profiles`.`id` = 1
   (0.3ms)  COMMIT
=> #<Profile id: 1, user_id: 1, birthday: "1990-01-09 15:00:00", created_at: "2018-07-06 13:27:01", updated_at: "2018-07-06 13:27:07">

ここまでは普通の話なんですが 他の値を代入すると、ちゃんとIDのかき消し処理をする

profile2 = Profile.create(birthday:Time.new(1989,1,10))
   (0.2ms)  BEGIN
  SQL (2.0ms)  INSERT INTO `profiles` (`birthday`, `created_at`, `updated_at`) VALUES ('1989-01-09 15:00:00', '2018-07-06 13:28:36', '2018-07-06 13:28:36')
   (1.9ms)  COMMIT
=> #<Profile id: 2, user_id: nil, birthday: "1989-01-09 15:00:00", created_at: "2018-07-06 13:28:36", updated_at: "2018-07-06 13:28:36">

user.profile = profile2
   (0.3ms)  BEGIN
  SQL (0.6ms)  UPDATE `profiles` SET `user_id` = NULL, `updated_at` = '2018-07-06 13:28:46' WHERE `profiles`.`id` = 1
  SQL (0.4ms)  UPDATE `profiles` SET `user_id` = 1, `updated_at` = '2018-07-06 13:28:46' WHERE `profiles`.`id` = 2
   (0.4ms)  COMMIT
=> #<Profile id: 2, user_id: 1, birthday: "1989-01-09 15:00:00", created_at: "2018-07-06 13:28:36", updated_at: "2018-07-06 13:28:46">

ただし手動で入れるとそうはならないので注意

profile3 = Profile.create(user_id:user.id,birthday:Time.new(1989,1,10))
   (0.3ms)  BEGIN
  SQL (0.5ms)  INSERT INTO `profiles` (`user_id`, `birthday`, `created_at`, `updated_at`) VALUES (1, '1989-01-09 15:00:00', '2018-07-06 13:29:39', '2018-07-06 13:29:39')
   (1.0ms)  COMMIT
=> #<Profile id: 3, user_id: 1, birthday: "1989-01-09 15:00:00", created_at: "2018-07-06 13:29:39", updated_at: "2018-07-06 13:29:39">

Profile.where(user_id:user.id).size
   (0.6ms)  SELECT COUNT(*) FROM `profiles` WHERE `profiles`.`user_id` = 1
=> 2

Modelを使った実装でカラム名を探すのに困ることが減るgem、annotate

表現モデルによってはどうしても長いカラム名を付けてしまったり、普段使い慣れないtypoしやすい英単語名をつけることがあると思います。

その際に手助けになるのがgem annotate です。

環境

rails (5.1.6)
annotate (2.7.4)

どういうものか

Modelのクラスにそのモデルのカラム名などの情報をファイル上部にコメント書きしてくれます。

例えば、以下のようなmigrationファイルでmigrateするとします。

class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.string :name, null: false, default: ""

      t.timestamps
    end
  end
end

このテーブルが作られた状態でコマンドを打つと以下のように結果が返ってきて

$ bundle exec annotate
Annotated (3): app/models/user.rb, test/models/user_test.rb, test/fixtures/users.yml

Modelクラスにカラムの情報がコメント記載されます

# == Schema Information
#
# Table name: users
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)      default(""), not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class User < ApplicationRecord
end

これでいちいちDBを見たりしなくてもカラム名がわかって、コード書くときもコメントからコピペをすればタイポなどを防ぐことができるので、多方面の重宝する。

余談

手動でmigrationファイルやモデルを作った時にRailsの規則に則ってないとコメントが正しく書き込まれないのでファイル名のタイポやクラス名の間違いに気づきやすいという副次的効果がある

個人的にはRailsアプリケーションには絶対いれたいgemの一つです。

関連リンク