どうも、torihaziです
今日は最近開発している際に触れることの多い、"Cookie"について
調べてみました。
というのも あまりよく知らずに使っていたからです。
httpOnlyとか samesiteなんとかとか。
それぞれがなんのために必要かとかは辞書的な意味はちょこっと入っているけれど
実際に人が納得できるくらいに説明できると聞かれたら否なので
これを機に調べてみることにしました。
随時書き足すか他記事で更新します。
Webサイトが ユーザのブラウザに保存する小さなテキストファイルのこと
これによりwebサイトはユーザの情報を記憶し、次回訪問時にその保持した情報を使い回すことができる。
調べた感じ、よくあるものは次のとおり
Webサイトが情報を保存するということで、キャッシュとは何が違うのかと疑問が生じますが
その違いは下記のようです。
cookieはユーザの個人データを、キャッシュはWebページのコンテンツを保持する
例えばキャッシュは 画像などの静的リソースを保持し、次回読み込み時に使用して読み込みを高速化したりする
ために使われます。
ここが特に私が知っておくべき情報でした。
開発をしていて HttpOnly 、 samesiteとか色々設定できますよね。
それらについて調べてみると
Domain属性:Cookieが送信される対象ドメインを指定指定されたドメインとそのサブドメインのみがCookieにアクセス可能
Path属性:Cookieが有効となるサーバー上のパスを指定指定されたパスとそのサブパスのリクエスト時のみCookieが送信される
Expires/Max-Age属性:Cookieの有効期限を設定Expiresは特定の日時、Max-Ageは秒単位の期間を指定設定しないとそれはブラウザが立ち上がっている間のみ有効となるセッションクッキーとなる。
Secure属性:HTTPSプロトコルを使用している場合のみCookieが送信されるよう制限通信の暗号化を強制することでセキュリティを向上ただCookieの内容自体が暗号化されるわけではない。
HttpOnly属性:Cookieをhttps通信上のみで利用。JavaScriptのスクリプト(document.cookieなど)からのアクセスを禁止。
SameSite属性:クロスサイトリクエストによるCookieの送信を制御値として「Strict」、「Lax」、「None」を設定可能
調べたところ、分かったのは2つ
これは例えばRailsにおいてcookiesメソッドで設定した場合、responseヘッダに設定されるもの。
これがresponseヘッダにあるとブラウザはその値をCookieに保存してくれる。
しかし、cookiesメソッドで指定されるオプションによって保存してくれたりしなかったりする。
みなさん、こんにちはtorihaziです
今日は現在やっている個人開発において、タイトルのようにdeviseの扱いに少し詰まったので
次回似たようなことをやる時につまらないように書き残しておこうかと思って今書いてます
ちなみにRailsはAPIモード、deviseとdevise-token-auth使ってます。
deviseを使って新規登録を作る際、frontendからは emailとpasswordしか送らないけど
backend側で emailの@より前を切り取ってそれを最初はnameにして差し込んでしまおうということをします。
なんでこういうことをするかというと
んー、nameをわざわざ新規登録formからuserに入力させるのがダサいかなと思ったからです。
あと実務で作成しているアプリケーションがそのようにしていて、
確かにその方がUX?も良いだろうし、、、てな感じですね。
他の方法があれば教えてください。
DeviseTokenAuth::RegistrationsController を継承して新しくControllerを作成します。
その後に 下記メソッドをオーバーライドします。
def build_resource super email = params[:email] password = params[:password] name = email.split("@")[0] @resource.name = name @resource.password_confirmation = password end
devise-token-authの公式ドキュメントを参照すると、次のような記載があります。
devise_token_auth/docs/usage at master · lynndylanhurley/devise_token_auth · GitHub
Email registration. Requires email, password, password_confirmation, and confirm_success_url params (this last one can be omitted if you have set config.default_confirm_success_url in config/initializers/devise_token_auth.rb). A verification email will be sent to the email address provided. Upon clicking the link in the confirmation email, theAPI will redirect to the URL specified in confirm_success_url. Accepted params can be customized using the devise_parameter_sanitizer system.
(今思ったんですが、この必須とされているemail, passwordとか項目いじれないんですかね。)
email, password, password_confirmation, (confirm_sucess_urlはconfigで設定するので無視)が必須らしいですが、
frontendからはemailとpasswordのformしか用意したくないです。
確認用passwordとかもfrontで表示非表示ボタン等用意すれば良いでしょ。
まぁそんな状況だったので今回backend側でやむなしでこうしました。
※ ちなみに@resourceとするのは公式で肝心の作成対象(今回であればUser)が@としているからです。
resourceではないのでご注意を。自分は最初それで少し詰まりました。
また
def create super do |resource| updateの処理 endend
みたいなやり方もありそうですが、今回自分がモデルのvalidatesに nameを必須にするようなことを書いていたため
このようにせざるを得ませんでした。
他にいい方法あれば教えてください。
2月も終わり、2025年も1/6が終わりました。
花粉が飛び散らかして、やかましいです。
新生活も始まる人も増えてきて、やたらと忙しくなりつつあるのではないでしょうか。
私も前職を辞めて Web系のエンジニアになってから半年も過ぎて
職場にも多少慣れてきたところで、早7ヶ月です。
ではいつも通り振り返っていきましょう
こういうのはまとめて最初は一言がいいのでしょうが、箇条書きで。
ですかね。
個人的には backendにも触れるようになったということがかなりでかかったです
もちろんまだそんなバリバリというわけではないですが、
小タスクを順調に消化していけてるなと感じています。
Rails全く触ってなくて、忘れそうだー、と少し前まで嘆いていたのが
今は改善されつつあり、最近ではleetcodeをrubyで解けるようにもなってきました。
入社時点に比べて着実にレベルは上がっているなと感じます。
ではいつもの如く、メンタル、frontback infraと分けてやっていきます。
よくいう言葉ですね。打席には立つべき。
自分もそう思います。
頭だけでの計算とかで済まさずに実地での経験の方がよく身につくからとかいうものです。
そのため機会が与えられているなら積極的に立たせてもらうべきです。
そしてなんとしてでもやり切ること。
これはどの仕事においても言えることですね。
「こんなん無理や!」と投げ出したくなる時もあるかと思います。
そしたら投げ出してみるといいです。多分一気に信頼無くなります。
そしたら仕事振られなくなります。
ただそうする前に他の人を頼るべきです。そしたら何かしら手を差し伸べてくれるはずです。
ただその時にもベタベタとすがりつくのは辞めましょう。
「どこどこのここがどうわからない」というふうに聞き手がわかるように努めましょう。
それができればいずれ自分のためにもなります。
兎にも角にも全力でやりましょう。
それができないなら次のように考えを改めるべきです。
よくアスリートとかそういった類の人が
「今日ここまでこれたのは支えてくれたみなさんのおかげです」とか言うじゃないですか。
自分はそれを聞いて、「いや自分の努力してきた結果でしょ、何聞こえのいいこと言っとるんじゃい」とか思う
ひねくれクソガキだったのですが最近そう思わなくなりました。
「なるほど、確かにその通り」だと。
人間、自分だけにベクトルが向いてると、こういう辛い努力とかしている時に
投げ出しやすくなります。少なくとも自分はそうです。
「別に良くね、やんなくても」と言ったように。
ただこの時にその行動をする目的、意義というものを自分から他のものに向けると
継続できる、やり切れることが多いです。
「あの人の期待に応えるために」とか「彼女のために」とか
「せっかくこの未経験に仕事くれてるのだから」とか。
「ありがたいことに仕事もらえてるんだからなんとしてでも」みたいな。
なんでもいいです。自分ではない他のものにベクトルを向けてみてください。
そうしたら多分やり切れると思います。
自分に向けたくなっても必死に他のものに向け続けることです。
と、最近うまくいっていそうな人、そうでなさそうな人を見ていて思いました。
多分そうでなさそうな人は感謝してないんだろうなと。
それでもそういうふうになる人はんー、まぁ頑張ってください笑
自分もしてしまっていたことがあったと思うのでこれを機に気をつけようかと思います。
これ意外と実装するの難儀だったのですが、公式に書いてありました。
ShadcnのDialogにおいて黒背景クリックでDialogを閉じないようにするためにはDialogContentに次を設定すればいける。radix-uiに書いてあった。 onInteractOutside={(event) => { event.preventDefault(); }}
これをするとならなくなります。
今まで渡したonOpenChangeのfalseの時の挙動で制御しようとしていましたが、
これだけでいけるっぽいです。
最初、frontendのテストって何がいるのかな、というところから始まりました。
そしたらHCのCTOに聞いて秒で解決したので、いただいたドキュメントをもとに読み進めていくと
現在のfrontendテスト界隈においてこのjestとreact-testing-libraryはこれがほぼ標準だということです。
テストをするならこいつらでしょ、というレベルです。
そもそもfrontendにおいて何をテストするのか、したいのかということを理解すると
この子達の必要性もスッと入ってくると思います。
自分はえ、rspectみたいに1つだけじゃダメなのとか思っていた人間だったので。
で、frontendで何をテストするのかというと、主に次の通りだと思います。
1つ目に関してはわかると思います。
問題は2つ目ですね。描画するにもボタン押したら何かが開くとかそういうことをテストする必要がありますね。
となるとその描画している要素を取得する必要がありそうです。バニラjsのgetelementbyidみたいに。
でこの時に
総じて「結果の判定」だけであればjestの管轄なのですが
その結果を判定するために必要な要素の取得や実際にrenderingするとなるとjestでは賄いきれません。
これは困ったということで、そこでreact-testing-libraryが出てくるわけです。
以上のことから frontendのテストでは一般的に "jestとreact-testing-library"が必要というわけです。
expectとかitとかrenderとかtoBeとかいろいろありますよね。
今使う段階になったら辞書的に少しづつ調べていくという感じで進めてます。
まだ消化しきれてないので来月くらいにはできるようになっているのではないでしょうか。
cssのpointer-events: autoとかnoneとか。
[CSS]pointer-eventsプロパティですごい便利に!クリックやホバーのターゲットになる要素を変更するテクニック | コリス
dialogをこれでもかといじり倒していた時に Dialogに設定されていたcssを紐解いて行って見つけました。
javascriptでないとできないようなことが、cssでもできるようになったっぽいです。
深掘りできてはいませんが使えはしそう。
まだあるけどキリがないので。
こいつのせいで初めてのbackendの中タスク mergeした後本番をバグらせました。
mergeしたら、ことごとく undefind methodnil classみたいな。
社内リリースだったからまだ良かったものの。
焦り散らかしました。
typescriptだとほぼほぼ回避できそうな事象だと思うので
改めて型付きの言語はさすがやと思いました。
結局自分が実装したところにことごとく「ボッチ演算子&」をつけると機能したので
何はともあれよかったです。
「nilの可能性があるものに関しては &をつけてエラーを回避しましょう」
ということを身をもって知りました。
今まで「なんでこれつける必要があんの」とか舐めてたツケが来ました。
二度とやりません。
業務に関してはこのくらいですかね。
特段かけることはないですね。ドメインに関わることもあるのでこのくらいで。
こいつはleetcode専用メソッドじゃないですかね。
rubyで最近leetcode進めていく中で見つけたメソッドです。
どういうものかというと配列に作用させるメソッドで、配列内の要素をカウントして、
その要素をkeyに、その要素の出現回数をvalueという形にしたhashを返してくれます。
問題はその出現回数が多い順に上からkこ取り出してその要素を配列として返せということだったので
そこからガチャガチャやりましたが、知っていると知らないとでは差が歴然でした。
こいつもleetcodeから取り入れた知識。
sort_byです。hashに作用させるとそのkeyとvalueを配列にして、valueをsortし、
各配列を1つの配列に閉じ込めて返してくれます。
こいつも知ってたら便利でした。
今月は特になしです。無念
ということで7ヶ月目の振り返りでした。
qiitaの記事も書いているし、ブログの記事も書いているし、
xのツイートも続けているし、
いい感じに続けていけてるのではないでしょうか。
一応今1年目ですが、時間なんてあっという間に過ぎるので
これからも頑張っていきたいです。
3月の目標としては
あとは実務を着実にこなしていこうかと思います。
ということで頑張りましょう。
現場からは以上です
昨日に引き続き、今度は残りの中級3つやろう。
Given an array of strings strs, group the anagrams together. You can return the answer in any order.
文字列の配列が与えられる。それらの中でアナグラムであるもの同士をグルーピングして配列として返せ。
なお順不同である。
# @param {String[]} strs# @return {String[][]}def group_anagrams(strs) hash = {} strs.each do |str| key = str.chars.sort hash[key] ||= [] hash[key] = hash[key] + [str] end hash.valuesend
このsortしたやつをkeyにするやつね。
こういうのはまぁ慣れてきた。
valuesにすることでhashのvalueをそれぞれ配列で取り出して、最後それらを配列で閉じてくれるやつも
この前知った。
ただこういうのもあった。
# @param {String[]} strs# @return {String[][]}def group_anagrams(strs) map1 = {} strs.each do |str| s = str.bytes.sort map1[s] ||= [] map1[s] << str end map1.valuesend
bytesにすると何がええんやろ。
Given an integer array nums and an integer k, return the kmost frequent elements. You may return the answer in any order.
数字の配列と整数kが与えられる。最も出現する要素を上からkこ特定し、配列として返せ。
なお順不同。
# @param {Integer[]} nums# @param {Integer} k# @return {Integer[]}def top_k_frequent(nums, k) nums.tally.sort_by {|_, v| v}.last(k).map {|array| array[0]}end
これは前やったtallyの印象が強すぎて覚えてた。
あとは要素をkeyにしてやるやり方だけど結局tallyを自前でやってるってだけ。
def top_k_frequent(nums, k) # nums.tally.sort_by {|_, v| v}.last(k).map {|array| array[0]} hash = Hash.new(0) nums.each do |num| hash[num] += 1 end hash.sort_by {|_, v| v}.last(k).map {|e| e.first}end
次の問題は課金しないとダメだったのでスルー。
ちょうどいいからこれで終わりにしよう。
よーやった。以上。
ついに前回でNeetCodeのRoadMapの最初が全て終わったので
今日はその問題を解き直してみることにする。
今日は初級全てにしよう。
Given an integer array nums, return true if anyvalue appears more than once in the array, otherwise return false.
数字の配列が与えられるので要素に重複があればtrueを、それ以外はfalseを返せ
def contains_duplicate(nums) nums.sort.uniq != nums.sortend
これも正解。ただ遅かったので、別のないか思い出す。
# @param {Integer[]} nums# @return {Boolean}def contains_duplicate(nums) hash = {} nums.each do |num| return true if hash[num] hash[num] ||= true end falseend
これでもまだ遅い。
あ、そうだこれだ。
def contains_duplicate(nums) nums.length != nums.uniq.length end
次。
Given two strings s and t, return true if the two strings are anagrams of each other, otherwise return false.
文字列s,tが与えられる。一方が片方のアナグラムである時trueを、そうでない時はfalseを返せ
文字列にcharsすると文字の配列として返してくれる。覚えててよかった。
def is_anagram(s, t) s.chars.sort == t.chars.sortend
これでも遅いのか。
そういえばこれもあったらしい。また忘れてる。
def is_anagram(s, t) return false if s.length != t.length s.chars.tally == t.chars.tallyend
次。
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.You may assume that each input would have exactly one solution, and you may not use the same element twice.You can return the answer in any order.
数字の配列とターゲットとなる数字が与えられる。
配列内の隣り合う2つの数字を足してターゲットの数字と等しくなる時、その2つの数字の配列内でのindexを配列にして返せ。
なお返す場合は順不同。
# @param {Integer[]} nums# @param {Integer} target# @return {Integer[]}def two_sum(nums, target) nums.each_with_index do |num, i| ((i + 1)...nums.length).each do |j| return [i , j] if target == num + nums[j] end end falseend
最強に遅い。
そういえば補数使うやり方あった。
# @param {Integer[]} nums# @param {Integer} target# @return {Integer[]}def two_sum(nums, target) hash = {} nums.each_with_index do |num, index| complement = target - num return [index, hash[complement]] if hash.has_key?(complement) hash[num] = index endend
よーこんなの思いつく。
意外と頭使う。
頭が疲れた。
まだまだや。
さて今日もやっていきますか。
neetcode生活、今日で最初のroadmap最終問題です。
sortされていない整数からなる配列が与えられる。
その配列の要素のうち、連続している数字があればその長さを返せ。
ただし、O(n)の計算量で済ませること。
案外簡単そうかもしれないので頑張っていこう。
def longest_consecutive(nums) return 0 if nums.empty? nums_set = Set.new(nums) max_length = 0 nums_set.each do |num| unless nums_set.include?(num - 1) current_length = 1 current_num = num while nums_set.include?(current_num + 1) current_num += 1 current_length += 1 end max_length = [max_length, current_length].max end end max_lengthend
num - 1を持つような数字を先頭にするという考えがどうしても思いつかなかった。
まずい。
復習というか解法の暗記みたいになっちゃうけど良いのだろうか。
他の回答も見たが似たようなことをやっていた。
随分ご無沙汰です。
なかなか続きません。
難しいからですかね。
今回の敵も強そうだ。
9x9マスのボードに数字が並べられている。
下記の3つのルールを満たしていた場合trueを返す- 全ての列に1~9の数字が入る- 全ての行に1~9の数字が入る-3x3のマスに1~9の数字が入る
少し読み違えていた。
実際にsudokuを解くのかと思っていたら、inputとして与えられた時点での盤面の妥当性を判断するだけで良いみたい。
途中まで
# @param {Character[][]} board# @return {Boolean}def is_valid_sudoku(board) rows = Array.new(9) { Set.new } cols = Array.new(9) { Set.new } boxes = Array.new(9) { Set.new } (0..9).each do |i| (0..9).each do |j| val = board[i][j] next if val == "." rows[i].include?(val) ? rows[i].add(val) : return false cols[j].include?(val) ? cols[j].add(val) : return false end endend
boxはどうやってやるんだろうか。
これは無理だ。
# @param {Character[][]} board# @return {Boolean}def is_valid_sudoku(board) rows = Array.new(9) { Set.new } cols = Array.new(9) { Set.new } boxes = Array.new(9) { Set.new } (0...9).each do |i| (0...9).each do |j| val = board[i][j] next if val == "." rows[i].include?(val) ? (return false) : rows[i].add(val) cols[j].include?(val) ? (return false) : cols[j].add(val) box_index = ( i / 3) * 3 + ( j / 3 ) boxes[box_index].include?(val) ? (return false) : boxes[box_index].add(val) end end trueend
今回得た教訓。
あとbox_indexのカラクリに気づけるか否か。
こっちの書き方の方がスマートかもしれない。
# @param {Character[][]} board# @return {Boolean}def is_valid_sudoku(board) rows = Array.new(9) {[]} cols = Array.new(9) {[]} boxes = Array.new(9) {[]} (0...9).each do |row| (0...9).each do |col| c_num = board[row][col] next if c_num == "." bi = (row/3)*3 + (col/3) if(rows[row].include?(c_num) || cols[col].include?(c_num) || boxes[bi].include?(c_num) ) return false end rows[row] << c_num cols[col] << c_num boxes[bi] << c_num end end trueend
あとrubyはメソッドの最後の評価した値が戻り値になるのでreturnと書かなくても良いていう
この風潮。未だ慣れん。
解けない問題が増えてきた。
んー悩みどころ。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。