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