1

javascript/coffeescript/ember.js/stackoverflow 初心者はこちら!

オブジェクトに対するアクションがサーバーから承認された場合にのみコンテンツを表示する if-like ヘルパーを作成しようとしています。基本的にはcan?、Rails cancan gem のメソッドが必要です。テンプレートを次のように書きたいと思います。

<h1>Viewing profile for {{email}}</h1>
<h2>Scores</h2>
{{#each score in scores}}
    <div class="summary">{{score.what}}  
        {{#can score action=destroy}}
            <a href="#" id="destroy">Destroyable</a>  
        {{/can}}
        {{#can score action=view}}
            <a href="#" id="view">Viewable</a>  
        {{/can}}
        {{#can score action=edit}}
            <a href="#" id="edit">Editable</a>  
        {{/can}}
    </div>
{{/each}}

ember.js ヘルパーは、can次のような json リクエストでサーバーにクエリを実行します。

<site>/api/v1/authorization.json?action=destroy&cName=Score&id=1

サーバーは単純に HTTP ステータス コード 200 または 401 を返し、ember はステータス コードに基づいて魔法のようにコンテンツを表示または非表示にします。サーバーで実行する必要がある役割とオブジェクトベースのアクセス許可チェックがいくつかあるため、この方法で承認を行う必要があり、js で承認ロジックを複製したくない。

これまで、すぐifに使用できるヘルパーを例として使用して、次のカスタム バインド ヘルパー (coffeescript) を作成しました。

Ember.Handlebars.registerBoundHelper 'can', (object, options) ->

    permission = EmberDeviseExample.Authorization.create
        action: options.hash.action
        object: object

    permission.authorize()

    options.contexts = [permission]

    Ember.Handlebars.helpers.boundIf.call(permission, "can", options)

ユーザー オブジェクトは次のとおりです。

EmberDeviseExample.User = DS.Model.extend
  email:        DS.attr('string')
  scores:       DS.hasMany('EmberDeviseExample.Score')

EmberDeviseExample.store.adapter.serializer.map('EmberDeviseExample.User', {scores: {embedded: 'load'}})

Authorization オブジェクトは次のとおりです。

EmberDeviseExample.Authorization = Ember.Object.extend
  action: ''
  object: null
  response: 401
  urlBase: ApiUrl.authorization_path

  can : (-> 
      return (this.get('response') == 200)
  ).property('response')

  authorize: ->
    # if object is an instance, include the id in the query params
    # otherwise, just include the class name
    obj = this.get('object')
    cName = obj.toString()
    id = null
    if Ember.typeOf(obj) == "instance"
      # cname looks something like "<namespace.name:embernumber>"
      # turn it into "name"
      cName = cName.split(':')[0].split('.')[1]
      id = obj.get('id')

    $.ajax 
       url : "#{this.get('urlBase')}.json"
       context : this
       type : 'GET'
       data : 
          action : this.get('action')
          cName : cName
          id : id

       complete : (data, textStatus, xhr) ->
          this.set('response', data.status)

    return this.get('can')

サーバー側では、authorization.json コードは次のようになります (rails 3)。認証を制御するために cancan gem を使用しています。

class AuthorizationsController < ApplicationController
  respond_to :json
  def show
    id     = params[:id]
    cName  = params[:cName]
    action = params[:action]

    object = cName.capitalize.constantize

    object = object.find(id) unless id.blank?

    authorized = can? action, object

    render status: (authorized ? 200 : 401), json: {}
  end
end

ルートは次のようになります。

  scope "/api" do
    scope "/v1" do
      resource :authorization, only: [:show]
    end
  end

もちろん、私のアプリには他のコードもあります。それを見る必要がある場合はお知らせください。

ヘルパーを削除すると#can、レンダリングされたテンプレートが表示されます。ヘルパーを再度追加すると#can、javascript エラーが発生します。Chrome のメッセージは次のとおりです。"Uncaught TypeError: Cannot read property '0' of null" @ ember.prod.js:2362.

オブジェクトとアクションを受け入れ、サーバー側の承認チェックを実行し、サーバーの結果に基づいてコンテンツを表示/非表示にするヘルパーを構築する方法を知っている人はいますか?

4

1 に答える 1

0

少し遅れて、あなたの質問に出くわしましたが、おそらく私はまだ助けることができます.

エラーの原因を特定するのは複雑ですが、意図した実装に問題があることがわかります。カスタム if ヘルパーをプロパティ 'score' にバインドしていますが、応答の変化を監視するプロパティは 'can' と呼ばれています。 、ヘルパーとして... (しかし、これはヘルパーから観察されておらず、とにかく拘束されていません!)

于 2015-03-20T15:15:12.307 に答える