- 投稿日:2019-11-27T23:42:14+09:00
1-100までのカードをn-1枚置きに裏返す(Ruby)
1-100までの数字が書かれたカードが裏返しで横に並んでいます。(1, 2, 3, 4, 5... 99, 100)
①初めは2番目のカードから1枚置きにカードを裏返して行きます。
②次に3番目のカードから2枚置きにカードを裏返して行きます。
③次に4番目のカードから3枚置きにカードを裏返して行きます。
・
・
・
このようにn番目のカードからn-1枚置きにカードを裏返していって、これ以上カードの向きが変わらなくなるまで続けます。その時に裏返っているカードは何番かを調べていきます。
考え方
カードを左から順に裏返す処理を書いていきます。カードが表か裏かはTrue(表), またはFalse(裏)で表すことが出来ます。
まずはカードを100枚用意します。
qiita.rbn = 100 cards = Array.new(n, false)配列はArray.newで作成することが出来ます。
また、その時に第2引数を指定すると、新しい配列をそのオブジェクトで埋めます。
ここでは100枚全てfalse(裏)にして配列を作成しました。次にカードを裏返して行きます。
qiita.rb(2..n).each do |i| j = i - 1 while j < cards.length do cards[j] = !cards[j] j += i end end初めは2番目のカードから裏返していくので、(2..n)として2番目のカードから順番に処理をしています。
また、n-1枚置きにカードを裏返すために、jにn−1の値を格納します。
そうしたら、whileのループの中で、n-1枚置きにカードを裏返す処理を行います。最後に裏返しのカードの番号を表示します。
qiita.rbno = 1 cards.each do |i| puts no if !i no += 1 end初めのカードから順番に、false(裏)だったらその番号(no)をputsしています。
答え
qiita.rb1 4 9 16 25 36 49 64 81 100ちなみに
カードの番号とその裏表の状態を同時にハッシュで保持出来るともっと簡単に記述出来るかもしれないと思ったり。。。
qiita.rbn = 100 cards = Array.new(n, false) (2..n).each do |i| j = i - 1 while j < cards.length do cards[j] = !cards[j] j += i end end no = 1 cards.each do |i| puts no if !i no += 1 end
- 投稿日:2019-11-27T23:37:55+09:00
IBM Watson "Personality Insights" を利用した性格分析(夏目漱石「こころ」を例に)
IBM Watson とは
日々の業務から生まれるデータをナレッジに変え、業務プロセスに組み込んで活用することで、プロセスの効率化や高付加価値化を実現できます。たとえば、人間には読みきれないような大量のデータの中からすばやく知見や洞察を見出したり、顧客に対してさまざまな場面で一貫した質の高い応対をすることを可能にします。また、情報と知見に基づく意思決定を支援したり、ビジネスのさまざまな業務や場面であなたをサポートします。
(引用 - IBM Watsonとは? - Japan)
https://www.ibm.com/watson/jp-ja/what-is-watson.html
- クレジットカードを登録せずに利用可能
Personality Insights とは
- IBM Watsonが提供しているAPIの1つ。
- メール・ツイート・メッセージを分析して、個人のパーソナリティ特性を推論
パーソナリティ特性
ビッグ・ファイブ(big5)
- 個人が世界とどのように関与しているかを示す
- 協調性、誠実性、外向性、情緒不安定性、開放性の5つディメンションを含む。
- 各ディメンションには、そのディメンションに従って個人をさらに特徴付ける 6 つのファセットがある。ニーズ(needs)
- 個人の共感を呼ぶ可能性がある商品の側面を説明するもの。
- 興奮、調和、好奇心、理想、親近感、自己表現、自由、愛、実用性、安定性、挑戦、構造の12個の特徴のニーズがある。価値(value)
- 個人の意思決定に影響を与える動機を説明するもの。
- 自己超越/人助け、不変/伝統、快楽主義/人生を楽しむ、自己高揚/成功、変化に対して抵抗感を持たない/興奮 の5つを含む上記内容は、製品情報 - IBM Watson Personality Insightsに詳細があります。
今回挑戦したこと
- htmlファイルをPersonality Insightsで分析し、その著者の性格を分析する
- CURLコマンドで、叩く
- 分析結果(json)をデスクトップに出力・保存する
- 保存した分析結果を、Rubyを使ってハッシュ化
- ハッシュ化した結果を整理
実行環境
項目 PC MacBook Air ブラウザ Google Chrome 前提条件
- IBM Cloud のアカウントを持っている
今回の分析対象とする文章
青空文庫で公開されているページ(html)を、デスクトップに保存する。
保存する名前:kokoro.html
デスクトップに移動し、デスクトップにあるファイルを確認cd desktop ls上記コマンド実行結果kokoro.html実際にやってみよう
下記のコマンドを実行する。
Watosonに分析させるコマンドcurl -X POST -u "apikey:YOUR_IBM_WATSON_API_KEY" \ --header "Content-Type: text/plain;charset=utf-8" \ --header "Accept: application/json" \ --data-binary @/User/YOUR_USER_NAME/Desktop/kokoro.html \ "https://gateway.watsonplatform.net/personality-insights/api/v3/profile?version=2017-10-13"注
YOUR_IBM_WATSON_API_KEY
にはAPIキーを
YOUR_USER_NAME
にはユーザー名を
それぞれ代入する。分析結果
デスクトップに
kokoro.json
が保存されていることを確認する。このjsonファイルには、パーソナリティーモデルに基づいた分析結果が格納される。
commandcd desktop ls出力結果kokoro.jsonkokoro.json{"word_count":20314,"processed_language":"en","personality":[{"trait_id":"big5_openness","name":"Openness","category":"personality","percentile":0.4190447483892409,"significant":true,"children":[{"trait_id":"facet_adventurousness","name":"Adventurousness","category":"personality","percentile":0.32241762665507223,"significant":true},{"trait_id":"facet_artistic_interests","name":"Artistic interests","category":"personality","percentile":0.5521516749265605,"significant":true},{"trait_id":"facet_emotionality","name":"Emotionality","category":"personality","percentile":0.5132346262424734,"significant":true},{"trait_id":"facet_imagination","name":"Imagination","category":"personality","percentile":0.607365647158204,"significant":true},{"trait_id":"facet_intellect","name":"Intellect","category":"personality","percentile":0.7578837755541521,"significant":true},{"trait_id":"facet_liberalism","name":"Authority-challenging","category":"personality","percentile":0.8196241048763219,"significant":true}]},{"trait_id":"big5_conscientiousness","name":"Conscientiousness","category":"personality","percentile":0.22525820846421102,"significant":true,"children":[{"trait_id":"facet_achievement_striving","name":"Achievement striving","category":"personality","percentile":0.24103760626726628,"significant":true},{"trait_id":"facet_cautiousness","name":"Cautiousness","category":"personality","percentile":0.3967189883611717,"significant":true},{"trait_id":"facet_dutifulness","name":"Dutifulness","category":"personality","percentile":0.24845542781829882,"significant":true},{"trait_id":"facet_orderliness","name":"Orderliness","category":"personality","percentile":0.207879302126662,"significant":true},{"trait_id":"facet_self_discipline","name":"Self-discipline","category":"personality","percentile":0.19535876642618683,"significant":true},{"trait_id":"facet_self_efficacy","name":"Self-efficacy","category":"personality","percentile":0.21390998519773624,"significant":true}]},{"trait_id":"big5_extraversion","name":"Extraversion","category":"personality","percentile":0.34971430412544213,"significant":true,"children":[{"trait_id":"facet_activity_level","name":"Activity level","category":"personality","percentile":0.33897831044712423,"significant":true},{"trait_id":"facet_assertiveness","name":"Assertiveness","category":"personality","percentile":0.11746700558582457,"significant":true},{"trait_id":"facet_cheerfulness","name":"Cheerfulness","category":"personality","percentile":0.22972256751949427,"significant":true},{"trait_id":"facet_excitement_seeking","name":"Excitement-seeking","category":"personality","percentile":0.2357839101981965,"significant":true},{"trait_id":"facet_friendliness","name":"Outgoing","category":"personality","percentile":0.29853824637994103,"significant":true},{"trait_id":"facet_gregariousness","name":"Gregariousness","category":"personality","percentile":0.3643146929286043,"significant":true}]},{"trait_id":"big5_agreeableness","name":"Agreeableness","category":"personality","percentile":0.27663077925440716,"significant":true,"children":[{"trait_id":"facet_altruism","name":"Altruism","category":"personality","percentile":0.4020555962581259,"significant":true},{"trait_id":"facet_cooperation","name":"Cooperation","category":"personality","percentile":0.3603843552650475,"significant":true},{"trait_id":"facet_modesty","name":"Modesty","category":"personality","percentile":0.582131278592358,"significant":true},{"trait_id":"facet_morality","name":"Uncompromising","category":"personality","percentile":0.34577537905073386,"significant":true},{"trait_id":"facet_sympathy","name":"Sympathy","category":"personality","percentile":0.608321787997034,"significant":true},{"trait_id":"facet_trust","name":"Trust","category":"personality","percentile":0.1107532137251554,"significant":true}]},{"trait_id":"big5_neuroticism","name":"Emotional range","category":"personality","percentile":0.7558550985505927,"significant":true,"children":[{"trait_id":"facet_anger","name":"Fiery","category":"personality","percentile":0.5983433110620369,"significant":true},{"trait_id":"facet_anxiety","name":"Prone to worry","category":"personality","percentile":0.7269479416509153,"significant":true},{"trait_id":"facet_depression","name":"Melancholy","category":"personality","percentile":0.8142313580352654,"significant":true},{"trait_id":"facet_immoderation","name":"Immoderation","category":"personality","percentile":0.5798042693808653,"significant":true},{"trait_id":"facet_self_consciousness","name":"Self-consciousness","category":"personality","percentile":0.7577882331656556,"significant":true},{"trait_id":"facet_vulnerability","name":"Susceptible to stress","category":"personality","percentile":0.7631343989629844,"significant":true}]}],"needs":[{"trait_id":"need_challenge","name":"Challenge","category":"needs","percentile":0.29712717312254844,"significant":true},{"trait_id":"need_closeness","name":"Closeness","category":"needs","percentile":0.33880584971327,"significant":true},{"trait_id":"need_curiosity","name":"Curiosity","category":"needs","percentile":0.7000224484452974,"significant":true},{"trait_id":"need_excitement","name":"Excitement","category":"needs","percentile":0.38269688677373603,"significant":true},{"trait_id":"need_harmony","name":"Harmony","category":"needs","percentile":0.2638918250639486,"significant":true},{"trait_id":"need_ideal","name":"Ideal","category":"needs","percentile":0.3202722066143936,"significant":true},{"trait_id":"need_liberty","name":"Liberty","category":"needs","percentile":0.44282382289912187,"significant":true},{"trait_id":"need_love","name":"Love","category":"needs","percentile":0.3958365238399758,"significant":true},{"trait_id":"need_practicality","name":"Practicality","category":"needs","percentile":0.8563266321622546,"significant":true},{"trait_id":"need_self_expression","name":"Self-expression","category":"needs","percentile":0.5737335986056481,"significant":true},{"trait_id":"need_stability","name":"Stability","category":"needs","percentile":0.22173366620030177,"significant":true},{"trait_id":"need_structure","name":"Structure","category":"needs","percentile":0.4504728693366197,"significant":true}],"values":[{"trait_id":"value_conservation","name":"Conservation","category":"values","percentile":0.18307614327169447,"significant":true},{"trait_id":"value_openness_to_change","name":"Openness to change","category":"values","percentile":0.46170119182941183,"significant":true},{"trait_id":"value_hedonism","name":"Hedonism","category":"values","percentile":0.48338908358801075,"significant":true},{"trait_id":"value_self_enhancement","name":"Self-enhancement","category":"values","percentile":0.37303733233452196,"significant":true},{"trait_id":"value_self_transcendence","name":"Self-transcendence","category":"values","percentile":0.18354711061030066,"significant":true}],"warnings":[{"warning_id":"CONTENT_TRUNCATED","message":"For maximum accuracy while also optimizing processing time, only the first 250KB of input text (excluding markup) was analyzed. Accuracy levels off at approximately 3,000 words so this did not affect the accuracy of the profile."}]}出力したjsonをハッシュに整形するコード(Ruby)require "json" File.open("kokoro.json") do |json| hash = JSON.load(json) puts "" puts "------big5------" puts "Openness" puts hash["personality"][0]["children"] puts "" puts "Conscientiousness" puts hash["personality"][1]["children"] puts "" puts "Extraversion" puts hash["personality"][2]["children"] puts "" puts "Agreeableness" puts hash["personality"][3]["children"] puts "" puts "Emotional range" puts hash["personality"][4]["children"] puts "" puts "------values------" puts hash["values"] end整形するコードを実行した結果------big5------ Openness {"trait_id"=>"facet_adventurousness", "name"=>"Adventurousness", "category"=>"personality", "percentile"=>0.32241762665507223, "significant"=>true} {"trait_id"=>"facet_artistic_interests", "name"=>"Artistic interests", "category"=>"personality", "percentile"=>0.5521516749265605, "significant"=>true} {"trait_id"=>"facet_emotionality", "name"=>"Emotionality", "category"=>"personality", "percentile"=>0.5132346262424734, "significant"=>true} {"trait_id"=>"facet_imagination", "name"=>"Imagination", "category"=>"personality", "percentile"=>0.607365647158204, "significant"=>true} {"trait_id"=>"facet_intellect", "name"=>"Intellect", "category"=>"personality", "percentile"=>0.7578837755541521, "significant"=>true} {"trait_id"=>"facet_liberalism", "name"=>"Authority-challenging", "category"=>"personality", "percentile"=>0.8196241048763219, "significant"=>true} Conscientiousness {"trait_id"=>"facet_achievement_striving", "name"=>"Achievement striving", "category"=>"personality", "percentile"=>0.24103760626726628, "significant"=>true} {"trait_id"=>"facet_cautiousness", "name"=>"Cautiousness", "category"=>"personality", "percentile"=>0.3967189883611717, "significant"=>true} {"trait_id"=>"facet_dutifulness", "name"=>"Dutifulness", "category"=>"personality", "percentile"=>0.24845542781829882, "significant"=>true} {"trait_id"=>"facet_orderliness", "name"=>"Orderliness", "category"=>"personality", "percentile"=>0.207879302126662, "significant"=>true} {"trait_id"=>"facet_self_discipline", "name"=>"Self-discipline", "category"=>"personality", "percentile"=>0.19535876642618683, "significant"=>true} {"trait_id"=>"facet_self_efficacy", "name"=>"Self-efficacy", "category"=>"personality", "percentile"=>0.21390998519773624, "significant"=>true} Extraversion {"trait_id"=>"facet_activity_level", "name"=>"Activity level", "category"=>"personality", "percentile"=>0.33897831044712423, "significant"=>true} {"trait_id"=>"facet_assertiveness", "name"=>"Assertiveness", "category"=>"personality", "percentile"=>0.11746700558582457, "significant"=>true} {"trait_id"=>"facet_cheerfulness", "name"=>"Cheerfulness", "category"=>"personality", "percentile"=>0.22972256751949427, "significant"=>true} {"trait_id"=>"facet_excitement_seeking", "name"=>"Excitement-seeking", "category"=>"personality", "percentile"=>0.2357839101981965, "significant"=>true} {"trait_id"=>"facet_friendliness", "name"=>"Outgoing", "category"=>"personality", "percentile"=>0.29853824637994103, "significant"=>true} {"trait_id"=>"facet_gregariousness", "name"=>"Gregariousness", "category"=>"personality", "percentile"=>0.3643146929286043, "significant"=>true} Agreeableness {"trait_id"=>"facet_altruism", "name"=>"Altruism", "category"=>"personality", "percentile"=>0.4020555962581259, "significant"=>true} {"trait_id"=>"facet_cooperation", "name"=>"Cooperation", "category"=>"personality", "percentile"=>0.3603843552650475, "significant"=>true} {"trait_id"=>"facet_modesty", "name"=>"Modesty", "category"=>"personality", "percentile"=>0.582131278592358, "significant"=>true} {"trait_id"=>"facet_morality", "name"=>"Uncompromising", "category"=>"personality", "percentile"=>0.34577537905073386, "significant"=>true} {"trait_id"=>"facet_sympathy", "name"=>"Sympathy", "category"=>"personality", "percentile"=>0.608321787997034, "significant"=>true} {"trait_id"=>"facet_trust", "name"=>"Trust", "category"=>"personality", "percentile"=>0.1107532137251554, "significant"=>true} Emotional range {"trait_id"=>"facet_anger", "name"=>"Fiery", "category"=>"personality", "percentile"=>0.5983433110620369, "significant"=>true} {"trait_id"=>"facet_anxiety", "name"=>"Prone to worry", "category"=>"personality", "percentile"=>0.7269479416509153, "significant"=>true} {"trait_id"=>"facet_depression", "name"=>"Melancholy", "category"=>"personality", "percentile"=>0.8142313580352654, "significant"=>true} {"trait_id"=>"facet_immoderation", "name"=>"Immoderation", "category"=>"personality", "percentile"=>0.5798042693808653, "significant"=>true} {"trait_id"=>"facet_self_consciousness", "name"=>"Self-consciousness", "category"=>"personality", "percentile"=>0.7577882331656556, "significant"=>true} {"trait_id"=>"facet_vulnerability", "name"=>"Susceptible to stress", "category"=>"personality", "percentile"=>0.7631343989629844, "significant"=>true} ------values------ {"trait_id"=>"value_conservation", "name"=>"Conservation", "category"=>"values", "percentile"=>0.18307614327169447, "significant"=>true} {"trait_id"=>"value_openness_to_change", "name"=>"Openness to change", "category"=>"values", "percentile"=>0.46170119182941183, "significant"=>true} {"trait_id"=>"value_hedonism", "name"=>"Hedonism", "category"=>"values", "percentile"=>0.48338908358801075, "significant"=>true} {"trait_id"=>"value_self_enhancement", "name"=>"Self-enhancement", "category"=>"values", "percentile"=>0.37303733233452196, "significant"=>true} {"trait_id"=>"value_self_transcendence", "name"=>"Self-transcendence", "category"=>"values", "percentile"=>0.18354711061030066, "significant"=>true}感想
- 人工知能は思った以上に気軽に利用することができる。
- カスタマーとの良い関係を維持することに利用出来そう。
参考資料
IBM Watson Personality Insights
- 投稿日:2019-11-27T23:19:23+09:00
ABC088B - Card Game for Two
問題
https://atcoder.jp/contests/abs/tasks/abc088_b
1回目
回答
N = gets.to_i A = gets.split.map &:to_i for i in 0..N-2 do for j in 0..N-2-i do if A[j] < A[j+1] hoji = A[j] A[j] = A[j+1] A[j+1] = hoji end end end i = 0 aliceSum = 0 bobSum = 0 while i < N aliceSum += A[i] if i+1 < N bobSum += A[i+1] end i += 2 end puts aliceSum - bobSum結果
2回目
回答
N = gets.to_i A = gets.split.map(&:to_i).sort.reverse result = 0 for i in 0..N-1 if i % 2 == 0 result += A[i] else result -= A[i] end end puts result結果
感想
sortあるんか〜〜〜〜〜い
- 投稿日:2019-11-27T22:16:09+09:00
Ruby学習ログ:その2【class, attr_accessor】
ハマりかけてます。
とりあえず整理するため書いていく!【Ruby】クラスとかインスタンスについて改めて学習してみた
クラス
= 初期処理 + インスタンス生成 + インスタンスメソッド定義・実行ちなみにクラスの中は 初期処理 と インスタンスメソッド定義 が含まれていれば大丈夫!
...と思ったがattr_accessorというメソッドがないとクラスの外でインスタンス生成ができないらしい
(scivolaさんがコメントにて間違いを指摘してくださりました。
attr_accessor
はメソッドを定義するメソッドとのこと)↓これが一番理解しやすかった↓
アクセスメソッド(アクセサメソッド )について(Ruby)
より引用↓class Pokemon def initialize(name) @name = name end def getName @name end def setName=(changed_name) @name = changed_name end end #クラス外部から値の参照が可能 pokemon = Pokemon.new('ピカチュウ') puts pokemon.getName => ピカチュウ #クラス外部から値の更新が可能 pokemon.setName = 'ギエピー' puts pokemon.getName => ギエピーこれを
attr_accessor
で書き換えるとclass Pokemon attr_reader :name def initialize(name) @name = name end end pokemon = Pokemon.new('ピカチュウ') puts pokemon.name => ピカチュウやっと理解できた...!
引数処理に関して掘り下げると
ruby引数処理に使えるテクニッククラスについてもっと知りたい!
→【まとめ】インスタンス変数、クラス変数、クラスインスタンス変数所感
アウトプット前提で学習すると効率よくインプットできますね!
個人的にはもっと質の高い記事を投稿したいが、学習ログという定に甘えてます
- 投稿日:2019-11-27T18:53:22+09:00
Railsチュートリアル 第10章 - 「div.paginationが無い」と言われてテストが通らない場合
何が起こったか
Railsチュートリアルも第10章まで進み、ユーザー一覧のテストを一通り書き終えました。しかし、以下のように「
div.pagination
が無い」と言われてテストが通りません。# rails test test/integration/users_index_test.rb Running via Spring preloader in process 12045 Started with run options --seed 11902 FAIL["test_index_including_pagination", UsersIndexTest, 2.137264299992239] test_index_including_pagination#UsersIndexTest (2.14s) Expected at least 1 element matching "div.pagination", found 0.. Expected 0 to be >= 1. test/integration/users_index_test.rb:12:in `block in <class:UsersIndexTest>' 1/1: [===================================] 100% Time: 00:00:02, Time: 00:00:02 Finished in 2.14716s 1 tests, 2 assertions, 1 failures, 0 errors, 0 skips解決
app/views/users/index.html.erb
やapp/controllers/users_controller.rb
の記述に間違いがないのにテストが通らない場合、fixtureの記述を間違えているのが原因かもしれません。私の場合は、fixtureにおける以下の記述間違いが原因でした。
test/fixtures/users.yml(抜粋)... <% 30.times do |n| %> - user_<% n %>: + user_<%= n %>: name: <%= "User #{n}" %> email: <%= "user-#{n}@example.com" %> password_digest: <%= User.digest('password') %> <% end %>これは気が付きにくい。
- 投稿日:2019-11-27T18:53:22+09:00
Railsチュートリアル 第10章 - 「div.paginationが無い」と言われてテストが失敗する場合
何が起こったか
Railsチュートリアルも第10章まで進み、ユーザー一覧のテストを一通り書き終えました。しかし、以下のように「
div.pagination
が無い」と言われてテストが通りません。# rails test test/integration/users_index_test.rb Running via Spring preloader in process 12045 Started with run options --seed 11902 FAIL["test_index_including_pagination", UsersIndexTest, 2.137264299992239] test_index_including_pagination#UsersIndexTest (2.14s) Expected at least 1 element matching "div.pagination", found 0.. Expected 0 to be >= 1. test/integration/users_index_test.rb:12:in `block in <class:UsersIndexTest>' 1/1: [===================================] 100% Time: 00:00:02, Time: 00:00:02 Finished in 2.14716s 1 tests, 2 assertions, 1 failures, 0 errors, 0 skips解決
app/views/users/index.html.erb
やapp/controllers/users_controller.rb
の記述に間違いがないのにテストが通らない場合、fixtureの記述を間違えているのが原因かもしれません。私の場合は、fixtureにおける以下の記述間違いが原因でした。
test/fixtures/users.yml(抜粋)... <% 30.times do |n| %> - user_<% n %>: + user_<%= n %>: name: <%= "User #{n}" %> email: <%= "user-#{n}@example.com" %> password_digest: <%= User.digest('password') %> <% end %>これは気が付きにくい。
- 投稿日:2019-11-27T18:26:47+09:00
【Rails】ユーザーと投稿を関連づける
※この記事はProgate Railsコースをやってみて開発する際使えそうなおおまかな手順をメモしただけです。
投稿にユーザの名前と画像を表示
- 投稿を管理しているテーブルに「どのユーザが投稿したのか」という情報を管理するためのカラム(user_id)を追加
- 「新規投稿の際にどのユーザーが投稿したのか」という情報を(user_id)に追加
- あとは表示するときに使うアクションでuser_idを使ってユーザ情報を集めてビューで表示
ユーザ詳細にそのユーザの投稿一覧を作る
- ユーザ詳細アクションでそのユーザと一致するuser_idの投稿をwhereメソッドで集めてビューで表示
投稿の編集と削除の制限
- 投稿詳細表示のアクションででログインしているユーザのidと投稿のuser_idが一致したら「編集」と「削除」のリンクを表示
- 投稿編集表示メソッド・投稿編集メソッド・投稿削除メソッドなどで現在ログインしているユーザのidと投稿のユーザidが一致しなければ投稿一覧へリダイレクト
「いいね」機能の追加
- Likeモデルと「いいねを押したユーザのID」と「いいねを押した投稿」を管理するためのlikesテーブルを作成
- likesテーブルを用いて操作するためのlikesコントローラを作成してdestroyメソッドとcreateメソッドを作成する
- いいねボタンの表示とcreateアクションとdestroyアクションの結びつけ
- いいねの数を表示
ヒント
・いいねボタンの表示
link_toメソッドにHTML要素を含む場合<% link_to("URL") do %> HTML要素 <% end %>・いいねの数の表示
whereメソッドとcountメソッドを使用いいねした投稿の表示
- likes.html.erbとそのルートとコントローラを作成する
- likesテーブルをもとにそのユーザがいいねした投稿を表示する
パスワードの暗号化
bcrypt
というgemをインストール- usersテーブルに
password_digest
カラムを追加してpassword
カラムを削除- 保存する際にパスワードを暗号化するために
has_secure_password
をuserモデルに追加ヒント
・passwordカラムを削除
remove_columnメソッドを使用暗号化されたパスワードでログインする
- authenticateメソッドを使用して、入力されたパスワードと比較して、一致すればログインできるようにする
ヒント
authenticateメソッドは渡された引数を暗号化する
- 投稿日:2019-11-27T18:20:53+09:00
Rubyで長い文字列を書く時の備忘録
Rubyで複数行に渡る長い文字列を作成する際の備忘録です。
文字列を作成する際、シングル(or ダブル)クオーテーションで囲う書き方が一般的です。
ダブルクオーテーションa = "長い文字列です。 複数行にわたる文字列は 読みにくいですね。"こう書けばもっと読みやすいよ。
ヒアドキュメントa = <<TEXT 長い文字列です。 複数行にわたる文字列は 読みにくいですね。 TEXTTEXTはただの識別子なので、TEXTでなくても良いです。
識別子を指定できるので、文字列について何かわかりやすい文言を指定できるというのも
メリットの1つです!以上、備忘録でした!
- 投稿日:2019-11-27T17:30:55+09:00
特定パス以下のActionController::RoutingErrorでJSONを返却する
環境
Ruby 2.5.7
Rails 5.2 (ActionPack 5.2)コード
lib/middleware/routing_error_response_json.rbmodule YourNameSpace::Middleware class RoutingErrorResponseJson RESPONSE_JSON_PATHS = %w[/api/v1] def initialize(app) @app = app end def call(env) request = ActionDispatch::Request.new(env) status, headers, response = @app.call(env) # NOTE: ActionController::RoutingError時に設定されるパラメータ # See https://github.com/rails/rails/blob/5-2-stable/actionpack/lib/action_dispatch/journey/router.rb#L64 if enable?(request) && status == 404 && headers['X-Cascade'] == 'pass' status, headers, response = pass_response(status) end [status, headers, response] rescue Exception => exception # rubocop:disable Lint/RescueException raise exception end private def pass_response(status) [ status, { "Content-Type" => "application/json" }, [ JSON.generate( { title: 'Routing Error', detail: 'No route matches', invalid_params: [] } ) ] ] end def enable?(request) RESPONSE_JSON_PATHS.any? { |path| request.path.to_s.start_with?(path) } end end endconfig/initializers/middleware.rbrequire_relative "../../lib/middleware/routing_error_response_json" ::Rails.application.config.middleware.use YourNameSpace::Middleware::RoutingErrorResponseJson実現できる事
↑の例であれば
/api/v1
以下へのリクエストでRoutingErrorとなった場合にJSONを返却する事ができる。
WebとApiが同居しているアプリケーションなどで利用価値があるかもしれない。最後に
もっと良い方法があれば教えて欲しいです。
- 投稿日:2019-11-27T17:26:34+09:00
Rubyのreturn備忘録
Rubyでメソッドを定義する際、他の言語経験者だと戻り値を返すためにreturnを使うことが多いかと思うのですが、
Rubyの場合はreturnを使わない書き方の方が主流です。メソッド定義(return版)def add(a, b) return a + b end add(1, 2)メソッド定義(主流版)def add(a, b) a + b end add(1, 2)returnはメソッドを途中で脱出する場合に使われることが多い。
以下の例は、引数がnilの場合はgreetingメソッドを抜けるようreturnを使っています。returnの書き方def greeting(country) return 'countryを入力してください' if country.nil? if country == 'japan' ・・・ end以上、備忘録でした!
- 投稿日:2019-11-27T17:24:32+09:00
クイズ:なぜバリデーションエラーになるでしょう
要約
- railsのcallbackで中間テーブルを生成する方法をミスるとvalidationエラーになるアンチパターン
詳細
- モデル構成
class User < ApplicationRecord has_many :notification_settings, dependent: :destroy has_many :notifications, through: :notification_settings, dependent: :destroy after_create :create_default_notifications end class NotificationSetting < ApplicationRecord belongs_to :user belongs_to :notification validates :user_id, uniqueness: { scope: [:notification_id] } end class Notification < ApplicationRecord has_many :notification_settings, dependent: :destroy has_many :users, through: :notification_settings, dependent: :destroy endとかで、ユーザに通知設定が複数ひもづいている状態で、ユーザが作成されたタイミングでデフォルトの通知設定を作りたくて
create_default_notifications
の中でdef create_default_notifications self.notifications = Notification.all endてやっていると一見OKっぽいんだけど、
validates :user_id, uniqueness: { scope: [:notification_id] }
で引っかかってvalildationエラーになる。理由
self.notifications = Notification.allが評価されたタイミングでNotificationSettingにinsertが発行されてしまって、
その後autosaveも動くので、結果2回createされてしまってuniqueじゃなくなってエラーになる。
has_manyにassignすると即insertされるというのがわかりにくかったという問題。
=はsaveされないという思い込みでした。修正
丁寧に1件1件buildする
Notification.all.each do |notification| self.notification_settings.build(notification: notification) end
- 投稿日:2019-11-27T16:56:41+09:00
Rubyの丸め誤差備忘録
小数点での計算の際、思わぬバグが生じたりする。
例えば0.1かける3が0.3にならない。
丸め誤差発生0.1 * 3.0 => 0.30000000000000004これはPCが10進数ではなく2進数で計算していることが原因なのですが、
上記コードから、以下のような場合が発生します。思わぬバグ0.1 * 3.0 == 0.3 #-> false 0.1 * 3.0 <= 0.3 #-> falseそのため、Rubyで小数点の計算を行うときは、Rationalクラスを使う!
数字の後ろに『r』をつけることで利用できる!Rationalクラス利用0.1r * 3.0r #->3/10 # 上記を利用すると・・・ 0.1r * 3.0r == 0.3 #-> true 0.1r * 3.0r <= 0.3 #-> true変数に小数点が入っている場合は、rationalizeメソッドを呼び出すことでRationalクラスの数値に変換することができる!
rationalizeメソッドa = 0.1 b = 3.0 a.rationalize * b.rationalize #-> 3/10『分数になってるやないか!』というツッコミが聞こえてくる・・・
その場合はto_fメソッドを使って、分数を少数にしてくださいませ!to_fメソッド(0.1r * 3.0r).to_f #-> 0.3 以上、備忘録でした!
- 投稿日:2019-11-27T16:55:35+09:00
eachメソッドとifメソッドの組み合わせの例
はじめに
この記事では、個人的に感動したeachメソッドとifメソッドを組み合わせについて解説します。
実行
最初に今回使用するコードを提示します。
users = ["田中", "鈴木", "佐藤", "山田", "藤本"] puts "誰をさがしますか?" name = gets.chomp.to_s num = 0 users.each do |user| if name == user num += 1 end end if num > 0 puts "発見しました" else puts "いませんでした" endこのコードは
配列users内に、入力した人名があった時に"発見しました"、無かった時に"いませんでした"と表示するプログラム
を表しています。まず最初に配列を定義します。
users = ["田中", "鈴木", "佐藤", "山田", "藤本"]次に、文字を入力して
name
に代入するようにします。puts "誰をさがしますか?" name = gets.chomp.to_s次に、
eachメソッド
で使うための変数num
を定義します。
ここで代入する数字はなんでもいいのですが、ここではnum = 0
としています。num = 0そして、今回の狙いの核となる
eachメソッド
およびifメソッド
を書いていきます。users.each do |user| if name == user num += 1 end end
eachメソッド
は、指定した配列の要素全てに対して、特定の処理を行うメソッドです。
今回の場合、指定した配列はusers
、特定の処理はifメソッド
になります。
ではifメソッド
だけを見てみると。if name == user num += 1 endとなります。
これは、name == user
の場合にnum += 1
という処理を行う、という処理になります。
もう少しかみ砕くと、入力した値が、元からあった値と一致したらnumに1を足すという処理です。これをusersの全ての要素一つ一つに行います。
users
の要素の中に。name
と一致するものが一つでもあれば、num > 0
となるので、最後の部分のif num > 0 puts "発見しました" else puts "いませんでした" endの
puts "発見しました"
が実行されます。
反対にname
と一致するものが一つもなければnum = 0
となりnum > 0
を満たせないので、ifメソッド
のelse
の部分であるputs "いませんでした"
が実行されます。これらの処理を組み合わせることにより
配列users内に、入力した人名があった時に"発見しました"、無かった時に"いませんでした"と表示するプログラム
を実現できます。追記
eachメソッド
とifメソッド
を始めとした条件式を使えば、簡単なアプリが色々作れそうなので、思いついたら色々試してみようと思います。
- 投稿日:2019-11-27T16:03:04+09:00
みんな大好き @mattn_jp さんのホクイモRuby ver.の解説
概要
@mattn さんのホクイモ、Rubyでわからないところがあったので調べました。
説明
コード再掲
puts '%1$s%1$sの%2$s'%((%w[ホイクモ]*2).map{|x|x.chars.sample(2).join})
'%1$s%1$sの%2$s'%
の最後の%はString#%
で、Stringクラスのメソッドで、フォーマットに対して呼び出すと引数を適用した文字列を返してくれるそうです。フォーマットの詳細は
Kernel::sprintf
を見ろというので、見に行きます。見てみると、
%
、s
、$
を使っているとわかります。
下記の事例などがわかりやすいですね。sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"感想
元記事のコメント欄で、C++の人から強い言葉でコメントがついていて、(以下略)。
- 投稿日:2019-11-27T14:56:02+09:00
Mac環境でRails内で別プロセスが立ち上がる処理をすると落ちてしまうとき
概要
Railsで
task runner
を実行しようとすると以下のエラーが起こり、途中で処理が止まってしまいました。$ bundle exec rails runner -e development [タスク] objc[13178]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called. objc[13178]: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.解決法
$ echo 'export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES' >> ~/.bash_profile $ exec $SHELL -l $ bin/spring stop $ bundle exec rails runner -e development [タスク]参照
macOS High Sierra で "__NSPlaceholderDictionary initialize" エラー
- 投稿日:2019-11-27T12:36:33+09:00
Rails6 のちょい足しな新機能を試す108(multi-db abort_if_pending_migrations編)
はじめに
Rails 6 に追加された新機能を試す第108段。 今回は、 multi-db abort_if_pending_migrations 編です。
Rails 6 では、rails db:abort_if_pending_migrations
が multi database に対応しました。Ruby 2.6.5, Rails 6.0.0 で確認しました。 (Rails 6.0.1 がリリースされていますが、確認した時点ではリリースされていませんでした。)
$ rails --version Rails 6.0.0今回は、簡単なスクリプトを作って確認します。
Rails プロジェクトを作成する
$ rails new rails_sandbox $ cd rails_sandbox今回は複数のDBを作って、それぞれ、 User と Book のCRUD を作ってから、
rails db:abort_if_pending_migrations
を実行して確認します。config/database.yml を編集する
config/database.yml
を編集して複数データベースにします。config/database.yml... development: backbone: <<: *default database: backbone_development library: <<: *default database: library_development migrations_paths: db/library_migrate ...User の CRUD を作成する
User
の CRUD を作成します。$ bin/rails g scaffold User name
Book の CRUD を作成する
Book
の CRUD を作成します。$ bin/rails g scaffold Book title --db libraryBook モデルを編集する
データベースの接続先を
library
に変更します。app/models/book.rbclass Book < ApplicationRecord connects_to database: { writing: :library, reading: :library } endマイグレーションを実行する
$ bin/rails db:create db:migrate
rails server
を実行する別に実行しなくても良いのですが、別の事象に遭遇したので、ここで実行します。
$ bin/rails s
マイグレーションを作成する
rails server を実行したのとは、別のコンソールから、books に published_at カラムを追加するマイグレーションを作成します。
$ bin/rails g migration add_published_at_to_books published_at:datetime --db librarydb:abort_if_pending_migrations を実行する
rails db:abort_if_pending_migrations
を実行すると、ちゃんとrails db:migrate
を実行しろとメッセージが出ます。$ rails db:abort_if_pending_migrations You have 1 pending migration: 20191022023755 AddPublishedAtToBooks Run `rails db:migrate` to update your database then try again.ブラウザでアクセスする
どういう訳か、http://localhost:3000/users または、 http://localhost:3000/books にブラウザからアクセスしても
ActiveRecord::PendingMigrationError
になりませんでした。
予想と違ったので、 Issue として報告 しておきました。試したソース
試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try108_multi_db_pending参考情報
- 投稿日:2019-11-27T12:19:08+09:00
投稿に対してのコメントの削除した際にエラー ActiveRecord::RecordNotFound
投稿に対してコメントできる機能を実装しました。
コメントは投稿詳細ページでコメントできるようにしています。
そのコメントを削除する際にエラーが出ます。
ActiveRecord::RecordNotFound in TweetsController#destroy
Couldn't find Tweet with 'id'=27
とでます。
tweets.controller.rbのdestroyアクションに飛んでいる状態です
本来はcomments.controller.rbのdestroyアクションに飛ばしたいです。この削除ボタンのlink先のurlが悪いのでしょうか?
= link_to "削除","/tweets/#{comment.id}", method: :delete, class: "image-delete"教えてくださいよろしくお願いします。
ファイル名<comments_controller.rb> class CommentsController < ApplicationController def create @comment = Comment.create(text: comment_params[:text], tweet_id: comment_params[:tweet_id], user_id: current_user.id) respond_to do |format| format.html { redirect_to tweet_path(params[:tweet_id]) } format.json end end def destroy comment = Comment.find(params[:id]) comment.destroy end private def comment_params params.require(:comment).permit(:text).merge(user_id: current_user.id, tweet_id: params[:tweet_id]) end endファイル名<views/comments/_comment.html.haml> .comments %h4 <コメント一覧> - if @comments - @comments.each do |comment| %p %strong = link_to comment.user.nickname, "/users/#{comment.user_id}" : = comment.text - if user_signed_in? && current_user.id == comment.user_id = link_to "削除","/tweets/#{comment.id}", method: :delete, class: "image-delete"ファイル名<routes.rb> resources :tweets do resources :comments, only: [:create, :destroy] end
- 投稿日:2019-11-27T01:37:03+09:00
RubyとPythonとmap
一方の言語でのイメージが邪魔して、もう一方の言語での書き方が思い出せない時がたまにあるんです。
Pythonmap(lambda n: str(n).rjust(3,"0"), [1,2,3]) >> ["001", "002", "003"]Ruby[1,2,3].map{|n| n.to_s.rjust(3,"0")} >> ["001", "002", "003"]