Use current_user variable in template ?
Closed this issue ยท 8 comments
Hello,
I'm trying to get around the best way to add session data to my templates.
For instance, my user1 is requesting the profile of user2 with the user http://domain/users/2.json
My template looks like something like that :
api_accessible :default do |t|
t.add :id
t.add :name
t.add :avatar_image
t.add lambda{|u| u.following?(current_user)}, :as => :following
end
But the current_user variable is not available in the model. Is there a way around that with the current implementation of the gem ?
Thanks for your help !
Hi,
I guess you are talking about a helper method called current_user
like it is used by devise.
You can't access them because the current_user
method is defined on a controller while acts_as_api
renders the template on a model.
The gem does not provide a workaround for this. In case you can't find a model-only solution you'll have to bridge it yourself.
I'm closing this ticket, as a don't see this as a problem caused by the lib.
However, if you need assistance solving your issue, feel free to contact me. :)
Best,
Chris
Hello,
As I see it, we can't make the current_user helper method available in the model without breaking the MVC convention.
However we could I guess, pass extra variables to the render_for_api methods so they are available ?
Something like this :
render_for_api :default, :json => @users, :root => :users, :variables => {:current_user => current_user}
But maybe there is a better "Rails Way" to do this ?
Sorry for the late answer :(
I also thought about passing variables a couple times, but I decided not to add it because:
- You can pass the variables only at one point, and only all at once. Once you'll need different information for attributes this will get messy
- What do you do with subresources?
- In fact, it would also break MVC, but in a much less flexible way than a custom solution would.
I also have had this kind of problem and generally it think acts_as_api should not be responsible for gathering the data.
The approach above will create e.g. N+1 queries in sql databases. It would be better if you could determine it when you fetch the data and before you pass it to acts_as_api.
I hope this helps. :)
I have been doing something like this to show relavent data about the current user. Using neo4j.
response_hash = @post.as_api_response :show
if current_user
if rel = current_user.rel_to(@post)
response_hash[:rel] = rel.as_api_response :show
It works because as_api_response returns a simple hash, which can be added to.
Hi,
in fact, most of the time I don't use acts_as_api
in AR models anymore, but in minimal presenter classes instead. This is much clearer in the separation of concerns and you can add the current user pretty easy.
Here is a simple example, how this can be done:
# in app/presenters
class Presenter
attr_accessor :proxy
attr_accessor :current_user
def initialize(proxy, options = {})
@proxy = proxy
current_user = options[:current_user] if options.has_key?(:current_user)
end
end
class PostPresenter < Presenter
extend ActsAsApi::Base
acts_as_api
delegate :title, :body,
:to => :proxy
api_accessible :default do |template|
template.add :title
template.add :body
template.add :author_name
end
def author_name
current_user.name
end
end
# in your controller
PostPresenter.new(@post, current_user: current_user).as_api_response(:default)
I have a similar problem, but I want to limit the number of child associations in a template .i.e.
the limit would be a param. in the request if not present default value of 10
api_accessible :v1_list do |template|
binding.pry
template.add :id
template.add :parent_id
template.add :client_id
template.add :reference
template.add :created_at
template.add :updated_at
template.add :closed_at
template.add :subtype_id
template.add :state
template.add lambda{ |incident| incident.items.first(limit) }, :template => :v1_list, :as => :items
end
So how can I add this, must I use presenter?, or I have any alternatives
Hi! You can pass options to as_api_response
, see these examples.
They will get passed as the second argument to all lambdas.
So in your case it would work like this:
MyModel.api_accessible :v1_list do |template|
binding.pry
template.add :id
template.add :parent_id
template.add :client_id
template.add :reference
template.add :created_at
template.add :updated_at
template.add :closed_at
template.add :subtype_id
template.add :state
template.add lambda{ |incident, options| incident.items.first(options[:limit]) }, :template => :v1_list, :as => :items
end
MyModel.as_api_response(:v1_list, limit: 10)
I hope this helps!