New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Action Pack Variants #12977
Action Pack Variants #12977
Conversation
| @@ -57,6 +57,10 @@ def _normalize_options(options) #:nodoc: | |||
| if options[:status] | |||
| options[:status] = Rack::Utils.status_code(options[:status]) | |||
| end | |||
| require 'pry';binding.pry | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a debug statement left in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shit, I knew I've missed something. Thanks! ;)
|
Thanks for the review, it's very valuable for me! <3 I've just pushed commit with fixes addressing your comments (separate commit to have nice diff, i'll squash it before merging). I've left some open questions questions and didn't moved setting variant from |
|
While polishing this PR I've stuck with the very last thing - nice a logical place to set variant in lookup context (#12977 (comment)). Suprisingly for various reasons it's not that straight forward as one would expect. I got suggestion by @josevalim to change implementation a bit and instead of setting it in request object ( |
|
I'd prefer to have it set the same way that format is set. It's an extension to the format, and the format is set on the request. I don't think we need to change this. If anything, self.variant is going to be less clear IMO. Request#variant implies that this is a per request setting as well.
|
|
Ditto. The request format has a well traveled path from Rack env to middleware to controller action to view resolver. The request variant walks the same path. It the variant diverges and needs some special handling, that's a strong sign that we should double-check why and adjust course so format & variant continue to behave alike. From the implementation so far, it looks like your sticking point may be due to seeing that request formats are set on the lookup context before processing an action: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/rendering.rb#L5-L9 If the variant is set before processing, then you can't set the request.variant within an action. No good. Trouble is, the way we manage the format today is pretty awkward. We set it on the lookup context (aka, the controller) because we don't want the view to "know about" requests. Fine, ok. To fix, set the format and variant on the lookup context just before rendering. The likely candidate for that is |
|
Thanks guys. I agree with you, it was Jose's suggestion to overcome problem with finding nice place to inject this functionality. @jeremy nicely described what's going on and suggested The best place for this to happen, in my opinion would be Can it stay the way it was initially proposed then |
|
|
|
I've rebased and force pushed commit with all comments addressed. If there's no other issues, I'll happily merge this |
|
@jeremy regarding @rafaelfranca removed additional hash lookup and added docs |
| # app/views/projects/show.html+tablet.erb | ||
| # app/views/projects/show.html+phone.erb | ||
| # | ||
| # If `request.variant = :tablet` is set, we'll automatically be rendering the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is rdoc so will not work, it should berequest.variant = :tablet`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
| # end | ||
| # end | ||
| # | ||
| # This is modeled loosely on custom mime types, but it's specifically not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems an implementation detail, maybe we should omit this first sentence and keep others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, I actually think we should either leave it or remove whole paragraph. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to remove the whole paragraph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Me too
|
Thanks @rafaelfranca, I've just pushed fixes to docs. |
|
|
| If request.variant = :tablet is set, we'll automatically be rendering the | ||
| html+tablet template. | ||
|
|
||
| In the controller, we can also tailer to the variants with this syntax: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the controller, can we respond to variants just like we respond to formats:
|
| @@ -102,6 +102,7 @@ def _process_format(format) | |||
| # :api: private | |||
| def _normalize_render(*args, &block) | |||
| options = _normalize_args(*args, &block) | |||
| options[:variant] = request.variant if defined?(request) && request.variant.present? | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't need this defined? check right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid we need: #12977 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are leaving this here, I'd leave a comment/todo do remove it in the future, as @rafaelfranca commented, it seems kinda weird having to do this check if we are inside action pack.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! I've just done that :)
On Tue, Dec 3, 2013 at 12:38 PM, Carlos Antonio da Silva <
notifications@github.com> wrote:
In actionpack/lib/abstract_controller/rendering.rb:
@@ -102,6 +102,7 @@ def _process_format(format)
# :api: private
def _normalize_render(_args, &block)
options = _normalize_args(_args, &block)
options[:variant] = request.variant if defined?(request) && request.variant.present?If we are leaving this here, I'd leave a comment/todo do remove it in the
future, as @rafaelfranca https://github.com/rafaelfranca commented, it
seems kinda weird having to do this check if we are inside action pack.—
Reply to this email directly or view it on GitHubhttps://github.com//pull/12977/files#r8057129
.
| # | ||
| # You can set the variant in a before_action: | ||
| # | ||
| # request.variant = :tablet if request.user_agent =~ /iPad/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be 2 spaces here too :)
By default, variants in the templates will be picked up if a variant is set
and there's a match. The format will be:
app/views/projects/show.html.erb
app/views/projects/show.html+tablet.erb
app/views/projects/show.html+phone.erb
If request.variant = :tablet is set, we'll automatically be rendering the
html+tablet template.
In the controller, we can also tailer to the variants with this syntax:
class ProjectsController < ActionController::Base
def show
respond_to do |format|
format.html do |html|
@stars = @project.stars
html.tablet { @notifications = @project.notifications }
html.phone { @chat_heads = @project.chat_heads }
end
format.js
format.atom
end
end
end
The variant itself is nil by default, but can be set in before filters, like
so:
class ApplicationController < ActionController::Base
before_action do
if request.user_agent =~ /iPad/
request.variant = :tablet
end
end
end
This is modeled loosely on custom mime types, but it's specifically not
intended to be used together. If you're going to make a custom mime type,
you don't need a variant. Variants are for variations on a single mime
types.
|
|
|
<3 thank you @strzalek |
By default, variants in the templates will be picked up if a variant is set and
there's a match. The format will be:
If
request.variant = :tabletis set, we'll automatically be rendering the html+tablet template.In the controller, we can also tailer to the variants with this syntax:
The variant itself is nil by default, but can be set in before filters, like so:
This is modeled loosely on custom mime types, but it's specifically not intended
to be used together. If you're going to make a custom mime type, you don't need
a variant. Variants are for variations on a single mime types.
/cc @dhh @josevalim