みずラテ

牛乳と水を2対1で。

【Rails】ActiveRecord_Relationのインスタンスはなぜmapが使えるのか

やってみたこと

ActiveRecord_Relationのインスタンスを生成してみました。

User.all.class
#=> User::ActiveRecord_Relation

.allだったり、.whereで取得したレコードはActiveRecord_Relationクラスのインスタンスとなります。
そして、mapメソッドを使うとなんとArrayになります。

User.all.map { |v| v }

これで取得したレコードの配列を生成することが出来ます。

そして最後にActiveRecord_Relationクラスのインスタンスがmapメソッドを持っているか確認してみました。

User.all.class.methods.include?(:map)
#=> false

疑問

mapもってないじゃん。

なぜmapが使えるのか

答え

ActiveRecord::RelationがEnumerableモジュールをインクルードしていて、Enumerableモジュールはmapメソッドを持っているのでそれを使っている。と推理。

includeしている瞬間の映像はこちら。(githubのソースより。)
github.com

include Enumerable

Enumerableモジュールが持っているメソッドはこちら。
docs.ruby-lang.org

これによって、見事にmapメソッドを使うことが出来るのでした。


今回は、これで以上です。

Ruby on Rails 6 実践ガイド (impress top gear)

Ruby on Rails 6 実践ガイド (impress top gear)

  • 作者:努, 黒田
  • 発売日: 2019/12/20
  • メディア: 単行本(ソフトカバー)

【Ruby】メタプログラミングで動的にクラスとメソッドを定義する

やりたいこと

  1. メタプロで、動的にクラスとそのメソッドを定義したい。
  2. Api関係の部分使いたいので、Moduleの配下に定義したい。
  3. 動的に定義したクラスは他のクラスを継承した形にしたい。

方法

  • const_setを使っていく
  • define_methodを使っていく

結果

これでいける!勝つる!

module Hello
  class_list = ['Ohayo','Konnichiwa','Konbanwa']

  #親クラスHelloの動的定義
  const_set(:'Hello', Class.new do
    def hello
      puts 'hello.'
    end
  end)

  #親クラスを継承した子クラスOhayo, Konnichiwa, Konbanwaの動的定義
  #動的にメソッドも定義する
  class_list.each do |v|
    const_set(v.intern, Class.new(Hello) do
      define_method v.downcase do
        puts v + ' desu.'
      end
    end)
  end
end

#実際に使ってみる。

#Ohayoクラスの生成
hello = Hello::Ohayo.new
#親クラスのメソッド呼び出し
hello.hello # -> hello.
#子クラスの動的に定義したメソッドの呼び出し
hello.ohayo # -> Ohayo desu.

ポイント:Classクラスのnewメソッドを理解する

公式リファレンスマニュアルに以下の記載があります。
class Class (Ruby 2.7.0 リファレンスマニュアル)

new(superclass = Object) -> Class
new(superclass = Object) {|klass| ... } -> Class

どういうことか。

1行目については引数に継承したいクラスオブジェクトを入れると、継承してくれる。デフォルトはObjectクラスの子クラスとしてclassが定義される。

2行目についてはブロックを与えるとその中身はclassに紐づく。つまりブロック内にメソッドを直書きすれば良い。

この2点を理解すると、↑のコードは問題なく読めると思います。
あとは適当に外部から取得してきた風に配列の中にクラス名を格納して、順次クラス定義をしているのと、define_methodで動的にメソッド定義してみました。

誰かのお役に立てれば幸い。

今回は以上です。

メタプログラミングRuby 第2版

メタプログラミングRuby 第2版

【Ruby】なぜ動的にclassを生成する際にObject.const_setとなるのか

ふとした疑問のメモです。

やっていたこと

rubyのメタプログラミングで動的にクラスの生成を行いたくて調べていたところ、Object.const_setで生成出来ることがわかった。

疑問

まず以下を試してみてください。

Object.respond_to?(:const_set)
#-> true

Objectクラスはconst_setメソッドを持っていることがわかります。
一方で、以下のようにObjectクラスの親クラスであるBasicObjectクラスに同じメソッドがあるか見てみると、

Object.superclass
#-> BasicObject
BasicObject.respond_to?(:const_set)
#-> true

ありました。ということは、Objectクラスのconst_setメソッドはBasicObjectのメソッドを継承したものだということが分かります。

ちなみに

Class.superclass
#-> Module
Module.superclass
#-> Object
Class.respond_to?(:const_set)
#-> true

ClassクラスもModuleクラスもconst_setメソッドを持っています。

じゃあ、Object.const_setじゃなくて、BasicObject.const_setでも、Module.const_setでも、Class.const_setでもいいのでは?

というのが今回の疑問

実際、

Class.const_set :Foo, Class.new
#-> Class::Foo
BasicObject.const_set :Daa, Class.new
#-> BasicObject::Daa

Classクラスを継承したFooクラスを生成出来ます。

普通のクラスは何クラスを継承している?

じゃあ普通のクラスは何クラスを継承しているのでしょう。BasicObjectクラス?Objectクラス?Moduleクラス?Classクラス?
正解は

class Foo
end
f = Foo.new
f.class
#-> Foo
f.class.superclass
#-> Object

結果

ということで普通に定義して生成したFooクラスのオブジェクトはObjectクラスを継承していました。
今回はconst_setメソッドで動的に普通のクラスを定義してインスタンスを生成したいので、普通の静的なクラス定義生成したオブジェクトと同じ様に、そのインスタンスはObjectクラスを親クラスに持つ様に作ったほうが良さそうです。

なので、Object.const_setを使うという結論になりました。
じゃあ、なぜ普通のクラスのインスタンスはObjectクラスを継承しているの?という疑問出てきますが、それはリファレンスマニュアルを見てみると、
class Class (Ruby 2.7.0 リファレンスマニュアル)

new(superclass = Object) -> Class

newメソッドの引数にはsuperclassを指定できて、デフォルトがObjectクラスだからなんですね。

ようやく腹落ちしました。

結論

おとなしくObject.const_setメソッドを使ってclassの動的定義をしていきたいと思います。

今回は以上です。

djandjan.hateblo.jp

【在宅育児】そろそろ限界な3歳児

在宅育児2週間目

保育園から登園自粛要請をもらって在宅育児に切り替えてから1週間が経ちました。我が家では僕も妻も奇跡的に在宅勤務を許されているので二人で子供を見ているのですが、結構娘もストレス溜まってきたのかなーと感じ始めました。

妻が結構ビデオ会議をする都合上、基本的には僕と娘が同じ部屋に籠もって仕事をしています。Youtubeを見させたり、保育園でやっているABCマウスという英語教材のアプリで遊ばせたりしています。

直近では、僕が「おしごと」と言って、PCでカタカタやっているので、娘も「おしごとしたい!」と言い出しました。何をしたかったかというとキーボードでカタカタやりたかったみたいで、メモ帳を出して、ひらがな入力モードに切り替えて上げたら、文字を打って楽しく遊び始めました。自分の名前を打ったり、保育園のお友達の名前を打ったりしています。僕が3歳の頃と比べるとすごい高度な遊び・・・笑

Youtubeでは「ペッパピッグ」というアニメをよく見ているのですが、外国のアニメなので、英語版やスペイン語版の動画も有るのですが、ちょっと目を話した隙にスペイン語版の動画を見始めていて割とおとなしく集中して見ていることがありました。まさか理解している・・・?予期せぬグローバリゼーションを肌で感じています。

そんな感じで集中しているときは1時間くらい持つのですが、最近はその集中も切れがちになってきて、すぐに僕のPCの前に来て肩車をねだったり、パソコンの画面を見せろと言ってきたり、机の下に入り込んでくるようになりました。

やっぱりずっと家にいて、保育園の友達とも遊べず、そろそろつまらなくなってきたのかなと感じています。

お昼休みの1時間の中で、ご飯を早く食べて一緒に散歩に出かけるようにしていますが、お散歩も出来て20分くらい。運動量が全然足りないですね。普段は保育園で午睡をしていますが、在宅保育のこの1週間、午睡が出来たのは1日だけで、それ以外は夜まで一度も寝ず、晩御飯を食べてすぐに電池が切れてパタリと寝るというパターンが多くなっています。これも良くないなと思っていて、保育園の生活パターンからどんどん外れていっている気がします。

取れる対策はあるのか

正直、この状態でずっと仕事したり生活したりするのは難しいですね。僕としても妻としても仕事はしなくちゃいけないし、あまり娘に日中かまってあげることが出来ない。おもちゃやYoutubeに頼るしかない。とはいえそれもあまり長続きしない。手詰まり感があります。

割と恵まれている方であることは認識していますが、下手すると年単位で考えていく必要があり、本格的に生活のあり方を考えていく必要がありそうですね。うーんツライ。

とりあえず現況についてとりとめなく書いて以上です。

リモートチームでうまくいく

リモートチームでうまくいく

  • 作者:倉貫義人
  • 発売日: 2016/01/29
  • メディア: Kindle版

Rails - Create Object from nested hash of JSON data by dry-struct

Now I am wondering to migrate a gem virtus to other new gem. And I tried dry-struct and dry-types. Here is the result of creating Rails Model Object from nested hash of JSON data.

What I would like to do

I prepared a sample data as below. The data is like JSON data and it has nested struct. Then the final expected result is to have auther object(Auther Class) and books objects(Array[Book Class]).

json_data = <<EOS
{
  "status": "0",
  "message": "",
  "author": {
    "id": "auther111",
    "name": "akutagawa"
  },
  "books": [
    {
      "id": "book111",
      "name": "rasho-mon",
      "publishedyear": "1915"
    },
    {
      "id": "book222",
      "name": "kumonoito",
      "publishedyear": "1918"
    },
    {
      "id": "book333",
      "name": "ababababa",
      "publishedyear": "1923"
    }
  ]
}
EOS

My environment

Rails 6.0.2
Ruby 2.5.7

Install dry-struct

At first, let's install gem dry-struct. It will install other related gems such as dry-types.

gem 'dry-struct', '~> 0.5.0'

bundle install

Initial setting

follow the way that the official document instruct.
dry-rb.org

create new file types.rb at initializers like below.

module Types
  include Dry.Types()
end

Create Classes

Create three classes Author, Book, and GetAuthorInfo. All of them has to be inherited by Dry::Struct.

class Book < Dry::Struct
  attribute :id, Types::String
  attribute :name, Types::String
  attribute :publishedyear, Types::String

  def title_call
    "The name of the book is" + name + "."
  end
end

class Author < Dry::Struct
  attribute :id, Types::String
  attribute :name, Types::String

  def my_name
    "My name is" + name + "."
  end
end

class GetAuthorInfo < Dry::Struct
  attribute :status, Types::String
  attribute :message, Types::String
  attribute :author, Author
  attribute :books, Types::Array.of(Book)
end

Usage

Let's use it. When get JSON data and parse it to hash(need to symbolize it) and put it to initial value of the GetAuthorInfo class, the nested object will be created!

parsed_data = JSON.parse(json_data, symbolize_names: true)
autherInfo = GetAuthorInfo.new(parsed_data)
autherInfo.auther.myname

Ofcourse you can call method of the class from the object. Try more.

autherInfo.books.size
autherInfo.books[1].title_call

Wonderfull!

Thank you for reading by post.

新型iPhone SEが大きくなった理由、もといスマホの巨大化の理由について

※この記事は、僕の個人的主観(N=1)ですのでご了承ください。

ついに!

新型iPhone SEの発表がようやくきましたね!僕は新型iPhone SEは4インチのベゼルレスを期待していましたけどね。残念。噂がで始めた時点で半年前くらいからすでに諦めていたので大人しく予約しようと思います。旧SEよ、さらばっ!4年近くありがとう!

ところで、


どうして4インチを出してくれないんだ!どうして最新のスマホは大きいスマホばかりなんだ!


と嘆いたことはないでしょうか。日本国内では特に小さいスマホの需要は大きい気がしているのに・・・。

今回はそのなぜ?!について以前考えた事について書いてみます。

観測範囲の出来事

仕事柄、海外の同僚とよくチャットツールでコミュニケーションを取っていた時期がありました。海外ではLINEの代わりにWhats app(ワッツアップ)というアプリがよく使われていますね。

その時、どうやって英語の文章を作成しているかというとqwerty式のキーボードに切り替えて両手で打ちます。qwertyのキーボードは片手じゃ打ちにくいし、スピードが出ません。両方の親指で操作します。外国人の同僚を見ても同じように打っていましたし、なんなら海外旅行で現地をぶらついてスマホをいじっている人を観察するとほぼ全ての人が両手でスマホを操作しています。

その時、僕は「これだ!」と合点したのでした。

両手で打つと4インチスマホは小さくて不便

そうなんです。両手でqwertyキーボードを打つとキーボードが小さい。押し間違えなんてしょっちゅうです。両手で英語の文章を作るときのみ、「もうちょっと大きかったらなー」と思うことがありました。逆に片手で操作する分には4インチスマホは右親指だけで安定して全ての操作が可能です。大きいと重くなるし、親指が届かない範囲が出来てきます。

世界の両手打ちの需要は大きいスマホ

身長の高さに比例して手の大きさも大きくなるみたいですので、比較的身長の高い欧米の方々にとっては小さいスマホだと両手打ちする時に打ちにくい→よって大きい打ちやすいスマホに人気がある!という綺麗な理論が完成しました。めでたしめでたし。

とはいえ

やっぱり残念ですが、新型iPhone SEが現時点で一番小さい中で一番性能の良いiPhoneとなったので、これを買ってまた次回に期待したいと思います。(小さいスマホの世界に戻ってくることはないんだろうなーと思いつつ。。)

今回はこのくらいです。

Apple レザーケース (iPhone SE用) - (PRODUCT)RED

Apple レザーケース (iPhone SE用) - (PRODUCT)RED

  • 発売日: 2020/04/24
  • メディア: エレクトロニクス