LoginSignup
19
10

More than 1 year has passed since last update.

問題です! ①と②が同じだって分かりますか?(クラス・インスタンス・メソッド・引数を実践で理解しよう!)

Last updated at Posted at 2020-09-09

はじめに

突然ですが、質問です。
書き方は違いますが、①と②が同じだって分かりますか?

User.rb(某アプリのモデルと仮定してください)
# Userのアソシエーションはこのようになっています
#   has_many :posts, dependent: :destroy
#   has_many :active_relationships, class_name: 'Relationship',
#                                   foreign_key: 'follower_id',
#                                   dependent: :destroy
#   has_many :passive_relationships, class_name: 'Relationship',
#                                    foreign_key: 'followed_id',
#                                    dependent: :destroy
#   has_many :following, through: :active_relationships, source: :followed
#   has_many :followers, through: :passive_relationships, source: :follower

# Userモデルのメソッドです
def feed 
  Post.where(user_id: following_ids << id) #=> ①
end

def feed
  Post.where(:user_id => self.following_ids.<<(self.id)) #=> ②
end

分からない方は、読んで勉強になることがあるかもしれません。
よければ読んでいただけると幸いです。

書くに至った経緯について

はじめまして。みけたと申します。
3月末で公務員を辞めて、Railsなどの勉強を始めて5ヶ月近く経過します。

主にMENTAというサービスでだいそんさんという方にお世話になっており、
スパルタコースというコースを受講しながら、日々勉強に励んでおります。

様々な課題が課されるのですが、その課題の1つがインスタクローンの実装です。
現在、私はこの実装に取り組んでいるところです。

先日、後発で受講を始めたメンティーさんからトップ画面にフィードを表示させる機能について、
コミュニティ内で質問がありました。

私はその範囲の実装を既に終えており、勉強がてらに質問に答えてみようと思ったのですが、
実力不足で答えられるほどの力がなかったので、改めて調べて、全力で答えてみることにしました。

それなりに気合を入れて答えたので、コミュニティ外の初学者の方にも何か役に立てばと思い、
Qiitaという形で公開してみることにしました。

前提条件について

Image from Gyazo

自身の投稿とフォローしているユーザーの投稿がトップページに表示される仕様となっています。

Userモデルにfeedというメソッドを実装して、posts_controller.rb
indexアクションにて該当の投稿を取得し、Viewにその投稿を渡すようなコードを書くのですが、
このfeedメソッドについて質問がありました。

アソシエーションについて

20200908_feed-method.png
以上のような構成図となっています。

なお、タイムスタンプ(created_atとupdated_atのカラム)は省略しています。
また、ER図の書き方は勉強不足のため、誤りがある可能性が高いです。。。

とりあえず、usersはたくさんのpostsを持っていて、@user.followingと書けばフォローしている
ユーザーが取得できることが分かれば、今回の記事は十分に理解できるかと思います。

なお、アソシエーションについては、この記事では説明しません。
以下の記事などを参考にするとよいかと思います。

質問

current_user.feedで何をやっているのか分からない!!!

該当のコードについて

posts_controller.rb
def index
  @posts = if current_user
             # このcurrent_user.feedが分からない!!!
             # feedメソッドについては、user.rbを参照してください
             current_user.feed.includes(:user).page(params[:page]).order(created_at: :desc)
             # 以下、省略
user.rb

# == Schema Information
#
# Table name: users
#
#  id               :bigint           not null, primary key
#  avatar           :string(255)
#  crypted_password :string(255)
#  email            :string(255)      not null
#  salt             :string(255)
#  username         :string(255)      not null
#  created_at       :datetime         not null
#  updated_at       :datetime         not null
#
# Indexes
#
#  index_users_on_email  (email) UNIQUE
#

class User < ApplicationRecord
  authenticates_with_sorcery! # sorceryというgemを使っています

  mount_uploader :avatar, AvatarUploader # carrierwaveを使っています(今回の説明では関係ない)

  # validationは関係ないので省略します

  # post.rbやcomment.rbなどで適切にアソシエーションが設定されていると仮定してください
  has_many :posts, dependent: :destroy
  has_many :comments, dependent: :destroy
  has_many :likes, dependent: :destroy
  has_many :like_posts, through: :likes, source: :post
  has_many :active_relationships, class_name: 'Relationship',
                                  foreign_key: 'follower_id',
                                  dependent: :destroy
  has_many :passive_relationships, class_name: 'Relationship',
                                   foreign_key: 'followed_id',
                                   dependent: :destroy
  has_many :following, through: :active_relationships, source: :followed
  has_many :followers, through: :passive_relationships, source: :follower

  # 色々とメソッドがあるんですが、関係ないので省略します

  # このfollowing_idsとか<<とか、何なの!?
  def feed
    Post.where(user_id: following_ids << id)
  end
end

なお、includes(:user).page(params[:page]).order(created_at: :desc)
についてはこの記事で取り扱いませんが、気になる方は適宜調べてください。

補足をしておくと、page(params[:page])と書けるのはkaminari
というgemを導入しているからです。

クラス・インスタンスの概念を把握する

まず、クラスとインスタンスの関係について自分なりに説明します。
これは個人的な理解なので、誤った解釈を導く可能性があります。
参考程度にお聞きください。

誤解を恐れずに言いますと、こんな感じです。
クッキーの型取りする銀色のやつと、実際に型取りされたクッキーの関係に似てますかね笑

  • クラス: 抽象的な概念としての型
  • インスタンス: 型から縁取られて出てきた具体的な個体

例えば、概念として「犬」という言葉を私たちは理解してますけど、
その時点で理解している「犬」というのは、すごいふわふわしたものです。

別に柴犬でもダックスフンドでも犬ですし、同じ柴犬でも大きさが微妙に違います。
けど、概念としての犬であることには違いないわけで、それを私たちは全て犬として認識しています。

この認識している概念としての犬こそが、クラスとしての犬です。
(便宜的に、犬クラスは犬種と長さという属性を持つクラスだと定義しましょう。)

ただ、この世界に存在するのは、全て具体的な犬です。
犬インスタンスです! 犬オブジェクトです!

犬インスタンスは、属性(attributesというやつです)を持っています。
犬インスタインス(id:1)は、犬種:柴犬、長さ:1mという属性を持っているかもしれませんが、
犬インスタンス(id:2)は、犬種:ダックス、長さ:50cmという属性かもしれません。

ちなみに、英語が多少できる人なら、インスタンスの意味から覚えるといいかもしれません。
インスタンスは、for example と同じ意味の for instance の instance です。
クラスの具体例なので、インスタンスって言うんですね!・・・きっと笑

メソッドについて考える

クラスとインスタンスについて把握して上で、メソッドについて考えてみましょう。
メソッドというのは「できることリスト」みたいなものです。

便宜的に、犬クラスは「走る」というメソッドを持っている、ということにしましょう。

犬クラスというのは概念的なものなので、走ることはできません。
走らせるとエラーになります。走れるのは犬インスタンスだけです。
(User.saveなどと書いてエラーになったとき、犬クラスは走れないことを思い出しましょう)

逆に犬オブジェクトから、犬種(という属性)が柴犬である犬を探すことはできません。
柴犬を見つけてきたい場合、犬クラスから探しましょう。
(@user.whereなどと書いてエラーになったとき、あなたはペットのゴン太という柴犬から、
柴犬を探そうとしているなんだか残念な人だという自覚を持ちましょう)

current_userって何?

かなり冗長に説明しましたが、そろそろ具体的に考えていきましょう。
まず、current_userから考えてみましょう。

current_userは、sorceryというgemを導入することにより使えるメソッドです。
公式GitHubをみると、そのメソッドのコードが書いてあります。

# attempts to auto-login from the sources defined (session, basic_auth, cookie, etc.)
# returns the logged in user if found, nil if not
  def current_user
    unless defined?(@current_user)
      @current_user = login_from_session || login_from_other_sources || nil
    end
    @current_user
  end

# https://github.com/Sorcery/sorcery/blob/a02c1247642357129ea739354c22978a06fccaa9/lib/sorcery/controller.rb#L87
# 87行目にcurrent_userメソッドが記載されています

え、メソッドなの!? と思われたあなた!
その発想が出てくるのは非常によいと思います!(初学者のくせに偉そう・・・)

辿っていくと分かりますが、sessionのuser_idを使って、
Userクラスから該当のユーザーを取得すると書いています。

なので、まあ結果として、current_userは、Userクラスのインスタンス
として考えてほぼ差し支えありません。

ただ、正確にはcurrent_userはメソッドであって、その返り値がUserクラスの
インスタンスになるように設計されていることを覚えておいてください。

feedって何クラスの何メソッド?

feedというメソッドですが、Userモデル(Userクラス)のインスタンスメソッドです。
インスタンスメソッドなので、userインスタンスのみ実行できます。

先ほど言ったとおり、current_userはメソッドではあるのですが、
そのメソッドを実行した結果として、Userクラスから該当のログインユーザーを取得します。
(面倒なので、以後このログインユーザーをcurrent_userと呼びます)

このcurrent_userは、userインスタンスであるため、
Userモデルのインスタンスメソッドであるfeedというメソッドが使ます。

クラス インスタンス メソッド
User current_user feed

current_userfeedメソッドを実行すると、
Post.where(user_id: following_ids << id)の返り値を取得します。

current_user.feed
#=> `Post.where(user_id: following_ids << id)`の返り値を取得

feedメソッドの中身を見ていく(following_idsとは)

続いて、Post.where(user_id: following_ids << id)を見ていきます。

特に見慣れない部分がfollowing_ids << idの箇所だと思います。
私もこれを見て、「え、あ、えと、分からない、ごめんなさい」ってなりました 笑
おそらく、多くの初学者にとって、ここが1番のつまづきポイントだと思います。

following_idsですが、これはアソシエーションでhas_many書くと使えるメソッドです。
「え、メソッド!」と思ったかもしれませんが、Railsガイドに書いてます。

collection_singular_idsメソッドは、そのコレクションに含まれるオブジェクトの
idを配列にしたものを返します。

4.3.1.6 collection_singular_ids - Railsガイド

ちなみに、@user.commentsと書くときのcommentsも実はメソッドです。

collectionメソッドは、関連付けられたすべてのオブジェクトのリレーションを返します。
関連付けられたオブジェクトがない場合は、空のリレーションを1つ返します。

@books = @author.books

4.3.1.1 collection - Railsガイド

@user.commentsと書くとき、.commentsと続けると@userに紐づくコレクションを
取得できるという覚えゲーでもあまり問題ありません。

むしろ、そう覚えても問題ないよう設計されているRailsが素晴らしいんです。
ただ、実はこれもメソッドだと知っておくと、理解がより深まっていくのではないでしょうか。

binding.pryを使ってみよう

では、binding.pryを使って、following_idsの挙動を確認しましょう。

まず、posts_controller.rbのindexアクションにbinding.pryって書きます。
書く場所は、ここにします。

gem 'pry-rails'は導入しておいてください。
導入方法や使い方は、この記事などを参考にするとよいでしょう。

 def index
    binding.pry
    @posts = if current_user
               current_user.feed.includes(:user).page(params[:page]).order(created_at: :desc)

    # 省略

binding.pryと書いた後、ブラウザでトップ画面をリロードしましょう。
すると、リロードしている状態で画面が止まるはずです。

ターミナルで確認してみると、rails cの時と同じような形でデバッグができます。

デバッグを始める前に、しつこいですが、クラスとインスタンスとメソッドのことを思い出しましょう。
following_idsは何ですか。そう、メソッドですよね。では、何のメソッドでしょう。

そう、インスタンスのメソッドですよね。

具体的なコレクション(複数のオブジェクト)がコレクションの各IDを返すメソッドなので、
これはインスタンスメソッドです。

なので、いきなりfollowing_idsと書くとエラーになります。

今回はログインしているユーザーがフォローしているユーザーたちのID、つまりfollowing_ids
取得したいので、current_user.following_idsと入力してみましょう。

フォローしているユーザーがいれば、配列が返ってくるはずです。

binding.pryを使った際のターミナルの画面
Processing by PostsController#index as HTML

From: 〜〜〜/app/controllers/posts_controller.rb @ line 5 PostsController#index:

     3: def index
     4:   binding.pry
 =>  5:   @posts = if current_user
     6:              current_user.feed.includes(:user).page(params[:page]).order(created_at: :desc)

[1] pry(#<PostsController>)> current_user.following_ids
  User Load (1.0ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 7 LIMIT 1
  ↳ (pry):6
   (1.6ms)  SELECT `users`.`id` FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 7
  ↳ (pry):6
=> [3, 10]

ここで、もしかしたら疑問に思ったかもしれません。

「あれ、feedメソッドではcurrent_userなんて書かずにfollowing_ids
入力していたような気がするけど、なんでだろう???」と。

selfは省略されている

モデルで書くインスタンスメソッドですが、ここではselfが省略されています。
つまり、こういうことです。

# ①と②は同じ

Post.where(user_id: following_ids << id) #=> ①
Post.where(user_id: self.following_ids << self.id) #=> ②

ちなみに、scivolaさんにご指摘いただきましたが、解釈の順番はこうなっています。

Post.where(user_id: (self.following_ids << self.id))

どうですか?
分かりやすくなったと感じた方もいるかと思います。

では、current_user.feedと書いた場合について考えてみましょうか。
要はこういうことが起きています。

Post.where(user_id: current_user.following_ids << current_user.id)

続いて、id: 1であるユーザーについて考えみましょう。
要はこういうことです。

Post.where(user_id: User.find(1).following_ids << User.find(1).id)

だいたい分かってきたんじゃないでしょうか。

ここではselfが省略されていますが、インスタンスが持っているメソッドが使用されていたり、
インスタンスが持っている属性の取得が行われているのです。

奥さん、<<ってメソッドなんですって

タイトルのとおりですが、「<<」はメソッドなんです。
え、メソッドって文字じゃなくていいんですか。。。 これはさすがにビビりますよね。
(私だけですかね。。。)

これは、Array(配列)クラスのインスタンスメソッドなんです。

ary = [1]
ary << 2
p ary # [1, 2]

では、振り返っていきましょう。
current_user.feedと書く場合、following_ids << idがどういう挙動になるか確認します。

# current_user(id: 1)が、`id: 4`と`id: 6`のユーザーを2人フォローしていると仮定

current_user.follwing_ids << current_user.id
[4, 6] << 1
[4, 6, 1]

分かりましたか。
つまり、フォローしているユーザーのidの配列に対して、自分のユーザーidを加えているのです。

そういえば、引数って分かりますか?

先ほどの事例の場合、難しいところがなかったので、すっと理解できたかと思います。
ただ、重要になってくるので、ary << 2 と書く時、2は引数であると覚えてください。

抽象的に説明しても分かりづらいので、まず引数があるメソッドと引数がないメソッドを見てみましょう。
大して犬好きでもないんですけど、犬の例で説明してしまっているので、初志貫徹したいと思います。

Class Dog

  # 本当はここに色々なくちゃいけないと思いますが、とりあえずスルーします

  def bark
    "わんわん"
  end

  def run(speed)
    "#{speed}キロでダッシュした!"
  end

end

ちゃんとした方々に怒られそうですが、Dogというクラス、つまりDogという抽象的な概念があって、
その型から生み出されたdogインスタンスには、barkrunというメソッドがあると想定してください。

じゃあ、dogインスタンスを誕生させましょう。

本当はdogという変数にすることが一般的なんでしょうけど、
せっかくなので愛着を持って、wankoという変数にしましょう。

wanko = Dog.new

このwankoですが、barkrunができます。

wanko.bark #=> "わんわん"
wanko.run(100) #=>  "100キロでダッシュした!"

無理させて100キロでダッシュさせてしまいましたが、この100というのが引数です。

メソッド内で変数を扱いたい場合、・・・と言うと分かりづらいので言い換えます。

引数を使うと走る速度に幅を持たすことができて、それはなぜかというと、
引数という「?」な速度をメソッド内に仮で書いておくことで、後から代入させる設計にできるからです。

この引数ですが、Rubyだと括弧を省略してこのように書くこともできます。
この書き方、個人的には気持ち悪いですが、この自由な感じこそがRubyの特徴らしいです。

wanko.run 100 #=> "100キロでダッシュした!"

following_ids.<<(id)って書いてもいいんですよ

さて、冗長な引数の説明にイラだった方もいるかもしれないですが、
それは<<がメソッドであり、idが引数だっていうことを改めてよく知ってほしいからです。

だって、メソッドって多くの場合どうやって書きますか?
そう、wanko.run(100)っていうのがよく見る形ですよね。

それにもかかわらず、following_ids << id<<がメソッドだって言われてもしっくりこないのは、
<<のインパクトもさることながら、書き方がよく見る形ではないからだと思うんです。

ということで、書き換えてみましょう。
こんな感じで。

following_ids.<<(id)

これまでと雰囲気が一転したので、すごく気持ち悪い感じになってしまいましたが、
<<はメソッドであって、idは引数なので、これでいいんです!!!

・・・これで動くのか疑問に思った方、いるかと思います。

私も理論専攻で先走ってこの文章を書いていたので、動くのかちょっと不安でした。。。
ただ、書き換えてみたら、やっぱりちゃんと動きました! よかった!

ちなみに、<<と似たappendpushといった似たメソッドがあります。
なので、こんな感じで書き換えることが可能です。
<<は単一の要素、appendpushは複数の要素を追加できるメソッドという違いがあります)

# ①と②と③は同じ
# following_ids << id の書き換え

following_ids.<<(id) #=> ①
following_ids.append(id) #=> ②
following_ids.push(id) #=> ③

user_id: following_ids << idについて考えよう

さて、徐々に範囲を拡大しましょう。
user_id: following_ids << idについて考えましょう。

これは、ハッシュというやつです。
ハッシュは、キーと値の組み合わせでデータを管理するオブジェクトのことです。(チェリー本のP147)

キー
:user_id following_ids と current_user.id

:user_idというシンボル形式のキーがあって、
その値がfollowing_idscurrent_user.idです。
(フォローしているユーザーのids + ログインユーザーのid)

このハッシュが、whereというメソッドの引数になっていると認識しましょう。

:user_idがどこから出てきたのか分からないあなた、
さらっとでよいので、ハッシュやシンボルについて勉強しましょう!

勉強をすると、以下のとおり書き換えができることも分かるはずです。

Post.where(user_id: following_ids << id)
Post.where(:user_id => following_ids << id)

ちなみに、=>を使う書き方は、ハッシュロケット記法といいます。
ハッシュロケット記法は、古い記法です。

未だにアプリなんかで使っていると古いコードをコピペしたのがバレます笑
=>が出てきたら、書き換えをするのを怠らないようにしましょう。

whereメソッドについて考えよう

さて、そろそろ全体を理解することができそうですね。
次は、whereメソッドについて理解しましょう。

whereメソッドですが、これはPostというクラスに対して実行するクラスメソッドです。
(若干不安ですが、たぶんクラスメソッドと言い切って良いと思います)

whereメソッドには引数があり、様々な形で書くことができます。

# 文字列で検索
Post.where("body = 'みけたさんカッコイイですね'")


# ハッシュ形式で検索
Post.where(body: 'みけたさんカッコイイですね')

さて、Post.where(user_id: following_ids << id)の場合において、
whereメソッドの引数が何になるのか考えましょう。

user_id: following_ids << idはどのような形式になるのでしょうか。

既に考察したとおり、user_id: following_ids << idはハッシュ形式になります。
そのことを踏まえて、また順を追って、具体的な事例に即して理解していきます。

# Post.where(user_id: following_ids << id)について
# current_user(id: 1)が、`id: 4`と`id: 6`のユーザーを2人フォローしていると仮定

Post.where(user_id: current_user.follwing_ids << current_user.id)
Post.where(user_id: [4, 6] << 1)
Post.where(user_id: [4, 6, 1])

Railsガイドでは、この事例の場合においてどのようなSQLが発行されるか説明しています。

そう、発行されるSQLは、以下のとおりですね。
whereメソッドは、Post全体の中からuser_idが条件に合致するものを探しているのです。

SELECT * FROM post WHERE (posts.orders_count IN (4,6,1))

まとめ

さて、冒頭から最後まで流れを追って確認しましょう。
すんなりと理解できるようになっていないでしょうか。

# Postクラスのオブジェクトであるcurrent_userがfeedメソッドを実行し、返り値を取得
current_user.feed

# では、feedメソッドの中身を見ていきましょう
def feed
  Post.where(user_id: following_ids << id)
end

# feedメソッドをcurrent_userが使ったので、①と②は同じ
current_user.feed #=> ①
Post.where(user_id: current_user.following_ids << current_user.id) #=> ②

# current_user(id: 1)が、`id: 4`と`id: 6`のユーザーを2人フォローしていると仮定する
Post.where(user_id: [4, 6] << 1)
Post.where(user_id: [4, 6, 1])

【補足】 破壊的メソッドと非破壊的メソッド

# current_user(id: 1)が、`id: 4`と`id: 6`のユーザーを2人フォローしていると仮定

current_user.follwing_ids << current_user.id
[4, 6] << 1
[4, 6, 1]

分かりましたか。
つまり、フォローしているユーザーのidの配列に対して、自分のユーザーidを加えているのです。

以上のように書きましたが、正しい理解をする上で、<<current_user.following_idsという
インスタンス自体を変更し、その変更した配列自体を返り値として返す「破壊的メソッド」であるという
ことを押さえておく必要があります。(scivolaさん、ありがとうございます)

え、どういうことかって。
こういうことです。

# `<<`は、current_user.following_ids自体を変更し、その変更したcurrent.following_ids自体を返す
current_user.follwing_ids << current_user.id
[4, 6] << 1
[4, 6, 1]

# current_user.following_idsを実行してみる
current_user.following_ids
[4, 6, 1]

実は、インスタンス自体は[4, 6]のままで変更しないけど、
返り値として[4, 6, 1]を返す+という非破壊的なメソッドもあります。

# `+`は、current_user.following_ids自体を変更しない
# current_user.idは配列形式にする必要がある
# Integer型の値を引数とする場合、to_aryメソッドによる暗黙の型変換を試みるが、TypeError: no implicit conversion of Integer into Arrayが発生
current_user.follwing_ids + [current_user.id]
[4, 6] + [1]
[4, 6, 1]

# current_user.following_idsを実行してみる
current_user.following_ids
[4, 6]

メソッドの返り値が何なのか意識することで、レベルアップが図れます!(どの立場・・・)

【補足】 アソシエーションしている場合の<<メソッドもあります!

話の流れ上、完全に話の腰を折るので最後に付け足すように書きましたが、
実は<<メソッドには違うものがあります。
(とはいっても、その違いをあまり意識することなく使えるよう設計されていますが)

まずRailsガイドを見てください。

collection<<メソッドは、1つ以上のオブジェクトをコレクションに追加します。
このとき、追加されるオブジェクトの外部キーは、呼び出し側モデルの主キーに設定されます。

@author.books << @book1

4.3.1.2 collection<<(object, ...) - Railsガイド

つまり、アソシエーションしている場合に使える<<メソッドというのがRailsで定義されていて、
この<<メソッドを使う場合、オブジェクト自体を追加することができるんです。

# current_user(id: 1)が、`id: 4`と`id: 6`のユーザーを2人フォローしていると仮定
# 表現が難しいので、イメージで書きます

current_user.following << current_user
[User.find(4), User.find(6)] << User.find(1)
[User.find(4), User.find(6), User.find(1)]

# 各userオブジェクトには、ユーザーの属性であるusernameやemailなどが保管されているとイメージしてください

ちなみに、先ほどの事例においては配列のように表現してしまいましたが、
正確にはCollectionProxyというクラスのオブジェクトです。
(scivolaさん、ありがとうございます)

# current_user(id: 1)が、`id: 4`と`id: 6`のユーザーを2人フォローしていると仮定
# 長くなるので、パスワード関係やcreated_atなどは省略します

current_user.following << current_user

# 以下がcurrent_user.following
 [<User:0x00007fc5677d2f10
  id: 4,
  email: "number4@example.com",
  username: "4番さん",
  avatar: nil>,
 <User:0x00007fc5677d2740
  id: 6,
  email: "number6@example.com",
  username: "6番さん",
  avatar: nil>
]

# 以下がcurrent_user
 <User:0x00007fc54dbced18
  id: 1,
  email: "number1@example.com",
  username: "1番さん(ログインユーザー)",
  avatar: nil>

# current_user.following << current_user
[<User:0x00007fc5677d2f10
  id: 4, #=> 以下省略>,
 <User:0x00007fc5677d2740
  id: 6, #=> 以下省略>,
 <User:0x00007fc54dbced18
  id: 1, #=> 以下省略>
]

なお、もし英語が苦手でなければ、こちらを参照してもよいかもしれません。
事例つきで、挙動について紹介してくれています。

【蛇足】 dashはいいぞ!

私はdashを愛用しています。
メソッドについて調べる時に、非常に便利です。

Image from Gyazo

さくっと調べることができて、使い方や引数も分かります。

英語なのがネックですが、日本語だと情報量が限られるのでそこは我慢しましょう。

Google検索だと調べるのに時間がかかるところ、数秒で調べられるのはメリットです。
気軽に調べられると、調べる回数が増えます!!

また、英語が苦手な方は、翻訳機能が使えるようなカスタマイズをしてみてはどうでしょう。
試せていないですが、こんなQiita記事を上げている方がいました。

Qiita等でも結構紹介されているので、Dashの導入を検討してみてください。
体験版がダウンロードできるので、是非試してもらいたいです。これは本当に便利です!

有料なものはちょっとという方は、DevDocsを使うとよいかもしれません。
最近試したのですが、単純調べるだけであればこちらでも十分かもしれません!

19
10
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
10