JQ Blog

クラス拡張ミックスインのサンプル作り

課題

  • 学校の先生、学生のリスト出力
    • 全員のリスト
    • データを指定

先生、学生のリスト出力

  • クラスメソッドを使って取り出す

指定データ出力

  • インスタンスメソッドを使って取り出す

前提

  • 先生、学生のデータはそれぞれmixin_samples/students_data.rbmixin_samples/teachers_data.rbを使う
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module MixinSamples
  module StudentsData
    def self.included(base)
      base.extend self
    end

    def data
      [
        { age: 18, name: 'Suzuki', japanese: 70, math: 80, science: 90, english: 70 },
        { age: 17, name: 'Sato', japanese: 60, math: 70, science: 50, english: 50 },
        { age: 18, name: 'Takahashi', japanese: 90, math: 90, science: 100, english: 70 },
        { age: 16, name: 'Tanaka', japanese: 80, math: 60, science: 70, english: 90 }
      ]
    end
  end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module MixinSamples
  module TeachersData
    def self.included(base)
      base.extend self
    end

    def data
      [
        { age: 46, name: 'Ito', teaching_subject: '国語', teaching_target: '1年生' },
        { age: 38, name: 'Watanabe', teaching_subject: '数学', teaching_target: '2年生' },
        { age: 25, name: 'Yamamoto', teaching_subject: '科学', teaching_target: '3年生' },
        { age: 32, name: 'Nakamura', teaching_subject: '英語', teaching_target: '3年生' }
      ]
    end
  end
end

Sample code

出力のためのTotalPrintPersonalPrintモジュールを定義する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module MixinSamples
  module TotalPrint

    def print_data
      puts convert_data
    end

    def print_names
      puts names
    end

    private

    def convert_data
      data.map { |val| val.map { |k, v| "#{k.capitalize}: #{v}" }.join(' | ') }
    end

    def names
      data.map { |val| val.values_at(:name) }.flatten.join("\n")
    end
  end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
module MixinSamples
  module PersonalPrint

    def to_print
      puts person_info
    end

    private

    def person_info
      args.map { |k, v| "#{k.capitalize}: #{v}" }.join(' | ')
    end
  end
end

データ指定のためのSearchモジュールを定義する

1
2
3
4
5
6
7
8
module MixinSamples
  module Search
    def search(name)
      objs = data.map { |hash| hash.values_at(:name).include?(name) ? hash : nil }.compact
      objs.map { |obj| new(obj) }
    end
  end
end

モジュールをMixinするスーパークラスを定義する

1
2
3
4
5
6
7
8
9
10
11
12
13
module MixinSamples
  class SchoolMember
    attr_accessor :args

    include PersonalPrint
    extend TotalPrint
    extend Search

    def initialize(args)
      @args = args
    end
  end
end

実際の本体である先生、学生のクラスを定義する

1
2
3
4
5
module MixinSamples
  class Teacher < SchoolMember
    include TeachersData
  end
end
1
2
3
4
5
module MixinSamples
  class Student < SchoolMember
    include StudentsData
  end
end

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
MixinSamples::Teacher.print_data
=>
Age: 46 | Name: Ito | Teaching_subject: 国語 | Teaching_target: 1年生
Age: 38 | Name: Watanabe | Teaching_subject: 数学 | Teaching_target: 2年生
Age: 25 | Name: Yamamoto | Teaching_subject: 科学 | Teaching_target: 3年生
Age: 32 | Name: Nakamura | Teaching_subject: 英語 | Teaching_target: 3年生

MixinSamples::Student.print_data
=>
Age: 18 | Name: Suzuki | Japanese: 70 | Math: 80 | Science: 90 | English: 70
Age: 17 | Name: Sato | Japanese: 60 | Math: 70 | Science: 50 | English: 50
Age: 18 | Name: Takahashi | Japanese: 90 | Math: 90 | Science: 100 | English: 70
Age: 16 | Name: Tanaka | Japanese: 80 | Math: 60 | Science: 70 | English: 90

teachers = MixinSamples::Teacher.search 'Ito'
=> [<MixinSamples::Teacher:0x007fd7b1682910 @age=46, @name="Ito", @teaching_subject="国語", @teaching_target="1年生">]

teachers.map { |teacher| teacher.to_print }
=>
Age: 46 | Name: Ito | Teaching_subject: 国語 | Teaching_target: 1年生

students = MixinSamples::Student.search 'Suzuki'
=> [<MixinSamples::Student:0x007fd7b1506500 @age=18, @args={:age=>18, :name=>"Suzuki", :japanese=>70, :math=>80, :science=>90, :english=>70}, @english=70, @japanese=70, @math=80, @name="Suzuki", @science=90>]

students.map { |student| student.to_print }
=>
Age: 18 | Name: Suzuki | Japanese: 70 | Math: 80 | Science: 90 | English: 70