mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-22 22:06:50 +00:00
Merge pull request #240 from beerlington/scope-name-alias
Adding scope_name method to alias scope in Serializer
This commit is contained in:
commit
324f9d83b3
@ -1,5 +1,9 @@
|
||||
# unreleased
|
||||
|
||||
* Add an alias for `scope` method to be the name of the context. By default
|
||||
this is `current_user`. The name is automatically set when using
|
||||
`serialization_scope` in the controller.
|
||||
|
||||
# VERSION 0.7
|
||||
|
||||
|
||||
|
||||
23
README.md
23
README.md
@ -232,22 +232,22 @@ end
|
||||
Within a serializer's methods, you can access the object being
|
||||
serialized as `object`.
|
||||
|
||||
You can also access the `scope` method, which provides an
|
||||
authorization context to your serializer. By default, scope
|
||||
You can also access the `current_user` method, which provides an
|
||||
authorization context to your serializer. By default, the context
|
||||
is the current user of your application, but this
|
||||
[can be customized](#customizing-scope).
|
||||
|
||||
Serializers will check for the presence of a method named
|
||||
`include_[ATTRIBUTE]?` to determine whether a particular attribute should be
|
||||
included in the output. This is typically used to customize output
|
||||
based on `scope`. For example:
|
||||
based on `current_user`. For example:
|
||||
|
||||
```ruby
|
||||
class PostSerializer < ActiveModel::Serializer
|
||||
attributes :id, :title, :body, :author
|
||||
|
||||
def include_author?
|
||||
scope.admin?
|
||||
current_user.admin?
|
||||
end
|
||||
end
|
||||
```
|
||||
@ -325,7 +325,7 @@ class PersonSerializer < ActiveModel::Serializer
|
||||
|
||||
def attributes
|
||||
hash = super
|
||||
if scope.admin?
|
||||
if current_user.admin?
|
||||
hash["ssn"] = object.ssn
|
||||
hash["secret"] = object.mothers_maiden_name
|
||||
end
|
||||
@ -353,7 +353,7 @@ class PostSerializer < ActiveModel::Serializer
|
||||
|
||||
# only let the user see comments he created.
|
||||
def comments
|
||||
object.comments.where(:created_by => scope)
|
||||
object.comments.where(:created_by => current_user)
|
||||
end
|
||||
end
|
||||
```
|
||||
@ -395,7 +395,7 @@ class PostSerializer < ActiveModel::Serializer
|
||||
has_many :comments
|
||||
|
||||
def include_associations!
|
||||
include! :author if scope.admin?
|
||||
include! :author if current_user.admin?
|
||||
include! :comments unless object.comments_disabled?
|
||||
end
|
||||
end
|
||||
@ -587,7 +587,7 @@ Ajax requests, you probably just want to use the default embedded behavior.
|
||||
|
||||
## Customizing Scope
|
||||
|
||||
In a serializer, `scope` is the current authorization scope which the controller
|
||||
In a serializer, `current_user` is the current authorization scope which the controller
|
||||
provides to the serializer when you call `render :json`. By default, this is
|
||||
`current_user`, but can be customized in your controller by calling
|
||||
`serialization_scope`:
|
||||
@ -598,6 +598,9 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
```
|
||||
|
||||
The above example will also change the scope name from `current_user` to
|
||||
`current_admin`.
|
||||
|
||||
Please note that, until now, `serialization_scope` doesn't accept a second
|
||||
object with options for specifying which actions should or should not take a
|
||||
given scope in consideration.
|
||||
@ -626,12 +629,12 @@ class CitiesController < ApplicationController
|
||||
def show
|
||||
@city = City.find(params[:id])
|
||||
|
||||
render :json => @city, :scope => current_admin?
|
||||
render :json => @city, :scope => current_admin, :scope_name => :current_admin
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Assuming that the `current_admin?` method needs to make a query in the database
|
||||
Assuming that the `current_admin` method needs to make a query in the database
|
||||
for the current user, the advantage of this approach is that, by setting
|
||||
`serialization_scope` to `nil`, the `index` action no longer will need to make
|
||||
that query, only the `show` action will.
|
||||
|
||||
@ -261,6 +261,13 @@ module ActiveModel
|
||||
|
||||
def initialize(object, options={})
|
||||
@object, @options = object, options
|
||||
|
||||
scope_name = @options[:scope_name]
|
||||
if scope_name && !respond_to?(scope_name)
|
||||
self.class.class_eval do
|
||||
define_method scope_name, lambda { scope }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def root_name
|
||||
|
||||
@ -31,6 +31,7 @@ module ActiveModel
|
||||
if serializer
|
||||
serialization_scope = controller.send(:serialization_scope)
|
||||
options[:scope] = serialization_scope unless options.has_key?(:scope)
|
||||
options[:scope_name] = controller.send(:_serialization_scope)
|
||||
options[:url_options] = controller.send(:url_options)
|
||||
render(given_options.merge(self.options).merge(:json => serializer.new(resource, options)))
|
||||
else
|
||||
@ -40,4 +41,4 @@ module ActiveModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
67
test/serialization_scope_name_test.rb
Normal file
67
test/serialization_scope_name_test.rb
Normal file
@ -0,0 +1,67 @@
|
||||
require 'test_helper'
|
||||
require 'pathname'
|
||||
|
||||
class DefaultScopeNameTest < ActionController::TestCase
|
||||
TestUser = Struct.new(:name, :admin)
|
||||
|
||||
class UserSerializer < ActiveModel::Serializer
|
||||
attributes :admin?
|
||||
def admin?
|
||||
current_user.admin
|
||||
end
|
||||
end
|
||||
|
||||
class UserTestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
before_filter { request.format = :json }
|
||||
|
||||
def current_user
|
||||
TestUser.new('Pete', false)
|
||||
end
|
||||
|
||||
def render_new_user
|
||||
respond_with TestUser.new('pete', false), :serializer => UserSerializer
|
||||
end
|
||||
end
|
||||
|
||||
tests UserTestController
|
||||
|
||||
def test_default_scope_name
|
||||
get :render_new_user
|
||||
assert_equal '{"user":{"admin":false}}', @response.body
|
||||
end
|
||||
end
|
||||
|
||||
class SerializationScopeNameTest < ActionController::TestCase
|
||||
TestUser = Struct.new(:name, :admin)
|
||||
|
||||
class AdminUserSerializer < ActiveModel::Serializer
|
||||
attributes :admin?
|
||||
def admin?
|
||||
current_admin.admin
|
||||
end
|
||||
end
|
||||
|
||||
class AdminUserTestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
serialization_scope :current_admin
|
||||
before_filter { request.format = :json }
|
||||
|
||||
def current_admin
|
||||
TestUser.new('Bob', true)
|
||||
end
|
||||
|
||||
def render_new_user
|
||||
respond_with TestUser.new('pete', false), :serializer => AdminUserSerializer
|
||||
end
|
||||
end
|
||||
|
||||
tests AdminUserTestController
|
||||
|
||||
def test_override_scope_name_with_controller
|
||||
get :render_new_user
|
||||
assert_equal '{"admin_user":{"admin":true}}', @response.body
|
||||
end
|
||||
end
|
||||
@ -1338,5 +1338,18 @@ class SerializerTest < ActiveModel::TestCase
|
||||
|
||||
end
|
||||
|
||||
def test_scope_name_method
|
||||
serializer = Class.new(ActiveModel::Serializer) do
|
||||
def has_permission?
|
||||
current_user.super_user?
|
||||
end
|
||||
end
|
||||
|
||||
user = User.new
|
||||
user.superuser = true
|
||||
post = Post.new(:title => 'Foo')
|
||||
|
||||
a_serializer = serializer.new(post, :scope => user, :scope_name => :current_user)
|
||||
assert a_serializer.has_permission?
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user