Slide 1

Slide 1 text

+40/4DIFNBͰ ෳࡶͳ࢓༷ͷೖྗϑΥʔϜͷ࣮૷ʹ ཱͪ޲͔ͬͨ࿩ ΫοΫύουגࣜձࣾ Ԙग़ ݚ࢙ 1

Slide 2

Slide 2 text

2 Ԙग़ ݚ࢙ ৯Ԙग़ݱ !TPMU ΫοΫύουגࣜձࣾ ങ෺ϓϩμΫτ։ൃ෦ ॴଐ ීஈ͸ 3BJMT΍ 3FBDUΛॻ͘ झຯ͸ϓϩτλΠϐϯάʢ࠷ۙ͸͓ֆඳ͖΋޷͖ʣ ҿञ TVEPΛ๷ࢭ͢ΔγεςϜ

Slide 3

Slide 3 text

3 +40/4DIFNBΛ࢖࣮ͬͯݱͨ͠΋ͷ

Slide 4

Slide 4 text

4 ࢲ͕։ൃʹܞΘ͍ͬͯΔϓϩμΫτ ੜ઱৯඼Λத৺ͱͨ͠&$ϓϥοτϑΥʔϜ

Slide 5

Slide 5 text

5 ൢചऀ޲͚؅ཧը໘ • ঎඼৘ใͷొ࿥ • Ӧۀ೔ͷ؅ཧ • ग़ՙ࡞ۀͷ֬ೝ • ঎඼ϨϏϡʔͷฦ৴

Slide 6

Slide 6 text

6 ൢചऀ޲͚؅ཧը໘ • ঎඼৘ใͷొ࿥ • Ӧۀ೔ͷ؅ཧ • ग़ՙ࡞ۀͷ֬ೝ • ঎඼ϨϏϡʔͷฦ৴

Slide 7

Slide 7 text

7 ঎඼৘ใͷొ࿥ • ͓ૣΊʹ͓ঌ্͕͠Γͩ͘ ͍͞ • ফඅظݶ·Ͱͷ೔਺ • ղౚ඼͔Ͳ͏͔ • ੜ৯༻͔Ճ೤༻͔ • ཆ৩͔ఱવ͔ • ফඅظݶ·Ͱͷ೔਺ • ղౚ඼͔Ͳ͏͔ ೖྗ͢΂͖඼࣭อূ΍৯඼දࣔʹؔΘΔ৘ใ͸঎඼ͷछྨ͝ͱʹҟͳΔ

Slide 8

Slide 8 text

8 ౰࣌ɺશ߲໨Λཏྻ͢ΔΑ͏ͳϑΥʔϜΛఏڙ͍ͯͨ͠😨 • ೖྗϛε͕සൃ͠ɺ঎඼ొ࿥ʹख͕͔͔ؒΔ • ೑ͳͷʹʮ͓ૣΊʹ͓ঌ্͕͠Γ͍ͩ͘͞ʯΛબ୒ͯ͠͠·͏ • ڕͳͷʹཆ৩͔ఱવ͔ೖྗ͠๨Εͯ͠·͏ ϑϩϯτΤϯυଆͰ঎඼ͷछྨʹ΋ͱͮ͘ϑΥʔϜͷग़͠෼͚ • ࣾ಺ͷӡ༻ϝϯόʹΑΔ঎඼৹ࠪͷෛ୲͕૿͑Δ όοΫΤϯυଆͰෆਖ਼ͳσʔλΛআͨ͘ΊͷόϦσʔγϣϯ

Slide 9

Slide 9 text

9 • ೖྗϛε͕සൃ͠ɺ঎඼ొ࿥ʹख͕͔͔ؒΔ • ೑ͳͷʹʮ͓ૣΊʹ͓ঌ্͕͠Γ͍ͩ͘͞ʯΛબ୒ͯ͠͠·͏ • ڕͳͷʹཆ৩͔ఱવ͔ೖྗ͠๨Εͯ͠·͏ ϑϩϯτΤϯυଆͰ঎඼ͷछྨʹ΋ͱͮ͘ϑΥʔϜͷग़͠෼͚ • ࣾ಺ͷӡ༻ϝϯόʹΑΔ঎඼৹ࠪͷෛ୲͕૿͑Δ όοΫΤϯυଆͰෆਖ਼ͳσʔλΛআͨ͘ΊͷόϦσʔγϣϯ ౰࣌ɺશ߲໨Λཏྻ͢ΔΑ͏ͳϑΥʔϜΛఏڙ͍ͯͨ͠😨

Slide 10

Slide 10 text

10 Ͳ͏΍࣮ͬͯ૷͢Δʁ def validate! if category == "魚" if quality_guarantee_type != "消費期限" raise Error.new("魚なのに消費期限が…") end if farmed == nil raise Error.new("魚なのに養殖かどうか…") end # if ... elsif category == "肉" # if ... elsif category == "根もの" # if ... end end • ࠓޙɺ঎඼ͷछྨΛ௥Ճͨ͘͠ͳͬͨͱ͖ ʹϝϯςφϯε͕େม • ϑϩϯτΤϯυͱόοΫΤϯυͰಉ༷ͷ JGจΛେྔʹॻ͘ඞཁ͕͋Δ • ͳΜ͔Πέͯͳͦ͞͏ʂ 👎 ՝୊ JG จΛେྔʹ࢖ͬͯΈΔ

Slide 11

Slide 11 text

11 Ͳ͏΍࣮ͬͯ૷͢Δʁ +40/4DIFNBΛར༻͢Δ { required: ["raw", "thawed", "farmed"], properties: { category_id: { const: "魚のID" }, thawed: { "$ref" => "#/definitions/thawed" }, farmed: { "$ref" => "#/definitions/farmed" }, raw: { "$ref" => "#/definitions/raw" }, }, dependencies: { thawed: { oneOf: [ # 中略 ], }, }, } • ࠓޙɺ঎඼ͷछྨΛ௥Ճͨ͘͠ͳͬͨͱ͖ ͷϝϯςφϯεੑ͕ߴ͍ • ϑϩϯτΤϯυͱόοΫΤϯυͷϩδοΫ ͕ڞ௨ͷεΩʔϚʹΑΓ׬੒͢Δ 👍 ϝϦοτ

Slide 12

Slide 12 text

12 +40/4DIFNBͱ͸ { id: 100, name: "カルボナーラの作り方", content: "ベーコンと玉ねぎを食べやすい大き さに切ります。〜(以下略)", public: true } +40/4DIFNBͱ͸ +40/ͷߏ଄Λఆٛͨ͠΋ͷ ྉཧϨγϐͷ +40/ͷߏ଄Λఆٛͯ͠ΈΑ͏ +40/ͷྫ

Slide 13

Slide 13 text

13 +40/4DIFNBͱ͸ { id: 100, name: "カルボナーラの作り方", content: "ベーコンと玉ねぎを食べやすい大き さに切ります。〜(以下略)", public: true } +40/4DIFNBͱ͸ +40/ͷߏ଄Λఆٛͨ͠΋ͷ ྉཧϨγϐͷ +40/ͷߏ଄Λఆٛͯ͠ΈΑ͏ { title: "お料理レシピ", type: "object", properties: { id: { title: "ID", type: "integer" }, name: { title: "名前", type: "string" }, content: { title: "作り方", type: "string" }, public: { title: "公開中", type: "boolean" } }, required: ["id", "name", "content", "public"] } +40/ͷྫ +40/4DIFNBͷྫ

Slide 14

Slide 14 text

14 +40/4DIFNBͱ͸ { id: 100, name: "カルボナーラの作り方", content: "ベーコンと玉ねぎを食べやすい大き さに切ります。〜(以下略)", public: true } +40/4DIFNBͱ͸ +40/ͷߏ଄Λఆٛͨ͠΋ͷ ྉཧϨγϐͷ +40/ͷߏ଄Λఆٛͯ͠ΈΑ͏ { title: "お料理レシピ", type: "object", properties: { id: { title: "ID", type: "integer" }, name: { title: "名前", type: "string" }, content: { title: "作り方", type: "string" }, public: { title: "公開中", type: "boolean" } }, required: ["id", "name", "content", "public"] } +40/ͷྫ +40/4DIFNBͷྫ ܕͳͲ੍໿͕ఆٛͰ͖Δ

Slide 15

Slide 15 text

15 ඼࣭อূͷೖྗϑΥʔϜΛ +40/4DIFNBͰॻ͍ͯΈΔ { title: "商品", type: "object", required: ["category_id"], properties: { category_id: { title: "カテゴリ", type: "number", enum: [1, 2, 3], enumNames: ["根もの", "鶏肉", "魚介加工品"] } }, dependencies: { category_id: { oneOf: [ { properties: { category_id: { const: 1 }, /** 根もの独自の入力項目 **/ }}, { properties: { category_id: { const: 2 }, /** 鶏肉独自の入力項目 **/ }}, { properties: { category_id: { const: 3 }, /** 魚介加工品独自の入力項目 **/ }}, ] }, }, }

Slide 16

Slide 16 text

16 { title: "商品", type: "object", required: ["category_id"], properties: { category_id: { title: "カテゴリ", type: "number", enum: [1, 2, 3], enumNames: ["根もの", "鶏肉", "魚介加工品"] } }, dependencies: { category_id: { oneOf: [ { properties: { category_id: { const: 1 }, /** 根もの独自の入力項目 **/ }}, { properties: { category_id: { const: 2 }, /** 鶏肉独自の入力項目 **/ }}, { properties: { category_id: { const: 3 }, /** 魚介加工品独自の入力項目 **/ }}, ] }, }, } EFQFOEFODJFTΧςΰϦ*%͕ઃఆ͞Ε͍ͯΔͱ͖ʜ ඼࣭อূͷೖྗϑΥʔϜΛ +40/4DIFNBͰॻ͍ͯΈΔ

Slide 17

Slide 17 text

17 { title: "商品", type: "object", required: ["category_id"], properties: { category_id: { title: "カテゴリ", type: "number", enum: [1, 2, 3], enumNames: ["根もの", "鶏肉", "魚介加工品"] } }, dependencies: { category_id: { oneOf: [ { properties: { category_id: { const: 1 }, /** 根もの独自の入力項目 **/ }}, { properties: { category_id: { const: 2 }, /** 鶏肉独自の入力項目 **/ }}, { properties: { category_id: { const: 3 }, /** 魚介加工品独自の入力項目 **/ }}, ] }, }, } EFQFOEFODJFTΧςΰϦ*%͕ઃఆ͞Ε͍ͯΔͱ͖ʜ POF0GͲΕ͔ʹҰக͢Δඞཁ͕͋Δ ඼࣭อূͷೖྗϑΥʔϜΛ +40/4DIFNBͰॻ͍ͯΈΔ

Slide 18

Slide 18 text

18 +40/4DIFNBʹ͍ͭͯΑΓৄ͘͠஌Γ͍ͨํ΁ +40/4DIFNBͰ͸͍͔ͭ͘όʔδϣϯ͕͋Γɺ ৽͍͠ %SBGUͰ͸ *G5IFO&MTFͱ͍͏ॻ͖ํ΋αϙʔτ͞Ε͍ͯ·͢ ͦͷଞʹ΋ NVMUJQMF0G΍ QBUUFSO ͳͲܕ΍੍໿ͷදݱํ๏͕͋ͬͨΓ EFGJOJUJPOTͱ͍ͬͨศརͳߏจ΋ଘࡏ͠·͢ ৄࡉ͸ 6OEFSTUBOEJOH+40/4DIFNB ͕ࢀߟʹͳΔͱࢥ͍·͢

Slide 19

Slide 19 text

19 +40/4DIFNBपΓͷϥΠϒϥϦબఆ ΫοΫύουϚʔτͷൢചऀ޲͚؅ཧը໘ͷٕज़ελοΫ • ϑϩϯτΤϯυɿ 3BJMTͷ 7JFXͱ 3FBDU5ZQF4DSJQU • όοΫΤϯυɿ 3VCZPO3BJMT

Slide 20

Slide 20 text

20 +40/4DIFNBपΓͷϥΠϒϥϦબఆ ΫοΫύουϚʔτͷൢചऀ޲͚؅ཧը໘ͷٕज़ελοΫ • ϑϩϯτΤϯυɿ 3BJMTͷ 7JFXͱ 3FBDU5ZQF4DSJQU • όοΫΤϯυɿ 3VCZPO3BJMT બఆͨ͠ϥΠϒϥϦ • ϑϩϯτΤϯυɿ SKTGUFBNSFBDUKTPOTDIFNBGPSN • όοΫΤϯυɿ EBWJTINDDMVSHKTPO@TDIFNFS

Slide 21

Slide 21 text

21 KTPO@TDIFNFS JSONSchemer.schema(json_schema).valid?(json_to_be_validated) +40/4DIFNBΛར༻ͯ͠όϦσʔγϣϯΛ͢ΔͨΊͷ 3VCZ੡ϥΠϒϥϦ ͨͬͨ͜Ε͚ͩͰ +40/4DIFNBʹ΋ͱ͍ͮͨόϦσʔγϣϯ͕Ͱ͖Δʂ

Slide 22

Slide 22 text

22 SFBDUKTPOTDIFNBGPSN import Form from 'react-jsonschema-form'; export function App() { return } +40/4DIFNBΛར༻ͯ͠ೖྗϑΥʔϜΛࣗಈੜ੒͢Δ 3FBDUϥΠϒϥϦ +40/4DIFNBΛ 1SPQTͱͯ͠౉͚ͩ͢ͰɺೖྗϑΥʔϜ͕׬੒͢Δ POF0GͰઃఆͨ͠ೖྗϑΥʔϜͷग़͠෼͚΋ಈతʹ΍ͬͯ͘ΕΔʂ

Slide 23

Slide 23 text

23 σβΠϯ͸ࣗ෼Ͱ࣮૷͢Δ • SFBDUKTPOTDIFNBGPSN͸ .BUFSJBM6*΍ #PPUTUSBQͳͲΛඪ४Ͱαϙʔτ͍ͯ͠Δ • ཁૉͷΧελϚΠζʹ͸ 8JEHFU΍ 'JFMEͳͲͷ࢓૊ΈΛར༻͢Δ

Slide 24

Slide 24 text

24 σβΠϯ͸ࣗ෼Ͱ࣮૷͢Δ • SFBDUKTPOTDIFNBGPSN͸ .BUFSJBM6*΍ #PPUTUSBQͳͲΛඪ४Ͱαϙʔτ͍ͯ͠Δ • ཁૉͷΧελϚΠζʹ͸ 8JEHFU΍ 'JFMEͳͲͷ࢓૊ΈΛར༻͢Δ 8JEHFUJOQVUཁૉ΍ TFMFDUཁૉࣗମ

Slide 25

Slide 25 text

25 σβΠϯ͸ࣗ෼Ͱ࣮૷͢Δ • SFBDUKTPOTDIFNBGPSN͸ .BUFSJBM6*΍ #PPUTUSBQͳͲΛඪ४Ͱαϙʔτ͍ͯ͠Δ • ཁૉͷΧελϚΠζʹ͸ 8JEHFU΍ 'JFMEͳͲͷ࢓૊ΈΛར༻͢Δ 8JEHFUJOQVUཁૉ΍ TFMFDUཁૉࣗମ 'JFME8JEHFUΛϥοϓ͢Δ $PNQPOFOU λΠτϧɾઆ໌ɾ஫هͳͲΛؚΊͨ಺༰

Slide 26

Slide 26 text

26 8JEHFUͱ 'JFMEͷαϯϓϧίʔυ export const RadioWidget = (props) => (
{props.options.enumOptions.map((option, i) => { return (
{ props.onChange(option.value); }} /> {option.label}
); })}
); export const FieldTemplate = (props) => { return (
{props.required ? ( 必須 ) : ( 任意 )} {props.label}
{props.rawDescription && {props.rawDescription}} {props.children} {/* この部分で Widget の描画が⾏ われる */} {props.rawHelp && {props.rawHelp}} ); };

Slide 27

Slide 27 text

27 VJ4DIFNB export function App() { const uiSchema = { farmed: { 'ui:disabled': false, 'ui:name': 'item[farmed]’, 'ui:widget': RadioWidget, 'ui:help': '養殖か天然を必ず選択してください。’, }, // ... }; return ( ); } +40/ 4DIFNB͸σʔλߏ଄ɾ੍໿ͷఆٛΛߦͳ͍ͬͯΔͨΊɺ ͦͷσʔλΛͲ͏͍͏෩ʹදࣔ͢Δ͔ʁͷఆٛͷ੹຿Λ VJ4DIFNB ͕୲͍ͬͯΔ

Slide 28

Slide 28 text

28 +40/4DIFNBͰೖྗϑΥʔϜͷग़͠෼͚Λ࣮૷ͨ݁͠Ռ ඼࣭อূʹؔ͢Δೖྗෆඋ཰ ঎඼ͷछྨΛબͿ͚ͩͰ඼࣭อূͷछྨ͕ࣗಈબ୒͞ΕΔ Α͏ʹͳͬͨͨΊɺೖྗෆඋ͸΄΅θϩʹͳΓ·ͨ͠ ։ൃϝϯςφϯεͷ༰қੑ ঎඼ͷछྨͷ௥Ճ΍ཁ͕݅૿͑ͨͱͯ͠΋ɺ+40/4DIFNBͷఆٛΛߋ৽͢Δ͚ͩͰղܾ͠ɺ ೖྗϑΥʔϜͷग़͠෼੍͚ޚͱόοΫΤϯυͷόϦσʔγϣϯΛ༰қʹ௥Ճɾߋ৽Մೳͳঢ়ଶ

Slide 29

Slide 29 text

29 Ԙग़ ݚ࢙ ৯Ԙग़ݱ !TPMU