- 投稿日:2021-03-08T22:41:24+09:00
【Ruby】Base64変換ツール書いてみた
ここの問題を解いてみました
コード
module Base64 TABLE = [*"A".."Z", *"a".."z", *"0".."9", "+", "/"] module_function def encode(str) binary_ary = str.bytes.map do |b| t = b.to_s(2) t.size == 8 ? t : t.rjust(8, "0") end binary_str = binary_ary.join binary_ary = binary_str.scan(/\d{6}/) binary_ary << binary_str[-(binary_str.size % 6)..].ljust(6, "0") unless binary_str.size % 6 == 0 binary_ary.map { |x| TABLE[x.to_i(2)] }.join << "=" * (binary_ary.size % 4) end def decode(base_str) binary_ary = base_str.delete("=").chars.map do |s| t = TABLE.index(s).to_s(2) t.size == 6 ? t : t.rjust(6, "0") end chr_code_ary = binary_ary.join.scan(/\d{8}/).map { |b| b.to_i(2) } chr_code_ary.pack("c*") end end乾燥した感想
解き終わったとき最高に気持ちよかったです
改善点などあればぜひご指摘お願いしますbinary_ary << binary_str[-(binary_str.size % 6)..].ljust(6, "0") unless binary_str.size % 6 == 0ここの
unless
修飾子以降を書き忘れるという凡ミスを犯し、それに気づくのにめちゃくちゃ時間がかかりました
作業時間の80%は最後の20%の作業にかかる時間であるっていう至言を完全に理解した
- 投稿日:2021-03-08T21:49:11+09:00
【Ruby on Rails】フォロー・フォロワー機能の実装
はじめに
Railsで作成中のアプリにフォロー・フォロワー機能を実装しました。
理解できていなかったことも多かったので、理解を深めるために投稿します。
解説が長すぎるので、全てリンクにしています。
参考にされる際は必要なところだけご覧いただいても構いません。前提条件と作成物
前提条件
- rails 5.2.4
- devise導入済み
- userテーブルは作成済み←Userに対しフォロー機能を設定します
作成物
- フォロー機能(follow,unfollow)
- フォロー・フォロワー一覧ページ
流れ
- Relationshipモデルとカラムを作成
- アソシエーションを記述
- Userモデルに
「フォロー機能」「フォロー解除機能」「フォローしているかどうかメソッド」を記述- Relationshipコントローラを作成・編集、ルーティング編集
- viewページを作成(フォローボタン)
- viewページを作成(フォロー・フォロワー一覧)
1. Relationshipモデルを作成
ターミナル$ rails g model Relationship follower_id:integer followed_id:integer # follower_id:フォローするユーザーのid, followed_id:フォローされるユーザーのid $ rails db:migrate # マイグレーション実行まずはRelationshipモデルとカラムを作ります。
今回はRelationshipで作りましたが、他のモデルの場合は置き換えてください。
カラム データ型 備考 relationship_id integer 記述不要、自動作成される follower_id integer フォローするユーザーのid followed_id integer フォローされるユーザーのid
【解説】なぜRelationshipモデルのカラムはuser_idではないのか?(クリック)
Relationshipモデルは中間テーブルの役割を担っています。
中間テーブルとは、多 対 多のリレーションを構築するとき、
2つのテーブルを関連づけるために各テーブルの外部キー(FK)をもつテーブルのことです。
今回のフォロー・フォロワー機能は、
・1ユーザーはたくさんのユーザーにフォローできる(1:N)
・1ユーザーはたくさんのユーザーにフォローされる(1:N)
つまり多 対 多のリレーション状態を作る機能です。
通常であれば、参照するテーブルのid(この場合はuser_id)を中間テーブルのカラムに当てることが望ましいですが、
今回の場合は参照されるのは両方ともuserテーブルとなり、重複してしまいます。
そのため、最終的に参照するのはuser_idですが、
分かりやすいように別のカラム名で定義をしてあげる必要があります。
今回は、
follower_id : フォローするユーザーのid
followed_id : フォローされるユーザーのid
としてカラムを設定しました。
中間テーブル?についてはこちら↓
Active Record の関連付け2. アソシエーションを記述
app/models/relationship.rbclass Relationship < ApplicationRecord belongs_to :follower, class_name: "User" belongs_to :followed, class_name: "User" # class_name: "User"を定義することでUserテーブルのレコードを参照する endRelationshipモデルにアソシエーションを記述します。
belongs_to :follower
の後にclass_name: "User"
を忘れないようにします。
【解説】なぜbelongs_to :follower(followed)なのか?class_nameはなぜ必要?(クリック)
belongs_to :follower, class_name: "User"
を元に見ていきます。
belongs_to = 従属 の意味です。
belongs_to :follower
でfollowerテーブルのfollower_idを探しにいきます。
ただ、今回はfollowerテーブルは作成していないのと、
参照してもらいたいのはfollower_idに格納されている値と同じuser_idです。
(user_idはフォロー・フォロワー関係にありますが、
relationshipテーブルの中で重複するため定義できません。
そのため、このような現象が起こります。)
このままではエラーになってしまうため、
class_name: "User"
でUserテーブルを参照するように定義します。
これを行うことで、例えば
「relationship_idが(1)の時follower_idに格納されている値と
同じuser_idをUserテーブルから探して」
というように関連づけることができます。(あくまで私の捉え方です)
followed_idに関しても同じなので、同様に定義します。
app/models/user.rb(フォロー機能部分のみ抜粋)class User < ApplicationRecord has_many :reverse_of_relationships, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy has_many :followers, through: :reverse_of_relationships, source: :follower # 被フォロー関係を通じて参照→followed_idをフォローしている人 has_many :relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy # 【class_name: "Relationship"】は省略可能 has_many :followings, through: :relationships, source: :followed # 与フォロー関係を通じて参照→follower_idをフォローしている人 endUserモデルにもRelationshipとのアソシエーションを記述します。
くどいようですが、user_idを中間テーブルで直接定義していないため、
Relationshipテーブルを参照した時にuser_idが参照できるよう、定義します。
また、今回はフォロー・フォロワー一覧ページも作成するため、2、4行目も記述します。
(フォロー・フォロワー数をカウントする時も使えます。)
【解説】has_many 1行目と3行目の意味は?(クリック)
has_many :reverse_of_relationships, class_name: "Relationship"
先程のRelationshipモデルと同じ意味です。
見分けやすいようにreverse_of_relationshipsと定義しました。
このままだと、reverse_of_relationship_idを探してしまいます。
それを防ぐために
foreign_key: "followed_id"
でどのカラムを参照して欲しいのかを定義します。
(foreign_keyは外部キーの意味です)
has_many :relationships, class_name: "Relationship"
の場合、class_nameは不要ですが、見た目統一のためにコードを残しています。
【解説】has_many 2行目と4行目の意味は?(クリック)
2行目のhas_many :followers, through: :reverse_of_relationships, source: :follower
を基準に見ていきます。
1行目で定義したのは、「どのカラムを参照するか」でした。
2行目と4行目では、参照したカラムを元に、関連するuser_idも参照できるように記述します。
1行目で定義したreverse_of_relationships
モデルをthrough
してfollower(_id)
というカラムを参照(source)
してね、と記述しています。
これを記述することで、@user.followersという記述がコントローラーで使えるようになります。
回りくどい説明になってしまいますが、2行目の場合は、
followed_idにあたるユーザーをフォローしているユーザー(つまりfollower_idにあたるユーザー)を参照することができます。
これはフォロー・フォロワー一覧ページを作成する時に使います。
3. Userモデルにメソッドを記述
app/models/user.rb(フォロー機能部分のみ抜粋)class User < ApplicationRecord def follow(user_id) relationships.create(followed_id: user_id) end def unfollow(user_id) relationships.find_by(followed_id: user_id).destroy end def following?(user) followings.include?(user) end end4. Relationshipコントローラを作成・編集
まずはrelationshipsコントローラを作成します。
ターミナル$ rails g controller relationships作成したコントローラにフォロー機能を作成・保存・削除するアクションと、
フォロー・フォロワー一覧を表示するアクションを記述していきます。app/controllers/relationships_controller.rbclass RelationshipsController < ApplicationController # ——————フォロー機能を作成・保存・削除する———————————— def create current_user.follow(params[:user_id]) redirect_to request.referer end def destroy current_user.unfollow(params[:user_id]) redirect_to request.referer end #————————フォロー・フォロワー一覧を表示する-———————————— def followings user = User.find(params[:user_id]) @users = user.followings end def followers user = User.find(params[:user_id]) @users = user.followers end
【解説】フォローを作成・保存・削除する(クリック)
current_user.follow(params[:user_id])
、
current_user.unfollow(params[:user_id])
では、先程userモデルで定義したfollow、unfollowメソッドを使っています。
relationshipsとusersはネストの関係のため、userモデルからメソッドの呼び出しも可能です。
モデルに記述する理由はこちらが参考になりました↓
Railsのモデルに書いたメソッドってどうやってコントローラで使うの?
【解説】フォロー・フォロワー一覧を表示する(クリック)
@users = user.followings
、
@users = user.followers
では、
先程userモデルで定義したアソシエーションを利用します。
これによりuser = User.find(params[:user_id])
で取得したユーザーのidが、
フォローしている もしくは フォローされている ユーザーのid一覧を
取得することができます。
ルーティングも記述します。
config/routes.rb(関連部分のみ)resources :users, only: [:index, :show, :edit, :update] do # ——————————————— ここから ——————————————— resource :relationships, only: [:create, :destroy] get 'followings' => 'relationships#followings', as: 'followings' get 'followers' => 'relationships#followers', as: 'followers' # ——————————— ここまでネストさせる ——————————— end
resources :users
の最後にdo
を記述するのを忘れないようにします。
relationships は中間テーブルなので、usersモデルにネストさせます。
followingsとfollowersは一覧ページ用に定義したアクションです。5. viewページを作成(フォローボタン)
view/users/_info.html.erb(フォローボタン部分のみ記述)<% if current_user.following?(user) %> <%= link_to "Unfollow", user_relationships_path(user.id), method: :delete %> <% else %> <%= link_to "Follow", user_relationships_path(user.id), method: :post %> <% end %>今回はuserページの部分テンプレート内に埋め込みましたが、
view/relationships/_follow_button.html.erbなど、
ボタン部分だけ記述したviewを作成してもOKだと思います。(そちらの方が見やすいです)
【解説】<% if current_user.following?(user) %>(クリック)
if current_user.following?(user)
では、
userモデルで定義したfollowing?メソッドを使っています。
これにより、「今ログインしているユーザーは今参照しているユーザーをフォロしているか?」が条件となります。
trueの場合は、フォローしている状態なので、フォロー解除(unfollow)できるような表示を、
falseの場合は、フォローしていない状態なので、フォローする(follow)できるように表示します。
6. viewページを作成(フォロー・フォロワー一覧)
view/relationships/followers.html.erbもしくはview/relationships/followings.html.erb<h2>Follower Users</h2>または<h2>Follow Users</h2> <% if @users.exists? %> <thead> <tr> <th>name</th> <th></th> <th></th> </tr> </thead> <tbody> <% users.each do |user| %> <tr> <td><%= user.name %></td> <td>フォロー数: <%= user.followings.count %></td> <td>フォロワー数: <%= user.followers.count %></td> </tr> <% end %> </tbody> </table> <% else %> <p>ユーザーはいません</p> <% end %>フォロー・フォロワー一覧ともにほとんど同じ記述です。
タイトルを<h2>Follower Users</h2>
なのか、
<h2>Follow Users</h2>
なのか選択します。
<% if @users.exists? %>
がtrueの場合は、ユーザー一覧を表示させます。
すでにユーザー一覧(index)を作成していれば、部分テンプレート化して埋め込みでOKです。
例:<%= render '/users/index', users: @users %>
などです。
作成していない場合は、上記のような形で表記できます。
tableタグだけで整えていますが、bootstrapなどを使えばより綺麗に整えられると思います。これでフォロー・フォロワー機能の実装は完了です!
おわりに
今回は、フォロー・フォロワー機能の実装を、手順と内容についてまとめました。
1度の実装だけでは理解が難しく、何度もパターンを試して、
アウトプットすることでまた少し理解が深まったような気がします。
フォロー・フォロワー機能の実装方法はたくさんあると思うので、
よりスマートで効率の良いコードを書けるように精進していきたいです^^内容が盛りだくさんのため、抜け漏れがあったら申し訳ありません。
また、理解が乏しい箇所・用語の使い方が間違っている点も多々あるかと思います。コメント欄でご指摘いただければ幸いです。こちらも参考になりました↓ありがとうございました。
https://qiita.com/mitsumitsu1128/items/e41e2ff37f143db81897
- 投稿日:2021-03-08T21:04:46+09:00
Railsポートフォリオで詰まった箇所まとめ(その都度追加)
Railsポートフォリオ作成中、時間を取られた箇所まとめ。精神的に来たもの一覧でもある。ほぼ自分への戒め用。もう少し早く書き始めればよかった・・・
【ページ内リンク】
0.環境
Q1.フォルダ全消しした後、再度同じものを作り直したときに途中でエラーの嵐になる
Q2.テーブルにDateTimeが追加できない!0.環境
・AWS
・heroku/7.48.0 linux-x64 node-v12.16.2
・Rails 5.2.4.5
・ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
・MySQL 5.7.31
・PostgreSQL 9.2.24Q1.フォルダ全消しした後、再度同じものを作り直したときに途中でエラーの嵐になる
A.前に作ったデータベース消してなかった。そりゃ同名のDB作ろうとしたらエラー出ますよね。
【解決策】
mysql> drop database 消したいDB名;・消したいDB名の確認方法は
mysql> show database;
Q2.テーブルにDateTimeが追加できない!
A.諦めてdateクラスとtimeクラスに分けた・・・(後に、
DateTime
って大文字D
とT
を使ってたからだと判明。これは酷い。)【経緯】
・日付と時刻を入れたかったので、それら二つとも代入できるDateTimeクラスって便利じゃん!ということで$ rails g model テーブル名 カラム名:DateTime
をやってみたが$ rails db:migrate
でエラー。
・エラー文読んでみたらDateTimeがダメみたい
・Time
でもDate
でも出来なかった
・色々考えた結果、$ rails g model テーブル名 カラム名:date ~
としたら出来た
・普通に$ rails g model テーブル名 カラム名:datetime
としたら出来るのでは・・・?
・出来た。【解決策】
$ rails g model テーブル名 カラム名:datetime
- 投稿日:2021-03-08T20:41:50+09:00
Two Sum 〜leetcode〜
〜問題文〜
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. _________________________________ Example 1: Input: nums = [2,7,11,15], target = 9 Output: [0,1] Output: Because nums[0] + nums[1] == 9, we return [0, 1]. Example 2: Input: nums = [3,2,4], target = 6 Output: [1,2] Example 3: Input: nums = [3,3], target = 6 Output: [0,1] Constraints: 2 <= nums.length <= 103 -109 <= nums[i] <= 109 -109 <= target <= 109 Only one valid answer exists.引用元: https://leetcode.com/problems/two-sum/
簡単に要約すると、
「与えられた配列(nums)内の数字同士で、足し合わせると、targetになる配列要素の添字(インデックス)を、2つ、配列として出力するようなメソッドを作りなさい。」
だそうです。〜回答例〜
def two_sum(nums, target) search = Hash.new nums.each_with_index do |item,index| i = search[target-item] return [i+1, index+1] if i != nil search[item] = index end end回答例引用元(一部改変):
https://leetcode.com/problems/two-sum/discuss/55/Accepted-ruby-solution以下、上記回答の分解分析
1. メソッドの定義
def two_sum(nums, target) 〜省略〜 end「two_sum」というメソッドで第一仮引数=「nums」と第二仮引数= 「target」と定義する。
2. 変数searchに代入
〜省略〜 search = Hash.new 〜省略〜変数「search」に対して、「Hash.new」を代入する。
Hash.newについては以下を参考にする。
参考:https://docs.ruby-lang.org/ja/latest/method/Hash/s/new.html
nums.each_with_index do |item,index| 〜省略〜 end「each_with_index」メソッド。
要素とその添字(インデックス)をブロックに渡して繰り返すメソッド。参考:https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_with_index.html
今回場合、ブロック変数の「index」部分に、添字(インデックス)が入ってくる。
また、添字は0から開始する。3. 以下、繰り返し部分
i = search[target-item]変数「 i 」に「search(=Hash.new)」を代入する。
「search」の添字の指定は、「target(=本メソッドの仮引数)」-「item(=numsの各要素)」で行う。return [i+1, index+1] if i != nil「return ~ if」の書き方は以下を参考にした。
参考:https://qiita.com/okhrt/items/3e98ba496bcf8c50ac64つまり「return 処理 if 条件」。
↓
「i (=search(=Hash.new))がnil(空)でなければ、 「i+1」 と 「index(=添字)+1」を配列で返しなさい。」という意味。全体の最終的ゴールの出力はこの行。
search[item] = index継続する場合はこちらに続く。
「search(=Hash.new)」の添え時として、「item(=numsの各要素)」を指定してあげた数値は、indexに代入される。
↓
処理後再びループへ。
- 投稿日:2021-03-08T20:32:14+09:00
【Ruby】to_iメソッドで値を整数に変換する。
個人メモです。
to_i
を使うと整数に変換できる。to_itest = { x: "123", y: "456", z: "789" } puts test[:x].class #String puts test[:x].to_i.class #Integer
class
は型を調べるメソッド。
to_itest = { x: "123", y: "456", z: "789" } puts test[:x].is_a?(Integer) #false puts test[:x].to_i.is_a?(Integer) #true
.is_a?(型)
は指定した型かどうかを調べるメソッド。
次の処理は何を意味しているか?
per_page = params[:per_page].to_iシンボルparamsの中のper_pageの値を取得し整数に変換したものを、per_pageに格納している。
つまり、per_pageにはただの整数が入っている。
- 投稿日:2021-03-08T19:57:19+09:00
【Ruby】before_actionとは何か?引数を渡す方法とオプションの使い方実例。
【Ruby】before_actionとは何か?引数を渡す方法とオプションの使い方実例。
before_actionとは何か?
各アクションが動く前に実行する処理を記述できる。
コントローラの冒頭に記述する。記述方法
1. 引数なしの場合
・
before_action :<メソッド名>
メソッドは同じファイルの下部に記述する。(※引数を渡すとエラーになる)
▼実例before_actionの例class UsersController < ApplicationController before_action :require_permission #(省略)アクションを記述 #before_actionの処理 def require_permission unless current_user.partner? || current_user.admin? redirect_to admin_root_path, alert: 'ここから先は管理者限定です!' end endアクションを実行する前に、
require_permission
を実行する。
もし、current_userのpartnerかadminの値が存在しなければ、admin_root_pathにリダイレクトする。その際にalartを表示する。unless文
条件式がfalseなら処理を実行する。
if !条件式
と同じunless 条件式 処理 end||
または(or)。
オブジェクトcurrent_userの
partner
またはadmin
の値が存在すればtrue, 存在しなければfalseを返す。redirect_to
・
redirect_to <リダイレクト先>[, <オプション名>: <値>]
alert:
で、アラートを表示する
2. 引数ありの場合
処理に引数を渡す場合は、矢印と波かっこ
→ { }
を使う。
before_action ->{ 処理 }
- 引数を渡さない場合でも使える。
▼実例
before_actionの例class UsersController < ApplicationController before_action ->{ require_permission("password") } #(省略)アクションを記述 #before_actionの処理 def require_permission("password") unless password === "xxxxx" redirect_to admin_root_path, alert: 'ここから先は管理者限定です!' end end
処理を複数記述する
処理を複数記述する場合も、
->{ }
を使う。before_action ->{ 処理1, 処理2 }
3. オプション
オプションをつけることで条件を絞ることができる。
オプション 内容 :only 実行するアクション :except 実行しないアクション :if 実行する条件 :unless 実行しない条件 例えば、createとshowアクションのみに適用したい場合は、
only: [:create, :show]
をつける。before_actionの例class UsersController < ApplicationController before_action :require_permission, only: [:create, :show] #(一部省略)アクションを記述 create: { create_params: :users_params, json_renderer: :show_renderer, }, show: { json_renderer: :show_renderer, }, #before_actionの処理 def require_permission unless current_user.partner? || current_user.admin? redirect_to admin_root_path, alert: 'ここから先は管理者限定です!' end end
▼->{ }
を使った場合も同じbefore_actionの例class UsersController < ApplicationController before_action ->{require_permission}, only: [:create, :show] #(一部省略)アクションを記述 create: { create_params: :users_params, json_renderer: :show_renderer, }, show: { json_renderer: :show_renderer, }, #before_actionの処理 def require_permission unless current_user.partner? || current_user.admin? redirect_to admin_root_path, alert: 'ここから先は管理者限定です!' end end
- 投稿日:2021-03-08T19:22:09+09:00
RSpecにて引数が必要なsubjectの使い方
はじめに
RSpecで、同じメソッドに対してのテストを複数回書くシーンでは、subjectを使うことでDRYなコードを書くことができます。
ここでは引数が必要なメソッドのテストをsubjectを用いて書きます。実装
ユーザー名(user_name)、自己紹介(pr)カラムがあるユーザーを、フリーワードで検索するuser_search(free_word)メソッドをテストするとします。普通に書くと以下のように繰り返し同じ処理が出てきます。
spec/models/user_spec.rbdescribe "#user_search" do context "when 'user_name1' is given" do it "return 1 result" do expect(Job.user_search("user_name1").count).to eq 1 end end context "when 'pr1' is given" do it "return 1 result" do expect(Job.user_search("pr1").count).to eq 1 end end endこれは以下のようにsubjectでまとめて処理を書くことができます。
spec/models/user_spec.rbdescribe "#user_search" do subject { User.user_search(field).count } context "when user_name1 is given" do let(:field) { "user_name1" } is_expected.to eq 1 end context "when pr1 is given" do let(:field) { "pr1" } is_expected.to eq 1 end end引数はletで定義することができます。
- 投稿日:2021-03-08T19:13:28+09:00
【Ruby】メソッド名や関数名の末尾の!(ビックリマーク)と?(はてなマーク)の意味とは?。実例で解説。
【Ruby】メソッド名の末尾の!(ビックリマーク)と?(はてなマーク)の意味について。
目次
- メソッド名末尾の!(ビックリマーク)の意味
- メソッド名末尾の?(クエスチョンマーク)の意味
1. メソッド名末尾の!(ビックリマーク)の意味
メソッド名の末尾についている!は処理を破壊的にする。
条件式の中で使われる!は否定を表すので、完全に異なる。
▼実例
例えば、非破壊のメソッドdowncase
(小文字にする)を使った場合、通常だと、元のオブジェクトは変化しない。通常str1 = "HELLO WORLD" str1.downcase puts str1 # HELLO WORLD
!
をつけると元のオブジェクトが変更(破壊)される。!ありstr2 = "HELLO WORLD" str2.downcase! puts str2 # hello world
定義した関数の中で使う場合
関数の中で破壊的メソッドを使う場合は、処理の中身がわかりやすいように、関数名の末尾に
!
をつける。def letterCange!(str) str.downcase! puts str end #関数の実行 letterCange!("HELLO WORLD") #結果 hello world
2. メソッド名末尾の?(クエスチョンマーク)の意味
真偽値を返すメソッドに使われる。
?
もセットで一つのメソッド。(?
なしだとエラーになる)通常str1 = "A STRING" puts str1.include?("RING") # true
▼?
がないとエラーになる?なし(エラー)str2 = "A STRING" puts str2.include("RING") # NoMethodError (undefined method `include' for "A STRING":String) # Did you mean? include??のつく主なメソッド一覧
メソッド 意味 例 include? 含むかどうか "string".include?("ring") => true empty? 空かどうか(Array, Hash, Set) [].empty? => true nil? nilかどうか 0.nil? => false
参考リンク
- 投稿日:2021-03-08T18:06:50+09:00
tiktokでogp相当の情報をAPIで取得する(ruby)
tiktokのスクレイピングをしてogp情報をとってくる処理を書いていたのだがいつのまにか下記のようにstatus code1000で弾かれるようになってしまっていた。
[25] pry(main)> html = open(movie_url) do |f| f.read; end => "{\"statusCode\":10000,\"verifyConfig\":{\"code\":10000,\"type\":\"verify\",\"subtype\":\"slide\",\"fp\":\"verify_5f101e29a0ad54278347a24437cfcb93\",\"region\":\"sg\",\"detail\":\"2SdJGObfW85-lX4dEGohkmh8YbPmZYiXwIh1pqrEUuohsJqr4t3XjgXHtkBHWheNJbj4MB*CVwF1ayKFmhUFcJY2yAgBxyatF0XXzv0*xk*DmEz7Og6oE0nS1mFuZXdkJE*Z05uOnCgTkh4d4yy7xfv6EiiQJGBxdHDxp21vXCZjphcNMaY6YoCrq-5wRulWVle0lP3RJyqJQUFbtIP8pH0LICH8SRGn9a6mItvTEiEwiHCfJHBxhTUf1kFCYkGm1gBpVE1s45qbaNPeVELCCU0732nlU1VLR7Jm16yTIne64NABwJSaXFAl19NrjsfHrV-Cxq*d4kuVUBERzDIIncNGgQ3m6MLdwGLw*H4xfl94O1LId2V5zlOltVL1gYtral9VUYNMskUBWclUpWt2zrUfpbVzuUg.\"}}"どうしようかなと思ったが、調べてみたらTikTokのAPIでogp相当の情報をとってこれるようだったので、apiを通して取得してくるように修正した。ドキュメントもあるので別に何も大変なことはない。
https://www.tiktok.com/oembed?url=https://www.tiktok.com/@scout2015/video/6718335390845095173このような形で情報を取得したいtiktokのURLをurlパラメータに渡してhttps://www.tiktok.com/oembed を叩くだけでいい。そうすると下記のようなレスポンスが返ってくる。
{ "version": "1.0", "type": "video", "title": "Scramble up ur name & I’ll try to guess it?❤️ #foryoupage #petsoftiktok #aesthetic", "author_url": "https://www.tiktok.com/@scout2015", "author_name": "Scout & Suki", "width": "100%", "height": "100%", "html": "<blockquote class=\"tiktok-embed\" cite=\"https://www.tiktok.com/@scout2015/video/6718335390845095173\" data-video-id=\"6718335390845095173\" style=\"max-width: 605px;min-width: 325px;\" > <section> <a target=\"_blank\" title=\"@scout2015\" href=\"https://www.tiktok.com/@scout2015\">@scout2015</a> <p>Scramble up ur name & I’ll try to guess it?❤️ <a title=\"foryoupage\" target=\"_blank\" href=\"https://www.tiktok.com/tag/foryoupage\">#foryoupage</a> <a title=\"petsoftiktok\" target=\"_blank\" href=\"https://www.tiktok.com/tag/petsoftiktok\">#petsoftiktok</a> <a title=\"aesthetic\" target=\"_blank\" href=\"https://www.tiktok.com/tag/aesthetic\">#aesthetic</a></p> <a target=\"_blank\" title=\"♬ original sound - ???????\" href=\"https://www.tiktok.com/music/original-sound-6689804660171082501\">♬ original sound - ???????</a> </section> </blockquote> <script async src=\"https://www.tiktok.com/embed.js\"></script>", "thumbnail_width": 720, "thumbnail_height": 1280, "thumbnail_url": "https://p16.muscdn.com/obj/tos-maliva-p-0068/06kv6rfcesljdjr45ukb0000d844090v0200010605", "provider_url": "https://www.tiktok.com", "provider_name": "TikTok" }コード(ruby)
uri = URI.parse("https://www.tiktok.com/oembed?url=#{params[:tiktok_url]}") response = Net::HTTP.get_response(uri) res_json = JSON.parse(response.body) html_doc = res_json["html"] title = res_json["title"] ogp_image = res_json["thumbnail_url"]
- 投稿日:2021-03-08T18:04:27+09:00
【Ruby】クラスの中のアットマークの意味。@と@@の違いは?(インスタンス変数とクラス変数の実例)
【Ruby】クラスの中のアットマークの意味。@と@@の違いについて。
@と@@の違い
どちらも変数を表す。インスタンスで使う変数か、クラスで使う(すべてのインスタンスで共通)の変数かの違い。
項目 意味 使い方 @ インスタンス変数 @<変数名> @@ クラス変数 @@<変数名> インスタンス変数とクラス変数の使い方
インスタンス変数
インスタンス変数は、生成したインスタンスごとに値がセットされるため、それぞれで固有となる。
class Aaa #インスタンス変数を定義 def setName(lastname, firstname) @name = lastname + " " + firstname end #メソッドを定義 def hello p "#{@name}さん" end end #インスタンスの生成 p1 = Aaa.new p2 = Aaa.new #インスタンス変数に名前をセット p1.setName("山田", "克巳") p2.setName("田中", "次郎") #インスタンスメソッドの呼び出し p1.hello # => "山田 克巳さん" p2.hello # => "田中 次郎さん"クラス変数
クラス変数は、すべてのインスタンスで共通となる。上書きされるため、後からセットした値が入る。
class Aaa #クラス変数を定義 def setName(lastname, firstname) @@name = lastname + " " + firstname end #メソッドを定義 def hello p "#{@@name}さん" end end #インスタンスの生成 p1 = Aaa.new p2 = Aaa.new #インスタンス変数に名前をセット p1.setName("山田", "克巳") p2.setName("田中", "次郎") #インスタンスメソッドの呼び出し p1.hello # => "田中 次郎さん" p2.hello # => "田中 次郎さん"各インスタンス毎で名前をセットしたが、後からセットした名前で上書きされるため、出力はどちらも後からセットした値になる。
- 投稿日:2021-03-08T18:03:50+09:00
Ruby2.3.4+Rails5.0.4からRuby3.0.0+Rails6.1.3にバージョンアップした話
はじめに
Heroku-16 Stackで動いているアプリケーションがあり、こちらが2021/6にEOLを迎える。
それに伴いHeroku Stackを上げるとRubyのバージョンも上げないといけなかった。
せっかくだったらこの機会に最新にしようと思い、バージョンを上げたのでその時の注意事項をメモ書き程度に残しておく。Gemfile
まず元々のGemfile
Gemfile# 一部抜粋 gem 'rails', github: 'rails/rails', branch: "5-0-stable" gem 'mysql2', '>= 0.3.18', '< 0.5' gem 'puma', '~> 3.0' gem 'rspec-rails', '~> 3.5' gem 'factory_girl_rails'Rubyのバージョン指定はしておらず、Herokuのデフォルトのバージョンになっていた。
今回はRubyとRailsのバージョンを上げたいので以下を設定してみた。Gemfileruby "3.0.0" gem 'rails', '~> 6.1', '>= 6.1.3'これで環境を作り直そうとした結果以下のエラー
Bundler could not find compatible versions for gem "bundler": In Gemfile: bundler-audit was resolved to 0.6.0, which depends on bundler (~> 1.2) license_finder was resolved to 3.0.2, which depends on bundler rails (~> 6.1, >= 6.1.3) was resolved to 6.1.3, which depends on bundler (>= 1.15.0) Current Bundler version: bundler (2.2.3) This Gemfile requires a different version of Bundler. Perhaps you need to update Bundler by running `gem install bundler`? Could not find gem 'bundler (~> 1.2)', which is required by gem 'bundler-audit', in any of the sources.bundler関連の問題でうまく環境が作れないようだった。
どうやらbundlerが1.15.3で作ろうとしているのが問題のようだった。
Gemfile.lockを消した状態でbundlerのバージョンを上げてbundle installした。
bundlerは2.2.11になった。Gemfile.lock# 一部抜粋 + RUBY VERSION + ruby 3.0.0p0 BUNDLED WITH - 1.15.3 + 2.2.11rexml
gem installすると以下のエラー
LoadError - cannot load such file -- rexml/document
こちらの記事を参考にしました。
Gemfilegem 'rexml'factory_girl
DEPRECATION WARNING: The factory_girl gem is deprecated. Please upgrade to factory_bot. See https://github.com/thoughtbot/factory_bot/blob/v4.9.0/UPGRADE_FROM_FACTORY_GIRL.md for further instructions. (called from <top (required)> at /usr/src/app/config/application.rb:17) porter-web-dev | /usr/local/bundle/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:332:in `require': cannot load such file -- rexml/document (LoadError)factory_girlは非推奨なのでfactory_botにバージョンアップする。
Gemfile- gem 'factory_girl_rails' + gem 'factory_bot'rspecファイル内にてFactoryGirlをFactoryBotに置換。
更新が用意してくれている置換コマンドで割といい感じに置換できた。mysql2
手元の環境はDockerで作成しているが
mysql-client
がないと言われたのでdefault-mysql-client
に変更Package mysql-client is not available, but is referred to by another package. This may mean that the package is missing, has been obsoleted, or is only available from another source
Dockerfile- RUN apt-get install -y mysql-client + RUN apt-get install -y default-mysql-client環境を立ち上げてみたがDBアクセスで以下エラー
Puma caught this error: Error loading the 'mysql2' Active Record adapter. Missing a gem it depends on? can't activate mysql2 (~> 0.5), already activated mysql2-0.4.10. Make sure all dependencies are added to Gemfile. (LoadError)mysql2のバージョンも上げる。
Gemfile- gem 'mysql2', '>= 0.3.18', '< 0.5' + gem 'mysql2', '~> 0.5.3'puma
ローカル環境が立ち上がらない。
こちらの記事を参考にしました。config/initializers/new_framework_defaults.rb- ActiveSupport.halt_callback_chains_on_return_false = false + #ActiveSupport.halt_callback_chains_on_return_false = falseローカル環境を立ち上げると証明書関連のエラー
こちらの記事を参考にpumaのバージョンも上げる。Gemfile- gem 'puma', '~> 3.0' + gem 'puma', '~> 5.2', '>= 5.2.1'Rspec
ローカル環境も立ち上がりある程度動くようになったのでテストを通してみたところ全部失敗した。
Failure/Error: raise WrongScopeError, "`#{name}` is not available from within an example (e.g. an " \ "`it` block) or from constructs that run in the scope of an " \ "example (e.g. `before`, `let`, etc). It is only available " \ "on an example group (e.g. a `describe` or `context` block)." `name` is not available from within an example (e.g. an `it` block) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc). It is only available on an example group (e.g. a `describe` or `context` block).こちらの記事を参考にしました。
spec/factories/hoge.rb- FactoryGirl.define do + FactoryBot.define do factory :hoge do - name 'テスト' + name {'テスト'} end endspec/spec_helper.rbconfig.before(:all) do FactoryBot.reload end最終的に
以下のようなGemfileになった。
Gemfile# 一部抜粋 ruby "3.0.0" gem 'rails', '~> 6.1', '>= 6.1.3' gem 'mysql2', '~> 0.5.3' gem 'puma', '~> 5.2', '>= 5.2.1' gem 'rexml' gem 'rspec-rails', '~> 4.0', '>= 4.0.2' gem 'factory_bot'各バージョンの後方互換を調べる
ローカル環境が起動しひと通りアプリケーションが動くことを確認。
RSpecが全て通ることを確認。
この時点で8割方バージョンアップ完了だったが、念の為各バージョンで後方互換切られているところを中心に調べていくことにした。
Ruby2.3から3.0という記事はなかったので1バージョンずつ調べていった。ruby2.4
特に問題なさそう。ruby2.5
後方互換の話は特になし。ruby2.6
範囲オブジェクトに影響あり。
git grep -i range
git grep "\.\."
あたりで範囲オブジェクトを使っている箇所を調べていった。ruby2.7
こちらも範囲オブジェクト関連。ruby3.0.0
1つずつ見てgrepしてみたが影響のありそうなものはそもそも使っていなかったので問題ないと判断した。rails6.1.3
https://qiita.com/ryohashimoto/items/622c3bcfb3336cb9317e
https://railsguides.jp/upgrading_ruby_on_rails.html
cookiesの話が気になるがrails4との比較をしているのでrails5からのアップデートでは問題なしと判断した。Heroku
以上の調査と修正によりバージョンアップ問題なしと判断し本番をHeroku-20 Stackに上げてデプロイ。
しかし本番でエラーが発生した。ActiveRecord::ConnectionNotEstablished: SSL connection error: error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocolこちらの記事と同様の事象のようだった。
なんとか解消したかったが原因不明のため、記事と同様にHeroku-18 Stackにしたら問題なく動いた。まとめ
今回所要時間15時間程度でバージョンアップすることができた。
ここまで早くできたのは以下の要因によるものと思われる。
- 元のバージョンがそこまで低くなかった。
- テストが書いてあった。
- 該当アプリケーションがシンプルな作りで機能がそこまで多くなく、検証すべき項目が少なかった。
せっかくバージョンを上げたので新バージョンで使えるようになった機能とかを使っていきたい。
まだ全然調べられていないがRails6からは標準でバルクインサートできるようになったらしい。
activerecord-import
とかgemを後入れしなくても良くなったのは嬉しい。
時間ができたら触ってみることにする。
- 投稿日:2021-03-08T17:14:42+09:00
【Ruby】includeとextendの違い。クラスメソッドとインスタンスメソッドの違いと実例。
【Ruby】includeとextendの違い。クラスメソッドとインスタンスメソッドの違いと実例。
目次
includeとextendとは?
どちらも、クラスの中でモジュールを呼び出すときに使う(mixin ミクシン)。
includeとextendの違い
読み込んだモジュールのメソッドを、インスタンスメソッドかクラスメソッドのどちらで読み込むかの違い。
メソッド 意味 include インスタンスメソッドとして読み込む extend クラスメソッドとして読み込む
クラスメソッドとインスタンスメソッドの違い
その名の通り、クラスから呼び出せるメソッドか、インスタンスから呼び出せるメソッドかの違い。
メソッド 呼び出し クラスメソッド <クラス名>.<メソッド名> インスタンスメソッド <クラス名>.new.<メソッド名> クラスメソッドは、クラスから直接メソッドを呼び出せる。
インスタンスの場合は、クラスから
new
を使って、インスタンスを生成して、メソッドを呼び出す。
クラスメソッドとインスタンスメソッドの使い分け
メソッド 用途 クラスメソッド 全体で共通 インスタンスメソッド インスタンス毎に固有 インスタンスメソッド
メソッドの結果が生成したインスタンス毎に固有となるメソッドを定義していく。(例えば、苗字や名前を登録するなど。)
インスタンスメソッドclass <クラス名> def <メソッド名> 処理 end end呼び出し<クラス名>.new.<メソッド名>
クラスメソッド
DBから指定したデータを抽出する場合など、どのインスタンスでも同じ答えが返るメソッドに使う。
- メソッド名の前に
self
がつく- メソッドはクラス名の後で直接呼び出せる(インスタンスを生成する必要がない)
インスタンスメソッドclass <クラス名> def self.<メソッド名> 処理 end end呼び出し<クラス名>.<メソッド名>
includeとextendの実例
include
インスタンスメソッドとして読み込む
includemodule Aaa def hello(name) p "こんにちは、#{name}さん" end end #モジュールの読み込み(mixin) class Xxx include Aaa end #メソッドの実行 Xxx.new.hello("山田") => "こんにちは、山田さん"▼クラスはNG
NGXxx.new.hello NoMethodError (undefined method `hello' for Xxx:Class)
extend
クラスメソッドとして読み込む
extendmodule Bbb def hello p "皆さん、こんにちは" end end #モジュールの読み込み(mixin) class Yyy extend Bbb end #メソッドの実行 Yyy.hello => "皆さん、こんにちは"▼インスタンスはNG
NGYyy.new.hello NoMethodError (undefined method `hello' for #<Yyy:0x00007f81b2083410>)
以上。
- 投稿日:2021-03-08T17:10:25+09:00
Rails newまでまとめてみた
アウトプット兼ねてまとめてみました。
*アドバイス訂正などありましたらご指摘お願いいたします。ステップ1
mkdir xxxでフォルダー作ってそこに移動
ステップ2
gem install rails ↓ rbenv exec gem install bundler
rbenv exec
はrbenvでインストールしたrubyを使ってbindlerを入れるらしい。ステップ3
rails new プロジェクト名 -d mysql作成したプロジェクトに移動
↓
bundle install --path vendor/bundle
二回目以降はbundle install
のみでOKステップ4
bundle exec rails s
- 投稿日:2021-03-08T16:14:55+09:00
【Ruby】モジュールとは?クラスの違いについて。モジュールの中のメソッドの呼び出し方
Rubyのモジュールとクラスの違いについて。モジュールの中のメソッドの呼び出し方実例と注意点。
目次
モジュールとは?
- メソッドを記述しておく場所
- moduleの中にdefでメソッドを書いていく
- メソッドを複数定義できる
module <モジュール名> def <メソッド名1> 処理1 end def <メソッド名2> 処理2 end , , , end
モジュールのメリット
- 複数読み込み可能
- 同じメソッド名を定義できる
メリット1 複数継承可能
複数のクラスを継承したい(メソッドの書かれた複数のファイルを読み込みたい)場合の代替手段。
▼どういうこと?
Rubyのデメリットとして、クラスを一つしか継承できない(単一継承)がある。このため、他のクラスを読み込んで、更に既に定義したメソッドを読み込みたい場合に、他のクラスを読み込むことができない。
この解決手段としてモジュールがある。モジュールを使えば、継承するクラスの他にもメソッドを読み込むことができるようになる。
メリット2 同じメソッド名を定義できる
module自体の名前が異なれば、同じメソッドでも違う名前になる。(オブジェクトのKVと同じ。)
オブジェクトの場合obj1 = {name: yamada, age: 24} obj2 = {name: tanaka, age: 24} #呼び出し obj1.name #yamada obj2.name #tanakanameという同じプロパティ名が存在するが、大元がobj1とobg2で異なるため、違う扱いになる。
▼モジュールの場合
modulemodule Aaa def hello p "こんにちは" end end module Bbb def hello p "ニーハオ" end endメソッド名はどちらもhelloだが、入れ物が異なるので問題ない。
モジュールの呼び出し方法
モジュールの呼び出し方法は2つ。
- classの中で読み込む
- moduleの中でmodule_functonを定義する
- Objectとextendを使う
1. classの中で読み込む
・
include <モジュール名>
で読み込む
・<クラス名>.new.<メソッド名>
で実行するメソッドの実行方法は、通常のクラスと同じくインスタンスを作成して、メソッドを呼び出す。
OK#モジュールの定義 module Aaa def hello p "こんにちは" end end #クラスで読み込み class Xxx include Aaa end #メソッドの実行 Xxx.new.hello => "こんにちは"モジュールが複数ある場合
カンマで繋ぐ。
・
include <モジュール名1>, <モジュール名1>,,,
▼注意点
メソッド名が同じ場合は、上のモジュールのメソッドが読み込まれる。(下側は無視される)OK(メソッド名が同じ場合)#モジュールの定義 module Aaa def hello p "こんにちは" end end module Bbb def hello p "ニーハオ" end end #クラスで読み込み class Xxx include Bbb, Aaa end #メソッドの実行 Xxx.new.hello => "こんにちは"mixinとは?
クラスの中でmoduleを呼び出すことをmixin(ミクシン)と呼ぶ。
mixinというメソッドがあるわけではなく、classの中でincludeを使ってmoduleを呼び出すこと = mixinとなる。
<
を継承と呼ぶのと同じく、ただの名称。
2. moduleの中でmodule_functonを定義する
・
module_function :<メソッド名>
▼注意点
-:
の後にスペースを空けない(エラーになる)
- 記述するメソッドは一つずつ。(メソッドが複数ある場合は複数記述する。カンマでつなげない)OK#モジュールの定義 module Aaa def hello p "こんにちは" end module_function:hello end #メソッドの実行 Aaa.hello => "こんにちは"
3. Objectとextendを使う
Object.new
で空のオブジェクトを生成し、.extend <モジュール名>
で拡張すれば、メソッドが使用できる。OK#モジュールの定義 module Aaa def hello p "こんにちは" end end #オブジェクトの生成 obj = Object.new #モジュールの拡張 obj.extend Aaa #メソッドの呼び出し obj.hello => "こんにちは"
NG事例
モジュールはクラスの中で定義した関数のように、
<モジュール名>.new.<メソッド名>
では呼び出せない。NG#モジュールの定義 module Aaa def hello p "こんにちは" end end #メソッドの実行 Aaa.new.hello #エラー内容 NoMethodError (undefined method `hello' for Aaa:Module)
- 投稿日:2021-03-08T14:16:41+09:00
小ネタ rspecでの比較を省略しないようにする
Failure/Error: expect(result).to be_a(Validation::Valid) expected #<Validation::Invalid value=#<Bundle id: nil, created_at: nil, updated_at: nil, action: nil, type: "B...on::Finder::NotFoundError: No feature_definition (site_linux) found for contract (hodor_contract)>]> to be a kind of Validation::Validこの
…
が見れずにデバッグに苦労すること、よくありますよね。以下のような設定を追加することで、
…
に切り替わる文字長を調整できるため、…が表示されなくなります。RSpec.configure do |config| config.expect_with :rspec do |c| c.max_formatted_output_length = 1000000 end end
- 投稿日:2021-03-08T14:07:09+09:00
GitHub Actions ReviewDog がエラー
ReviewDogをGithub actions経由で使っていたら急にエラーが発生
Installing rubocop with extensions ... https://github.com/rubocop/rubocop ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /var/lib/gems/2.7.0 directory.原因はubuntu-latetのデフォルトruby versionが 2.5.1から2.7.0に変わったこと。
https://github.com/actions/virtual-environments/issues/1816reviewdoc.yamljobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: 2.6.5 #マイクロバージョンまで指定可能こんな感じでyamlにrubyのバージョンを指定するようにすればOK
他に指定できるバージョンはこちらから参照可能
https://github.com/ruby/setup-ruby
- 投稿日:2021-03-08T12:25:19+09:00
AWSへデプロイ後にユーザー情報が更新できない現象への対処法
AWSへデプロイ後に、user.saveでユーザー情報が保存できない現象についての対処法
とあるプログラミング学習サイトを利用してRailsを学び、作成したアプリケーションをサーバーへデプロイしたところまでは良かったのですが、その後作成したユーザーのアイコンを変更できない現象に遭遇しました。手探りでの対処で苦戦しましたので、同じことを繰り返さないためにも投稿に残したいと思います。
現象が発生した元のコード
app/controllers/users_controller.rbdef update @user = User.find_by(id: params[:id]) @user.name = params[:name] @user.user_id = params[:user_id] @user.email = params[:email] if params[:image] @user.image_name = "#{@user.id}.jpg" image = params[:image] File.binwrite("public/user_images/#{@user.image_name}", image.read) end if params[:password] != nil @user.password = params[:password] end if @user.save flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.user_id}") else render("users/#{@user.user_id}/edit") end endこのコードでローカルではうまくいっていたのですが、サーバーへデプロイ後はユーザー画像のみ保存されて、MySQLのデータは更新されませんでした。
試したこと
エラーが吐き出されていないか確認しましたが、log/production.logにはエラーらしきものはなく、mysql.logを確認しようとしましたがどこにあるのかわからず、できませんでした。
このためはじめはrails consoleで状況を確認しようとしましたが、RDSのデータベースには接続されていないのか、users = User.allでユーザー情報を取得しようとしても、users.count = 0の状態でした。
そこで直接MySQLへログインして、テーブルのデータをSQLで更新してみたところ、こちらはできましたので、MySQLを使用して更新する方法を取ることにしました。
現象が改善した後のコード
app/controllers/users_controller.rbdef update id = @current_user.id updated = 0 update_name_sql = "update users set name = '#{params[:name]}' where id =#{id};" updated = ActiveRecord::Base.connection.execute(update_name_sql) update_email_sql = "update users set email = '#{params[:email]}' where id =#{id};" updated = ActiveRecord::Base.connection.execute(update_email_sql) if params[:image] update_image_name_sql = "update users set image_name = '#{id}.jpg' where id =#{id};" updated = ActiveRecord::Base.connection.execute(update_image_name_sql) image = params[:image] File.binwrite("public/user_images/#{id}.jpg", image.read) end if params[:password] hashed_password = BCrypt::Password.create(params[:password]) update_password_sql = "update users set encrypted_password = '#{hashed_password}' where id =#{@current_user.id};" ActiveRecord::Base.connection.execute(update_password_sql) end if updated =! nil flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.id}") else flash[:notice] = "データベースへの保存に失敗しました" render("users/edit") end endSQLを直に作成して、ActiveRecord::Base.connection.execute(SQL)でMySQLのデータベースを直接更新する方法へ変えました。
(パスワードに関してもトラブルがありましたので、直接暗号化してから保存するコードに書き換えました)まとめ
プログラミング学習サイトの良いところは、手軽に言語の学習に手をつけられるところですね。しかし現実には実用レベルに達するためにいくつもの壁を越えなければいけないものなのだと実感しています。ローカルでは動いていたけれど、サーバー環境ではうまくいかないことが普通にあるのだとわかりました。これに懲りずにポートフォリオ作りに励もうと思います!
- 投稿日:2021-03-08T11:36:34+09:00
画像を投稿するときに、undefined method `images' for nil:NilClass担ってしまう問題を解決する
今回、Active Storageを使って、画像を投稿する機能を作りました。
しかし、投稿自体はあるものの、投稿から投稿一覧に遷移するときに、タイトルのエラーになってしまうという問題にぶち当たりました。結論から言うと、viewの引数の指定が間違っていたためです。なので、そこを修正してあげることで解決しました
以下、投稿一覧ページの、がぞうを表示する部分です
<% if @post.images.attached? %> <div class = 'images'> <% @post.images.each do |image| %> <%= image_tag post.images %> </div> <% end %> <% end %>こちらを間違えてしまってしました。
それを、こういった形に修正しました。
<% if post.images.attached? %> <div class = 'images'> <% post.images.each do |image| %> <%= image_tag image %> </div> <% end %> <% end %>このように、インスタンス変数を指定していいたのですが、それらを取っ払い、
image_tag
の部分のimages
を、image
に変えました。参考記事
- 投稿日:2021-03-08T11:36:34+09:00
画像を投稿するときに、undefined method `images' for nil:NilClassになってしまう問題を解決する
今回、Active Storageを使って、画像を投稿する機能を作りました。
しかし、投稿自体はあるものの、投稿から投稿一覧に遷移するときに、タイトルのエラーになってしまうという問題にぶち当たりました。結論から言うと、viewの引数の指定が間違っていたためです。なので、そこを修正してあげることで解決しました
以下、投稿一覧ページの、がぞうを表示する部分です
<% if @post.images.attached? %> <div class = 'images'> <% @post.images.each do |image| %> <%= image_tag post.images %> </div> <% end %> <% end %>こちらを間違えてしまってしました。
それを、こういった形に修正しました。
<% if post.images.attached? %> <div class = 'images'> <% post.images.each do |image| %> <%= image_tag image %> </div> <% end %> <% end %>このように、インスタンス変数を指定していいたのですが、それらを取っ払い、
image_tag
の部分のimages
を、image
に変えました。参考記事
- 投稿日:2021-03-08T10:52:43+09:00
カラムから外部キーを削除する
アプリを作成している中で外部キーを削除する必要が出てきたので今後のためにも記事を残します。
/schema.rb
create_table "behavior_histories", force: :cascade do |t| t.bigint "care_recipitent_id" t.date "behavior_history_date", null: false t.text "action_record", null: false t.time "behavior_time", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.bigint "family_id" t.index ["family_id"], name: "index_behavior_histories_on_family_id" t.index ["care_recipitent_id"], name: "index_behavior_histories_on_care_recipitent_id"この中の外部キーであるcare_recipitent_idを削除します。
migrationファイルの作成
rails g migration remove_foreign_key_to_behavior_histories外部キーの削除
class RemoveForeignKeyToBehaviorHistories < ActiveRecord::Migration[6.0] def change remove_foreign_key :behavior_histories, :care_recipitents remove_reference :behavior_histories, :care_recipitent, index: true end endrails:db:mirateで削除されていることを無事確認。
※remove_foreign_keyとremove_referenceの順序を変えるとうまくいかないため注意してください。
- 投稿日:2021-03-08T01:17:45+09:00
routes.rbのルーティングを他ファイルに分割した話
はじめに
本稿は、railsのroutes.rbに記述されたルーティングが数百行にも渡り、コードの可読性が欠けてしまっている場合において、自身がどのように見やすさを確保したのかを記載したものになります。
ルーティングを分割する
0. 編集前のconfig/routes.rb
※記載されている内容は例として設定しているだけなので、それぞれのルーティング名に関連性はありません。
config/routes.rbRails.application.routes.draw do namespace :api, format: 'json' do namespace :v1 do namespace :libraies do resources :libraries end namespace :books do resources :books end end namespace :v2 do namespace :libraries do resources :libraries do collection do get :borrowed_books end end resources :librarians do end end end end endこちらのroutes.rbをファイル分割していきます。
1. config配下に"routes"ディレクトリを作成する
2. config/routes.rbを編集
config/routes.rbRails.application.routes.draw do def draw(routes_name) instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb"))) end Rails.application.routes.draw do # ここに"routes_name"を定義します。 end end
- "routes_name"には
1. config配下に"routes"ディレクトリを作成する
で作成したroutesディレクトリ内に作成したファイル名を指定します。※まだconfig/routes配下にファイルを作成していないので、次で作成していきます。
分割先のファイルを用意
今回サンプルで作成したroutes.rbでは
- api v1
- api v2
この粒度で分割していきたいと思います。
そこで
api_v1.rb
とapi_v2.rb
という名前のファイルを作成します。touch config/routes/api_v1.rb
touch config/routes/api_v2.rb
3. routes.rbに作成したファイル名を指定する
config/routes.rbRails.application.routes.draw do def draw(routes_name) instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb"))) end Rails.application.routes.draw do draw :api_v1 draw :api_v2 end end4. api_v1.rbを編集
config/routes/api_v1.rbnamespace :api, format: 'json' do namespace :v1 do namespace :libraies do resources :libraries end namespace :books do resources :books end end end5. api_v2を編集
config/routes/api_v2.rbnamespace :api, format: 'json' do namespace :v2 do namespace :libraries do resources :libraries do collection do get :borrowed_books end end resources :librarians do end end end end終わりに
これでかなり見やすくなりました!
分割するタイミングはプロダクトによって様々だと思いますが、コードの可読性を上げるためにも管理ができる範囲でコードをどんどん外に出していくことは重要だと思います。
- 投稿日:2021-03-08T00:52:08+09:00
[Ruby] あるインスタンスのブロック内で、そのインスタンスのメソッドやインスタンス変数を使う方法
- 投稿日:2021-03-08T00:27:28+09:00
【個人開発】ファラオが情報共有し現代社会を生き抜くアプリ作りました
はじめに
こんにちはファラオ
世は情報社会、多くの人々がスマートフォンを持ち歩きTwitterなどで常に情報交換していますね
しかし、世で使われているSNSは現代の言語で書かれており、ファラオが使うのには少し不便なのではないでしょうか
今回はそんな情報収集に苦労しているファラオ達に使っていただけるSNSを開設しましたサービス概要
hieroglitter
ファラオ達がヒエログリフで情報を共有出来るアプリです
普段お使いの言語を入力すると、ヒエログリフに変換されて投稿されます
これで世界中のファラオと情報を共有出来ますね
※現在は日本語とアルファベットのみに対応しています使い方
こちらがトップページです
ファラオのプライバシーを守るためファラオログイン機能によって平民はフィルタリングしています
安心してお使いください
ファラオの皆さんならどこからファラオログイン出来るか一目瞭然ですね?
こちらがアプリのメインページです
ここから好きなように投稿してください
お気に入りの投稿を見つけたら猫ボタンを押すと好きなだけあなたの好意を伝えられます
使用技術について
Ruby on Rails 6.0.3.5
Yahoo ルビ振り API
https://developer.yahoo.co.jp/webapi/jlp/furigana/v1/furigana.html
漢字で投稿された際に内部でひらがなに変換していますgem 'miyabi'
https://rubygems.org/gems/miyabi/versions/0.1.1
ひらがな、カタカナをアルファベットに変換するのに使わせていただいていますgem 'pharaoh_lang'
https://rubygems.org/gems/pharaoh_lang
アルファベットをヒエログリフに変換するメソッドto_hieroglyphを提供するgemを自作しました
変換表はこちらを参考にさせていただきました
https://gist.github.com/souri-t/3bb9475c2710a55a10e71337d84ce2c3自作gemについて
アルファベットを対応するヒエログリフに変換して出力するメソッドを提供する単純なgemです
Unicodeはヒエログリフに対応しているので、A-Zまでそれぞれの音が対応するヒエログリフの文字コードをもとに文字列を変換しています
アルファベット以外はそのままの文字を出力します
※デプロイ後にノリで作成したのでせっかくなのでノリで使いましたおわりに
クソアプリ作ってみたかったので心が満たされました
自分の好きな感じのアプリが作れたかなと思います
就活用に作ってるポートフォリオそっちのけで作ったので、そっちが全然進んでませんが僕は元気です
よかったら遊んでみてくださいね
hieroglitter
ちなみにファラオファラオ言ってたらアプリの名前誰も覚えてくれなくてファラオSNSって呼ばれてます
このアプリはweb1week-202102に参加するために作りました。だら?FlutterとReactとLaravelと風来のシレン様、良い機会を下さりありがとうございました