#ruby-on-rails #ruby
#ruby-on-rails #ruby
Вопрос:
У меня есть объект записи:
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">
Быстрым, грязным способом я просто добавляю это в представление с .to_json
помощью вызова, чтобы я мог видеть различные атрибуты на экране.
Но я хочу удалить несколько атрибутов, которые я не хочу отображать или не должен отображать по соображениям безопасности.
Я думал, что мог бы просто написать такой метод:
# 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
Но pluck
для запросов.
Я знаю, что мог бы вручную что-то сделать в представлении или создать хэш в модели, но я думаю, что уже есть метод для того, что мне нужно, просто не найдя его в Google.
У меня уже есть одна запись, не нужно запрашивать с pluck
помощью или select
; или map
результатов.
Есть ли простой способ внести в белый список или черный список атрибуты, которые я хочу отобразить для одной записи?
Я пробовал pluck
, select
, map
и tap
безрезультатно.
Комментарии:
1. о чем
.to_json(only: %w[id oauth_id])
? Или.to_json(except: [...])
2. Вау. Я не думал мутировать JSON, и я не знал, что вы можете сделать
only
иexcept
на них. Спасибо! Если вы хотите опубликовать это в качестве ответа, я приму это и дам вам эти приятные, приятные моменты.3. Вы также можете использовать
attributes.values_at(:id, :oauth_id, :etc)
для получения массива, подобногоpluck
gives4. Гениально! @maxpleaner, спасибо!!
Ответ №1:
Похоже, что существует приличное количество вариантов, но, вообще говоря, то, о чем вы говорите, — это шаблон presenter.
Если бы вы хотели Hash
получить из своей модели, это было бы просто:
def details
attributes.slice('id', 'oauth_id', 'oauth_expires_at',
'sync_emails', 'last_email_sync', 'manual_query')
end
Если вам нужен более формальный объект, то здесь появляется presenter (для этого есть много библиотек, но мы просто напишем нашу собственную ради этого вопроса)
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
Затем вы можете вызвать как
o = OauthUserPresenter.new(OauthUser.first)
технически o
это объект presenter только для чтения. Ни один из других атрибутов не будет раскрыт, и вы по-прежнему можете получить доступ к методам как id
, oauth_id
, и т.д.
Презентаторы также позволяют добавлять другие методы, не загромождая модель, например
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
Комментарии:
1. В этом случае хэш полностью в порядке, но я действительно ценю обзор докладчика. Кое-что, о чем я начал слышать, но еще не проверил. Спасибо!