def children_methods(children_of_type) ... children_of_type.each do |method_name, node_type| module_eval <<-RUBY, __FILE__, __LINE__ attr_reader :#{method_name} RUBY ... end end end end class Directive < AbstractNode children_methods(arguments: GraphQL::Language::Nodes::Argument) end • メソッドの中の module_eval なので、今の Spinel は拒否する(inherited フックの中も同じ) • 引数はソースに書いてあるので、原理的には展開できる
plan.first until e.nil? case e.fid when 1 # name v8 = obj.name # if v8.nil? # String! leaf_null_error("User", "name", e.field, e.key) return nil end res[e.key] = v8.to_s # String end e = e.next_entry end res end メソッドで り す なので なので
String field :display_name, String def display_name = object.name.capitalize end def resolve(field, user) wrapper = UserType.new(user) # if wrapper.respond_to?(field.name) then wrapper.public_send(field.name) elsif user.is_a?(Hash) then user[field.name] else user.public_send(field.name) end end ユーザーごとに む • name は User のメソッド、display_name は UserType で定義したメソッドだと、スキーマを見れば決まっている。 それでもユーザーごと、フィールドごとに包んで探し直している
|result_name, ast_node| evaluate_selection(result_name, ...) # → continue_field end end def continue_field(value, ..., current_type, ...) case current_type.kind.name when "OBJECT" evaluate_selections(selections, ...) # 1 when "LIST" value.each do |inner_value| resolve_list_item(inner_value, ...) の中へ # 1 ずつ → continue_field end end end • 1 人を受け取り、その 1 人の中身を最後まで埋めてから、次の 1 人へ進む再帰
field.how when :method then user.name when :hash then user[:name] end end ループの で、 回だけ する # next: 1 case field.how when :method then users.map { |user| user.name } when :hash then users.map { |user| user[:name] } end スキーマから コード⽣成 # Ruby : users.map { |user| user.name } は、コードを書き すときに んでいる