gRPC(ruby)で以下のようなエラーが発生した場合の原因と対処法。
"error": "13 INTERNAL: Unknown field name '文字列' in initialization map entry.\n\n/app/grpc/lib/helpers/article_helper.rb:222:
初期化時に指定した名前のフィールドが存在しないというエラー。
丁寧に該当するエラーが発生したファイル名と行を教えてくれている。
## field nameとは? フィールド名とはprotocol buffers(.protoファイル)で定義した要素を指している。
message <メーセージ名> {
<型> <フィールド名> = <フィールド番号>;
.
.
.
}
エラーは.protoファイルに渡したフィールド名が存在しないことを伝えている。
## 発生状況と対処法
.rbに記述したサーバーコードで.protoファイルのクラス生成時に、存在しないフィールド名を渡したため。
PJ::Model::ArticleItem.new("rowspan")`
名前空間PJ::ModelのクラスArticleItemのインスタンスを作成し、引数に"rowspan"を渡している。
この記述と.protoの対応は以下となる。
- ArticleItemがmessage名
- 引数で渡したrowspanがフィールド名
.protoファイルの指定したmessageで指定したフィールドを設定していないために発生したエラー。
//名前空間の設定
package pj.model;
message ArticleItem {
ArticleItemTdTh td_th = 1;
}
message ArticleItemTdTh {
int32 rowspan = 1;
int32 colspan = 2;
}
該当するメッセージ名ArticleItem
で使えるフィールド名はtd_th
。
対処法
引数で渡すフィールド名をtd_th
に変更すればいい。
PJ::Model::ArticleItem.new("td_th")
以上でエラーが解消する。
## (補足)発生状況詳細 実際のコードはもう少し複雑なので、以下は参考。
## エラーが発生した処理
def convert_article_item(article_item:)
#変数item_typeの宣言
item_type = article_item['item_type']
##rowspan & colspanの設定
#item_typeが"TYPE_TD"かつ、値rowspanとcolspanが存在するなら
#変数rowspanとcolspanに代入
if item_type == "TYPE_TD" and (rowspan = article_item['rowspan'] and colspan = article_item['colspan'])
#convert_item_td_thメソッドにキーワード引数で変数rowspanとcolspanを渡す。
#実行結果を article_item_paramsに代入
article_item_params['td_th'] = convert_item_td_th(rowspan: rowspan, colspan: colspan)
#item_typeの条件は複数存在
elsif item_type = ....
.
.
.
end
#メッセージ名ArticleItemに変数article_item_paramsに代入した値をフィールド名として渡す
PJ::Model::ArticleItem.new(article_item_params)
end
def convert_item_td_th(rowspan:, colspan:)
td_th_params = {}
td_th_params['rowspan'] = rowspan if rowspan.present?
td_th_params['colspan'] = colspan if colspan.present?
PJ::Model::ArticleItemTdTh.new(td_th_params)
end
item_type
に複数のパターンが存在する。
TYPE_TD
かつ、article_item['rowspan']
, article_item['colspan']
が存在する時に、
convert_item_td_th
メソッドを実行する。
キーワード引数としてrowspan
, colspan
を渡す。
td_th_paramas = {'rowspan' = rowspan, 'colspan' = colspan}
をフィールド名として、メッセージArticleItemTdTh
に渡す。
package pj.model;
message ArticleItem {
//列挙型でTYPE_の種類だけフィールドを用意
enum Type {
TYPE_INVALID = 0;
TYPE_DIV = 1;
TYPE_CODE = 2;
TYPE_TYPOGRAPHY = 9;
TYPE_IMAGE = 10;
TYPE_HTML = 11;
TYPE_TEXT = 12;
TYPE_LI = 14;
TYPE_DT = 15;
TYPE_DD = 16;
TYPE_UL = 17;
TYPE_OL = 18;
TYPE_DL = 19;
TYPE_TABLE = 20;
TYPE_TR = 21;
TYPE_TH = 22;
TYPE_TD = 23;
TYPE_TOC = 24;
}
//該当するTYPE_をフィールドtypeに渡す。
Type type = 3;
//今回使っているのはここのArticleItemTdTh
oneof type_details {
ItemTypography typography = 10;
ArticleItemImage image = 11;
ArticleItemCode code = 12;
ArticleItemHtml html = 13;
ArticleItemToc toc = 14;
ArticleItemTable table = 16;
ArticleItemTdTh td_th = 17;
}
}
//ArticleItemTdThの型とフィールド
message ArticleItemTdTh {
int32 rowspan = 1;
int32 colspan = 2;
}
ArticleItemTdTh.new('td_th')
が、Oneof
のArticleItemTdTh td_th
に対応する。
型ArticleItemTdTh
はmessageの中で他のmessageを型として呼び出せる仕様を利用している。
td_th = {rowspan:数値 , colspan:数値}
の形のデータが受け渡される。