Hiroshi Sato · 3月 11 記事へ

スタイルシートを変えるだけでは、面白くないので、バグだと気づいていながら放置していた問題の修正もお願いしました。

編集画面で削除したデータが削除後も左側のリストにそのまま表示されているという問題です。

これも一発の依頼で簡単に解決しました。

修正依頼内容です。

ExpenseItem.tstxの削除ボタンを押して、該当レコードを削除した後、ExpenseItemList.txtのリストを更新して、削除した項目がそのリストに含まれないように修正してください

Cllaude Codeの応答です。

App.tsx で状態管理をしているので、削除後のリスト更新は App.tsx 経由で行うのが適切です。
全体の流れを確認して修正します。
Read current App.tsxRead current App.tsx構造を把握しました。
App.tsx に onDeleteItem コールバックを追加してリストから該当IDを除外し、ExpenseItem.tsx に props として渡す方針で修正します。
2個のファイルを作成しました, 
2個のコマンドを実行しました, 
ファイルを読み取りました2個のファイルを作成しました, 
2個のコマンドを実行しました, 
ファイルを読み取りました
App.tsx と ExpenseItem.tsx の2ファイルを更新しました。

変更の流れ:

App.tsx

onDeleteItem コールバックを useCallback で追加。削除されたIDを受け取り、setExpenseItemList で filter して該当IDの項目をリストから除外します。
また setResponse("") で右ペインの表示もクリアします。

<ExpenseItem> に onDeleteItem={onDeleteItem} を props として渡します。

ExpenseItem.tsx

props から onDeleteItem を受け取ります。
削除API呼び出し成功後の .then() 内で onDeleteItem(response.id) を呼び出し、App.tsx 側のリスト更新をトリガーします。

これにより、削除ボタンを押してAPIが成功すると、アラート表示→左ペインのリストから該当項目が即座に消える、という動作になります。

CSPのセッションとRESTのセッションを共有する方法があることがわかりました。

UseSession=1に設定してCSPのアプリケーション名(/csp/hoge)でセッションクッキーを共有することで%sessionデータを共有できます。

RESTのアプリケーション定義を/csp/user/apiとして

UseSession=1に設定するとREST APIとCSP間で%sessionの共有ができることがわかりました。
(Parameter UseSession As Integer = 1;をクラス定義に含める)


セッションクッキーパスを/csp/user/という風にCSPアプリケーション名に合わせるのがかぎです。

cspクラスとして定義し、OnPageメソッドでJSON形式でデータを返すという方式ならば、%sessionを引き継げます。

これをREST APIと言うのは若干抵抗がありますが、そういっても間違いではないでしょう

RESTをとりあえずやめて以下のようなCSPクラスとして実装すると、正しく動作することが確認できました。
 

素晴らしいプログラミング能力ですね

Class Shop.AddEntry Extends %CSP.Page
{

ClassMethod OnPage() As %Status
{
  set status = $$$OK

  try {

    if $data(%request) {
      set %response.ContentType = "application/json"
      set %response.CharSet = "utf-8"
    }

    set return = {}

    // リクエストボディ(JSON)の読み取り
    set body = ##class(%DynamicObject).%FromJSON(%request.Content)
    set id     = body.id
    set amount = body.amount

    // 顧客情報の呼び出し
    if $get(%session.Data("oid")) = "" {
      set cust = ""
    }
    else {
      set cust = ##class(Shop.Customer).%OpenId(%session.Data("oid"))
    }
    if cust = "" {
      set return.LogoutMessage = "ログアウトされました。\n再度ログインしてください。"
      write return.%ToJSON()
      quit
    }

    // かごにエントリを追加・削除
    if +amount = 0 {
      // 個数が0の場合、かごにエントリがなければエラーを返す
      if '$data(%session.Data("basket", id)) {
        set return.ErrorMessage = "個数を入力してください"
        write return.%ToJSON()
        quit
      }
      // かごからエントリを削除
      kill %session.Data("basket", id)
    }
    else {
      // かごにエントリを追加
      set %session.Data("basket", id) = amount
    }

    // 注文件数の取得
    set id = "", count = 0
    for {
      set id = $order(%session.Data("basket", id))
      quit:id=""
      set id($increment(count)) = id
    }

    // 注文件数をセット
    set return.OrderLength = count

    // 注文IDと表示行の配列をセット
    set orderIds  = []
    set orderLines = []
    set total = 0
    for i = 1:1:count {
      set oref = ##class(Shop.Product).%OpenId(id(i))
      set item = $extract(oref.Name, 1, $zposition(oref.Name, 20))
      set line = item _ $justify("", 20 - $zwidth(item)) _ " " _ $justify(%session.Data("basket", id(i)), 3)
      // ObjectScriptの配列は1基点 → Javascriptの0基点に合わせて末尾追加
      do orderIds.%Push(id(i))
      do orderLines.%Push(line)
      set total = total + (cust.determinePrice(oref.ListPrice) * %session.Data("basket", id(i)))
    }
    set return.OrderIds   = orderIds
    set return.OrderLines = orderLines
    set return.Total      = $fnumber(total, ",")

    write return.%ToJSON()

  }
  catch e {
    set status = e.AsStatus()
  }

  quit status
}

}

%sessionを使用している場合は、REST APIで書き換えるのは、相当難しいことが判明しました。
(CSPのセッションとRESTのセッションは別物のため)

#callに書き換えるしかなさそうです

Hiroshi Sato · 2月 16 記事へ

このシンプルな例をREST APIで書き換えるとこんな感じです。
まずはCSPファイルです。

<html>
<body>
<!--フォームの記述-->
<form name="f1">
<input type="text" value="" name="text1">
<input type="button" value="test" onclick="runMyRoutine();">
</form>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- ボタンクリックで最初に呼び出されるJavascript関数 -->
<script language="javascript">
function runMyRoutine() {
  axios.get('http://localhost:8080/api/user/getMessage/Hiroshi')
  .then(response => {
   console.dir(response)
   self.document.f1.text1.value = response.data.Message
  })
  .catch(error => {
    console.log(error)
  })
  }
</script>
</body>
</html>


次に呼び出されるREST APIのクラスです。

Class Samples.API Extends %CSP.REST
{

Parameter CONVERTINPUTSTREAM = 1;

XData UrlMap
{
<Routes>
  <Route Url="/getMessage/:name" Method="GET" Call="GetMessage"/>
</Routes>
}

ClassMethod GetMessage(pName As %String) As %Status
{
  set status = $$$OK

  try {
	
    if $data(%request) {
      set %response.ContentType="application/json"
      set %response.CharSet = "utf-8"
    }
    set return = {}
    set return.Message = "Hello "_pName
    write return.%ToJSON()
	  	  
  }
  catch e {
		
    set status = e.AsStatus()
		
  }
  
  quit status
}

}


RESTアプリケーションの設定例

Hiroshi Sato · 10月 20, 2025 記事へ

動作が不安定だった原因が判明しました。

環境変数の設定に不備があったのが原因のようです。

iris-embedded-python-wrapperをインストールし、環境変数を適切に設定すれば、OKです。

Hiroshi Sato · 10月 7, 2025 記事へ

この方法でも色々と動作が不安定な場合があり、やはり現時点ではirispythonコマンドを使用する方法がおすすめです。

Hiroshi Sato · 4月 18, 2025 記事へ

レポートのリンク先がなくなっているようです

Hiroshi Sato · 4月 9, 2025 記事へ

GoogleのコンソールUIが劇的に変わっており、ここの記述と実際の現時点のUIの対比に苦労しました。
時間と共に変わってしまうのでなかなか難しいところですね(相手がクラウドサービスの場合は特に)

中でも

テストユーザ で +ADD USERS から xxxxxx@gmail.com を追加して [保存して次へ] をクリック
この部分がどれに対応するのかなかなかわかりませんでした
プロジェクトのページの左ペインから対象を選ぶと、+ADD Userというボタンが表示されます。

Hiroshi Sato · 1月 7, 2025 記事へ

そうです。
私が作成しているDockerコンテナのiris.scriptの中で本文で記載しているコマンドを入れています。(必ずでもないですが)

Hiroshi Sato · 8月 8, 2024 記事へ

訂正します。

現バージョン(2024.1)にもこれらの機能はありました。

Hiroshi Sato · 4月 9, 2024 記事へ

以前のバージョンでは(2023.x)ではWindowsの場合は、pathPrefixをつけないと接続できなかった記憶があります。

その時もMac版では必要なかったので、2024からWindows版もそれに合わせたということですかね

(またはWindows版ではその追加設定がたまたま抜けていたか)

Hiroshi Sato · 4月 4, 2024 記事へ

macOSの場合は、pathPrefixの設定は必要なく接続できました。

これはApache由来の話なのかMacOS特有の事情なのかは確認していないのでわかりません。

Hiroshi Sato · 10月 23, 2023 記事へ

投稿ありがとうございます。
TZ=JST-9で行けると思います。

Hiroshi Sato · 3月 2, 2023 記事へ

最新の状況に合わせて記事を大幅更新しました。

Hiroshi Sato · 3月 11, 2022 記事へ

ちなみに

360万文字越えのデータは無理です。

サーバー側のWriteメソッドが受け付けるのは、普通のIRISの文字列なので、その最大値の制限は受けてしまいます。

Hiroshi Sato · 3月 11, 2022 記事へ

>私のサンプルは、.Netの標準ライブラリーであるSystem.IO.FileStreamを使っています。

>なので同じRead,Writeメソッドでも中の実装は違っていると思います。

これは全然関係ないコメントでした。

バージョンはいくつを使っていますか?
 

私が使用しているのは、

2021.2 (Build 650U)

です。

新しいバージョンを使うといろいろと改善されていることがあったりするので、是非最新を試すようにしてみてください。
でもあんまり巨大なファイルを一度で読み書きするのは結局ディスクの読み書きやプロセスのメモリーのアロケーションやいろいろなことが絡んでくるので一筋縄ではいかないこともありそうです。

Hiroshi Sato · 3月 9, 2022 記事へ

kobataさん
ご視聴ありがとうございました。

私のサンプルで2M以上のファイルでもOKでした。
私のサンプルは、.Netの標準ライブラリーであるSystem.IO.FileStreamを使っています。

なので同じRead,Writeメソッドでも中の実装は違っていると思います。
 

Hiroshi Sato · 3月 3, 2021 記事へ

Hirosesさん
提供情報が参考になったなら幸いです。
MACのExcelで全く使えないわけではなく、VBAのフォーム機能が使えないだけです。
なので、ボタンを押してマクロを呼び出し、そこでREST/JSONアクセスするのはできます。
(お知らせしたサンプルにもその例があります)

Hiroshi Sato · 3月 3, 2021 記事へ

Hiroseさん
返答遅れて申し訳ないです。
Multi Purpose Utility System  
これは何だかMUMPSを思い出させるネーミングなので、申し訳ないですが却下させてください。
でもイメージは間違っていないと思います。
キャッチーなネーミングは、コンシューマを意識する場合は不可欠なのですが、IRISはどこまでいっても消費財ではなく生産財なので、すべての人に理解してもらうのはやはり難しいところです

Hiroshi Sato · 2月 24, 2021 記事へ

hiroseさん

その通りです。
大は小を兼ねますからね

IRISなら軽いものから重たいものまで何でもこなせます。
用途に合わせてデータベースを分けないとなると、同じデータを物理的に別々に管理しなければならなくなりますよね。
ITの課題の1つがデータのサイロ化です。

データがいろいろなところに散在していると、それを取りまとめるための手間が増えてしまいます。
1つのデータベースが色々な用途に対応できるとその手間が少なくできるのではないかと思います。

そんな方向性をIRISは目指しています。
キーワードとしてはマルチモデルとマルチワークロードです。

Hiroshi Sato · 2月 24, 2021 記事へ

Hiroseさん
先週のバーチャルサミット聴講していただいたと思いますが、ウルシステムズの漆原社長の講演は聞かれましたか?
そこでエッジの効いたデータベースと紹介いただいています。
見てない場合は是非ご覧になってください。