2016-03-30 9 views
3

UserInvoiceの間で、StartAppを使用しているときに、Elmアーキテクチャに従ってワークフローを分割しようとしています。Elmのコンポーネント間の通信

ユーザーには請求書がありますが、アクセスするにはログインする必要があります。

モデルでは、これらの線に沿って何かのように見えることがあります。

type Model 
    = NotLoggedIn Credentials 
    | LoggedIn RealName (Maybe Invoices) 

type alias State = 
    { login : Model 
    , notification : ...... 
    , ...... 


type alias Invoices = { invoices: List Invoice, ...... } 

ユーザーモジュールは、アクションを持っています

type Action 
    = Login (Result Http.Error String) 
    | Logout 
    | Submit 
    ... 

と更新機能:

update : Action -> Model -> (Model, Effects Action, Notification) 
update action user = 
    case (action, user) of 
     (Login res, _) -> 
     case res of 
      Ok name -> 
       (LoggedIn name Nothing, Effects.none, Info "Welcome!") 
    ... 

私は詳細をスキップ認証の、それはすべて良いです。興味深い部分は、Loginアクションです。タプルがmainstep機能に送信されます。

step : Action -> State -> (State, Effects Action) 
step action state = 
    case action of 
     UserAction a -> 
     let (newstate, ef, n) = User.update a state.login 
     in ({ state | login = newstate, notification = n }, Effects.map UserAction ef) 
     InvoiceAction a -> ...... 

ので、ユーザがログインした次は、私たちはInvoiceモジュール内のいくつかのinitアクションを呼び出したいです。

これはどのように正しく行われるべきですか?カプセル化を維持するためにInvoiceのアクションを開始するにはどうすればよいですか? Effects.none以外のものを返さなければなりませんか?

答えて

3

これは、アプリのデータのさまざまなモデリングによって解決できる場合があります。

私が理解している方法では、ユーザーと、ユーザーを必要としない操作が必要な操作があります。 InvoiceActionは、UserActionに属している必要があることを私に縫っています。

だから、あなたは、ユーザーモデルはログインの詳細と請求書の詳細の両方をカプセル化します

type MainAction = UserAction UAction | NonUserAction NonUAction 

type UAction = AuthAction Credentials | InvoiceAction Invoice.Action 

を持つことができます。そしてログインが成功すると、InvoiceActionにリダイレクトできます。

update action model = 
    case action of 
    AuthAction credentials -> 
     let 
     (isLoggedIn, notifications) = Authentication.check credentials 
     model' = { model | credentials = credentials, notifications = notifications} 
     in 
     if isLoggedIn 
     then update (Invoice.initialize model'.credentials) model' 
     else (model', Effects.none) 

    InvoiceAction act -> 
     let 
     (invoices, fx) = Invoice.update model.credentials act model.invoices 
     in 
     ({model | invoices = invoices}, Effects.map InvoiceAction fx) 

実際の動作はinitialize: Credentials -> Actionような署名付き機能initialize介してインボイスモジュールによって提供されます。これは、カプセル化を維持するために行われます。ユーザモジュールは、特定の請求書アクションについて知る必要はなく、初期化に関連するものがあり、それはその機能を介して得ることができる。

また、更新シグネチャを簡略化し、モデル内の通知を移動しました。これは通知が特別なものでないと思うので個人的な好みです。それらはモデル内の他のデータと似ています。もちろん、通知がカスタムStartAppを経由してポートにルーティングされ、いくつかのJSメカニズムによって表示されるタスクである場合、それらをリターンに保つことが理にかなっているかもしれません。

2

一つのアプローチは次のようになります。

  • は、親コンポーネント
  • でメールボックスを作成しますUser更新
  • ユーザーの更新にそのメールボックスのアドレスを渡し、このアドレスにメッセージを送信する効果を返す
  • メッセージを受信すると、このメールボックスは、次のような動作をトリガーします。Invoice

elm-tutorialのこの章では、このパターンを示していますhttp://www.elm-tutorial.org/090_showing_errors/flow.html

+0

貴重なご意見ありがとうございました。 – punund