render :string
to send text to the client in response, which means doing the entire render process. And yet, we wanted to reduce it as much as possible.CallStackPrinter
with CallStackPrinter
(the best way to visualize profile data from a Ruby application, from all I've seen). We also wrote several benchmarks that could duplicate the profiler in the course of its work in order to focus on a particular site and obtain more accurate data.Content-Type
header, which has two components (the content-type itself and the optional charset). Both components were available in the Response object via a getter and a setter:Copy Source | Copy HTML<br/> def content_type =(mime_type)<br/> self .headers[ "Content-Type" ] =<br/> if mime_type =~ / charset / || (c = charset ). nil ?<br/> mime_type.to_s<br/> else <br/> "#{mime_type}; charset=#{c}" <br/> end <br/> end <br/> <br/> # Returns the response's content MIME type, or nil if content type has been set. <br/> def content_type <br/> content_type = String (headers[ "Content-Type" ] || headers[ "type" ]). split ( ";" )[ 0 ]<br/> content_type .blank? ? nil : content_type <br/> end <br/> <br/> # Set the charset of the Content-Type header. Set to nil to remove it. <br/> # If no content type is set, it defaults to HTML. <br/> def charset =( charset )<br/> headers[ "Content-Type" ] =<br/> if charset <br/> "#{content_type || Mime::HTML}; charset=#{charset}" <br/> else <br/> content_type || Mime ::HTML.to_s<br/> end <br/> end <br/> <br/> def charset <br/> charset = String (headers[ "Content-Type" ] || headers[ "type" ]). split ( ";" )[ 1 ]<br/> charset .blank? ? nil : charset .strip. split ( "=" )[ 1 ]<br/> end <br/>
Copy Source | Copy HTML<br/> def assign_default_content_type_and_charset !<br/> self .content_type ||= Mime ::HTML<br/> self .charset ||= default_charset unless sending_file?<br/> end <br/>
Content-Type
header semicolon and then did more work with strings to connect them together again. And of course, Response#content_type=
used in other parts of Rails to properly set it depending on the type of template or inside the respond_to
blocks.Copy Source | Copy HTML<br/>attr_accessor :charset, :content_type<br/> <br/> def assign_default_content_type_and_charset !<br/> return if headers[CONTENT_TYPE].present?<br/> <br/> @content_type ||= Mime ::HTML<br/> @charset ||= self . class .default_charset<br/> <br/> type = @content_type. to_s .dup<br/> type < < "; charset=#{@charset}" unless @sending_file<br/> <br/> headers[CONTENT_TYPE] = type<br/> end <br/>
Copy Source | Copy HTML<br/> def render_partial_collection (options = {}) #:nodoc: <br/> return nil if options[:collection].blank?<br/> <br/> partial = options[:partial]<br/> spacer = options[:spacer_template] ? render (:partial => options[:spacer_template]) : '' <br/> local_assigns = options[:locals] ? options[:locals].clone : {}<br/> as = options[:as]<br/> <br/> index = 0 <br/> options[:collection].map do |object|<br/> _partial_path ||= partial ||<br/> ActionController::RecordIdentifier.partial_path(object, controller. class .controller_path)<br/> template = _pick_partial_template(_partial_path)<br/> local_assigns[template.counter_name] = index<br/> result = template.render_partial( self , object, local_assigns.dup, as)<br/> index += 1 <br/> result<br/> end .join(spacer).html_safe!<br/> end <br/>
Copy Source | Copy HTML<br/>with = [opts. delete (:with)].flatten<br/>as = (opts. delete (:as) || template.match(%r[(?:.*/)?_([^\./]*)])[ 1 ]).to_sym<br/> <br/> # Ensure that as is in the locals hash even if it isn't passed in here <br/> # so that it's included in the preamble. <br/>locals = opts.merge(:collection_index => - 1 , :collection_size => with.size, as => opts[as])<br/>template_method, template_location = _template_for(<br/> template,<br/> opts. delete (: format ) || content_type,<br/> kontroller,<br/> template_path,<br/> locals.keys)<br/> <br/> # this handles an edge-case where the name of the partial is _foo.* and your opts <br/> # have :foo as a key. <br/>named_local = opts.key?(as)<br/> <br/>sent_template = with.map do |temp|<br/> locals[as] = temp unless named_local<br/> <br/> if template_method && self . respond_to ?(template_method)<br/> locals[:collection_index] += 1 <br/> send(template_method, locals)<br/> else <br/> raise TemplateNotFound, "Could not find template at #{template_location}.*" <br/> end <br/> end .join<br/> <br/>sent_template <br/>
sent_template = with.map
). Unlike ActionView, which figured out the name of the template, took the template object, the name of the counter, etc., Merb limited the activity inside the loop to setting several Hash values and calling the method._article.html.erb
, etc.) . This means that it is not always possible to determine the exact pattern that needs to be rendered.render :partial => "name", :collection => @array
faster. To achieve this, we split the logic into 2 ways: faster for the case when we know the pattern, and slower for the case when it needs to be defined depending on the object.Copy Source | Copy HTML<br/> def collection_with_template (template = @template)<br/> segments, locals, as = [], @locals, @options[:as] || template.variable_name<br/> <br/> counter_name = template.counter_name<br/> locals[counter_name] = - 1 <br/> <br/> @collection.each do |object|<br/> locals[counter_name] += 1 <br/> locals[as] = object<br/> <br/> segments < < template. render (@view, locals)<br/> end <br/> <br/> @template = template<br/> segments<br/> end <br/>
Source: https://habr.com/ru/post/90160/
All Articles