4

How can I pass an argument to a model method using grape entity ?

I'd like to check wheter the current_user likes an item when presenting the item, so I built a model user_likes? method:

class Item
  include Mongoid::Document
  #some attributes here...
  has_and_belongs_to_many :likers

  def user_likes?(user)
    likers.include?(user)
  end
end

but I don't know how to send current_user to the grape-entity model :

module FancyApp
  module Entities
    class Item < Grape::Entity
      expose :name #easy
      expose :user_likes # <= How can I send an argument to this guy ?
    end 
  end
end

in the grape api:

get :id do
  item = Item.find(.....)
  present item, with: FancyApp::Entities::Item # I should probably send current_user here, but how ?
end

I feel like the current_user should probably be sent from this last piece of code, but I can't figure how to do it :(

Any thoughts ? Thanks !

aherve
  • 3,795
  • 6
  • 28
  • 41

3 Answers3

7

Well, I found I could pass current as a parameters, and use it in a block. So :

present item, with: FancyApp::Entities::Item, :current_user => current_user 

and in the entity definition:

expose :user_likes do |item,options|
  item.user_likes?(options[:current_user])
end
aherve
  • 3,795
  • 6
  • 28
  • 41
  • It might let you do it, doesn't mean it's the best way though. Cleaner the way I suggested. – oliverbarnes Apr 21 '14 at 15:29
  • @Oliver Barnes I'm new to Grape entities can you elaborate on how your suggestion is cleaner? It seems to me, in your suggestion, you are altering the actual record in the database just to pass it to the entity, this doesn't seem clean to me. – mfunaro Oct 10 '14 at 20:23
  • 2
    I'd actually recommand NOT to use `update_attributes` in any case. It does indeed perform a database altering, and you absolutely do NOT want that. If two users simultaneously request your route, then you'd have a great chance of mixing the `current_user` value for at least one of the users. – aherve Oct 11 '14 at 11:26
  • True, don't know what I was thinking. Answered in a haste probably - deleted – oliverbarnes Oct 13 '14 at 14:03
0

@aherve, for some reason your syntax won't work in my case. The syntax in Grape Entity docs is a little different

your example, the syntax should be:

expose(:user_likes) { |item, options| item.user_likes?(options[:current_user]) }
tkhuynh
  • 941
  • 7
  • 15
0

Another way would be to store the current user in the item temporarily by defining an attribute accessor:

class Item
  include Mongoid::Document
  #some attributes here...
  has_and_belongs_to_many :likers
  attr_accessor :current_user

  def user_likes
    likers.include?(current_user)
  end
end

and in the grape api set the current user:

get :id do
  item = Item.find(.....)
  item.current_user = current_user
  present item, with: FancyApp::Entities::Item
end

no changes to the grape-entity model is needed.
There is no database field current_user_id or so. No writes to database.

Martin M
  • 8,430
  • 2
  • 35
  • 53