[Question/Support] Is there anyway to access controller methods (i.e. current_user) in blueprints?
dylandamsma opened this issue · 3 comments
Is there an existing issue for this?
- I have searched the existing issues
Describe your question or ask for support
I have a MatchBlueprint that is being used heavily across my other blueprints and APIs.
The MatchBlueprint contains a custom field:
field :high_fives do |match, options|
{
high_fives_count: match.high_fives_count,
high_fived: match.high_fived_by?(current_user)
}
end
However, current_user is not available to the blueprint, even though it is in the controller the blueprint is rendered from. I don't want to pass it as an option, because then I need to pass it in many places. Is there anyway to set this globally or access the controller method somehow?
I kind of expected it to work like a view, as: "It heavily relies on the idea of views which, similar to Rails views, are ways of predefining output for data in different contexts."
👋 Hey @dylandamsma!
If you need to provide additional context to a Blueprint, I would suggest providing it via the options
argument on render
. If it's always needed, and you would like to avoid passing it in everywhere, then you could also consider one of:
- Decorating the
Match
object before rendering, so that you can simply callmatch.high_fived
in theBlueprint
without needing thecurrent_user
context. - Storing and exposing
current_user
on a per-request basis via a thread-safe store (e.g. ActiveSupport::CurrentAttributes or RequestStore), and invoke that within the Blueprint.
I kind of expected it to work like a view, as: "It heavily relies on the idea of views which, similar to Rails views, are ways of predefining output for data in different contexts."
That's a fair assumption. We may want to rephrase this in the README
though, as there's intentionally no "Rails magic" at play here; it's like a view in that it's responsible for presentation/serialization of data, but not specifically analogous to how ERB
views work in Rails.
Thank you for the quick response and, let me say it now, because I forgot to mention it earlier: Great work on Blueprinter and I really like this approach. Especially the ability to define views and therefore be more efficient in the data I render to the API.
In the end, I solved it by using a Current.rb model that has the user attribute. Seems that can be accessed in a blueprint, so that did the trick. Now I can call Current.user within:
field :high_fives do |match, options|
{
high_fives_count: match.high_fives_count,
has_high_fived: match.high_fived_by?(Current.user)
}
end
The reason I mentioned the views, is because I am used to JB / JBuilder gems, which function similar to erb views.
Thank you for the quick response and, let me say it now, because I forgot to mention it earlier: Great work on Blueprinter and I really like this approach. Especially the ability to define views and therefore be more efficient in the data I render to the API.
In the end, I solved it by using a Current.rb model that has the user attribute. Seems that can be accessed in a blueprint, so that did the trick. Now I can call Current.user within:
field :high_fives do |match, options| { high_fives_count: match.high_fives_count, has_high_fived: match.high_fived_by?(Current.user) } end
The reason I mentioned the views, is because I am used to JB / JBuilder gems, which function similar to erb views.
It's possible to use ERB views to render blueprints if you want. See here #397
Also like lessthanjacob said, you can also provide your current_user like this
MyBlueprint.render_as_hash(record, user: current_user)
then in your fields
field :high_fives do |match, options|
options[:user]
=> user
end