Upgrade to Pro — share decks privately, control downloads, hide ads and more …

生活発表

 生活発表

8aebb410308ec2c655550798e92cd2df?s=128

ken3ypa

June 28, 2019
Tweet

Transcript

  1. 生活発表 @ken3ypa

  2. 最近読んでる本

  3. EffectiveRuby RubyのTips集 各章が独立していて、どこからでも読める Amazonレビューによると、おすすめは「Ruby1‑2年目の方」とい うことで、レベル感的にもちょうど良さそう あなたのRubyをより輝かせる48の特別な方法

  4. 今回はそこで知ったテクニック + αをご紹介

  5. Struct/OpenStruct 構造体(Struct)を定義できます 構造体:配列とハッシュの性質を併せ持ったようなクラス いろんな方法でメンバーにアクセス出来る メンバー 属性とかkeyとか…そんな感じのものなので適宜読み替えてく ださい 用語はRuby逆引きハンドブックに準拠

  6. 定義とアクセス 定義方法 Struct.newで構造体サブクラスを定義 引数にはメンバの名前をシンボルを指定 構造体サブクラスにあるnewクラスメソッド の引数に、メンバ ーの値を渡すことで設定出来る newが二回出てきて紛らわしいが別物 Struct vs

    OpenStruct Structはメンバを静的に扱う(定義したあとから追加できない) OpenStructは動的に扱う(定義したあとでも追加できる)
  7. 定義とアクセス User = Struct.new(:name, :age) ken = User.new("Ken", 29) p

    ken.name #=> "Ken" p ken[:name] #=> "Ken" p ken["name"] #=> "Ken" p ken[0] #=> "Ken" 使い勝手としては、属性を集積したいときに新しいクラスを作るま ででもないが、Hashよりは色々やりたいときに良さそう
  8. Classクラス/Structクラス Classと似てる所: newしてインスタンスを作成できる クラスメソッド 、インスタンスメソッドを定義出来る 属性をセット出来る というかStructも立派なクラスなので、上記の性質を持ちます p Struct.class #=>

    Class p Struct.ancestors #=> [Struct, Enumerable, Object, Kernel, BasicObject]
  9. Classクラス/Structクラス # Class class User attr_reader :name, :age def initialize(name,

    age) @name = name @age = age end def instance_method "#{name} さんは#{age} 歳です" end def self.klass_method " クラスメソッドです" end end # Struct User = Struct.new(:name, :age) do def instance_method "#{name} さんは#{age} 歳です" end def self.klass_method " クラスメソッドです" end end user = User.new("ken", 29) p user.ken # 属性値へのアクセス p user.instance_method # インスタンスメソッド呼び出し p User.klass_method # クラスメソッド 呼び出し
  10. Hash/Struct # Hash ken = {name: "Ken", age: 28} ken[:tel]

    # => nil ken[:address] = " 中野区" # 要素が追加される 存在しないkeyのアクセスすると、nilが返る 後から存在しないkeyに対する要素の追加が可能 存在しない属性にアクセスすると、NameErrorが返る 後から存在しないkeyへの要素の追加ができない # Struct User = Struct.new(:name, :age) ken = User.new("Ken", 29) ken[:tel] # => NameError: undefined method 'tel' ken[:address] = " 中野区" # => NameError: undefined method 'addre
  11. どんなときに嬉しいか ➀書き捨てのクラスを書くとき ➁JSONをparseするとき

  12. ➀書き捨てのクラスを書くとき class A < Struct.new(:a){ def a; "a" end }

    def a super end end p A.new.a 書き捨てスーパークラス&スーパークラスのメソッド呼び出し とりあえず継承関係を書きたいときに便利
  13. こんな構造のスクリプトも class Parser # NOTE: 構造は右記 [["A", "B", "C"],["A`", "B`",

    "C`"]] def initialize(str) @raw_words = str.lines.map {|words| words.split(",")} end # NOTE: 構造は右記 [[ItemObjectA],[ItemObjectB]] def parse @raw_words.inject([]) {|items, elements| items << Item.new( end end class Item attr_reader :name, :price, :discount def initialize(elements) @name = elements[0] @price = elements[1].to_i @discount = elements[2].delete("\"").chomp end end
  14. こう書ける class Parser # NOTE: 構造は右記 [["A", "B", "C"],["A`", "B`",

    "C`"]] def initialize(str) @raw_words = str.lines.map { |words| words.split(",") } end # NOTE: 構造は右記 [[ItemObjectA],[ItemObjectB]] def parse @raw_words.inject([]) { |items, elements| items << Item.new end Item = Struct.new(:elements) do def name ;elements[0] ;end def price ;elements[1].to_i ;end def discount ;elements[2].delete("\"").chomp ;end end end
  15. ➁JSONをparseするとき require 'json' json = '{ "user1": { "name": "ken",

    "age":29 }, "user1": { "name":2, "age":2 } }' hash = JSON.parse(json) p hash["user1"]["age"] # => 29 Hashの値の取り出し方はあんまり好きじゃない
  16. こう require 'json' json = '{ "user1": { "name": "ken",

    "age":29 }, "user1": { "name":2, "age":2 } }' hash = JSON.parse(json) p hash.user1.age # => 29 こう取り出せたら便利な気がする
  17. そこでOpenStruct struct = JSON.parse(json, object_class: OpenStruct) p struct.user1.age

  18. そこでOpenStruct struct = JSON.parse(json, object_class: OpenStruct) p struct.hash.user1.age # =>

    29 optionとして指定出来るobject_classにOpenStructを渡してあげる メソッド呼び出し、属性へのアクセスのようにしてアクセス出来る Betterなインターフェースが実現出来る
  19. Struct(正直使い道ないかなって思ったけど)、便利!