J'ai un objet record :

2.7.0 :005 > o = OauthUser.first
  OauthUser Load (0.5ms)  SELECT "oauth_users".* FROM "oauth_users" ORDER BY "oauth_users"."id" ASC LIMIT $1  [["LIMIT", 1]]
2.7.0 :006 > o
 => #<OauthUser id: 1, name: "Person Name", email: "person@email.com", oauth_id: "111111111111111", oauth_provider: "google", oauth_token: "blahblahblah...", oauth_refresh_token: nil, oauth_expires_at: "2020-11-13 18:22:24", sync_emails: nil, last_email_sync: nil, manual_query: nil, created_at: "2020-11-13 17:22:25", updated_at: "2020-11-13 17:22:25"> 

D'une manière rapide et sale, je lance simplement cela dans une vue avec un appel .to_json afin que je puisse voir les différents attributs à l'écran. Mais je souhaite supprimer quelques attributs que je ne souhaite pas afficher ou que je ne devrais pas afficher pour des raisons de sécurité.

Je pensais pouvoir écrire une méthode comme celle-ci :

# app/models/oauth_user.rb
def details
  # don't show sensitive tokens, only show fields I care to see
  pluck(:id, :oauth_id, :oauth_expires_at, :sync_emails, :last_email_sync, :manual_query)
end

Mais pluck est pour les requêtes.

Je sais que je pourrais faire quelque chose manuellement dans la vue ou créer un hachage dans le modèle, mais je pense qu'il existe déjà une méthode pour ce que je recherche, mais je ne la trouve pas sur Google.

J'ai déjà un seul enregistrement, je n'ai pas besoin d'interroger avec pluck ou select ; ou map résultats.

Existe-t-il un moyen simple de mettre en liste blanche ou en liste noire les attributs que je souhaite afficher pour un seul enregistrement ?

J'ai essayé pluck, select, map et tap en vain.

0
Chiperific 13 nov. 2020 à 20:48

1 réponse

Meilleure réponse

On dirait qu'il existe un nombre décent d'options, mais en général, vous parlez d'un modèle de présentateur.

Si vous vouliez un Hash de votre modèle, ce serait simple :

def details
  attributes.slice('id', 'oauth_id', 'oauth_expires_at', 
                   'sync_emails', 'last_email_sync', 'manual_query') 
end 

Si vous vouliez un objet plus formel, c'est là qu'intervient le présentateur (il existe de nombreuses bibliothèques pour cela, mais nous allons simplement écrire la nôtre pour cette question)

class OauthUserPresenter
  WHITELIST = %w(id oauth_id oauth_expires_at sync_emails last_email_sync manual_query)
  WHITELIST.each {|attr| define_method(attr) {@_exposed_attributes[attr]}}

  def initialize(user) 
     @_exposed_attributes = user.attributes.slice(WHITELIST)
  end 

  def to_hash #this will allow for #as_json and #to_json 
    @_exposed_attributes
  end

end 

Ensuite, vous pouvez appeler en tant que

o = OauthUserPresenter.new(OauthUser.first)

Maintenant o est techniquement un objet présentateur en lecture seule. Aucun des autres attributs ne sera exposé et vous pouvez toujours accéder aux méthodes comme id, oauth_id, etc.

Les présentateurs vous permettent également d'ajouter d'autres méthodes sans encombrer le modèle, par ex.

class OauthUserPresenter
   def expired? 
     begin
       Time.parse(oauth_expires_at) <= Time.now
     rescue TypeError, ArgumentError #handle nil, empty string, and invalid times
       true
     end
   end 
end 
3
engineersmnky 13 nov. 2020 à 19:55