Rails 4: why is one way of rendering partials so much faster? - ruby

I'm not sure if this is a Rails specific issue, hence the reason I tagged it ruby as well.
I'm rendering a collection of event records via a partial. However, I found that rendering the partial differently results in drastic performance differences.
Both version use the exact same data, the only thing changing is the code used to render the partials.
Why the heck is one version consistently 4x faster than the other? Makes me wonder what other performance hits I'm taking...
Slow version (950ms total request time):
<% events.each do |event| %>
<%= render partial: "events/event", locals: { event: event } %>
<% end %>
# Log output
Rendered events/_event.html.erb (1.1ms)
Rendered events/_event.html.erb (1.1ms)
...
Faster version (250ms total request time):
<%= render partial: "events/event", collection: events, as: :event %>
# Log output
Rendered events/_event.html.erb (58.7ms)

example 1:
you are rendering a partial x times (depending on events).
which means you are compiling html x times(once each time the loop runs). which is slow
example 2:
you are rendering one partial with a collection of events
the html is compiled once(as there is only one partial). which is fast

Related

Using content_for and yield_content in Ramaze

Sinatra has sinatra/contrib to asist with this, what's the equivalent in Ramaze? I'm using Erubis by the way. Also, a quick Google search shows up really old pages that insist setting variables in the controllers and using them in the views.
Edit 1:
Taken from the gem documentation (http://www.sinatrarb.com/contrib/content_for.html)
You call content_for, generally from a view, to capture a block of markup giving it an identifier:
# index.erb
<% content_for :some_key do %>
<chunk of="html">...</chunk>
<% end %>
Then, you call yield_content with that identifier, generally from a layout, to render the captured block:
# layout.erb
<%= yield_content :some_key %>
I don't think Ramaze can do this natively. But you could quite easily do this manually, write a helper to do this, or even fill-in a Hash instance.
You might also want to look at partials if you need to render small chunks of HTML in loops.
You could also combine render_partial, store results in a hash, and yield it's content in the layout.
If the use case is something like rendering a sidebar, you probably want to write a helper so you take the logic out of your views.
A trivial example is here : https://github.com/Ramaze/ramaze/wiki/Adding-a-dynamic-sidebar-in-a-layout

Use rspec with capybara-webkit or selenium to measure page load times

I'm hoping to find a way to write rspec scripts (or something else) that can be used to measure page load times. So similar to how firebug can tell when a page has fully loaded, is there a similar way to do that in rspec?
Or even any other ruby gem?
Thanks!
You can use benchmark in your views:
<% benchmark("Showing projects partial") do %>
<%= yield %>
<% end %>
If you do this in your application layout you'll have a log with page loads:
Showing projects partial (0.0ms)

rendering Ruby statements inside of rails views?

So in my DB I want stored a ruby/HTML statement in the Database Table such as -
p This site is owned from 2000 - #{Time.now.year} by Acme Widget Co. /p
Or let's say that I want people to be able to include in other code snippits - e.g.
A client wants to run in a show view in the middle of a paragraph some magical partial such as #{render 'my_magical_code'}
On the view I have this being rendered as <%= raw(#page.content) %>
But its like a double rendering and rails will just put on the page #{render 'my_magical_code'} or #{Time.now.year}
So can / how do I solve this?
Thanks!
There are work arounds but I think the most proper way to solve your problem is to store your information in a better way. Add a migration to your model with a year_founded and company rows. You can then call these in your views rather than storing the HTML. Eg. This site is owned from <%= #object.year_founded %> to <%= Time.now.year %> by <%= #object.company %>

Remote Method Understanding?

In rails 3
While using remote method form submit, it affects the database twice with the same form values.
controller file:
#user_message = UserMessage.new(params[:user_message])
if #user_message.save
render :update
else
render :nothing => true
end
view file:
<%= form_tag ('/feedback/user_message'), :method =>'post', :remote=> true, :id=>'user_message' do%>
<%= hidden_field_tag 'user_message[user_id]', #user.user_id %>
<h2><%= #question %></h2>
<%= text_area_tag 'user_message[msg]',"", :size=>"40x5" %>
<%= submit_tag "Submit"%>
<% end %>
When I hit the submit button it creates two records on the table.
Why?
There may be couple of things that might be causing this
may be the ujs file is included twice may may be like
//= require jquery_ujs // expected to load from the rails-jquery gem
//= require_tree . // if any file is present in assets directory hierarchy it will be loaded
Or just a bug taking your sleep away
https://github.com/rails/jquery-ujs/issues/208
check out more solutions
Jquery Rails 3... form submits twice... deletes twice... help
Rails 3.1 remote requests submitting twice
This may also be related to the understanding of asset pipeline when and how use pecompiled assets.
I always use this config in development mode
config.server_static_assets = false
this forces the app to call the assets from app assets
and use precompiled assets from public in production mode
The problem most likely related to asset pipeline
You should precompiled the asset pipeline before.
This will create two copy of rails.js, one in your assets and one in application.js
This is a bug or gotcha in rails 3
See here http://www.ruby.code-experiments.com/blog/2011/10/another-gotcha-with-the-rails-31-asset-pipeline-or-why-are-my-jquery-ujs-ajax-requests-triggered-twi.html
Hope this help

Rails + Haml: Returning from a partial will somehow remove the form tag

This is lengthy, yes, I apologize. But I want to be clear because this issue is so odd.
I have a terms of service modal that comes up whenever a user has not accepted our terms of service (TOS). For the purposes here, javascript is turned off and what is rendered is strictly html/css. So the page, if thought of in 3 layers, is: bottom layer = page they came to see (i.e. an event page), middle layer: a semi-opaque overlay, top (primary/visible) layer: a modal with the terms of service agreement form in it. This form is simply an accept checkbox and submit button.
I noticed that the TOS was not working properly, but at seemingly random times. Then I noticed that it was broken but only on my event page (/event/foo) even though the same partial is responsible for showing the terms of service agreement no matter where they show up on the site. So for any other page, like /group/bar, the same TOS modal would show up and would work fine.
I then realized that the problem was that the form tag was missing from my HTML! Just gone.
So, taking a step back, the (HAML) code in question is simply:
%div#accept_tosC
%b Before form_for
- form_for #current_user do |form|
%b After form_for
%div#tosC= render :partial => 'general/terms'
%div.left
= render :partial => 'shared/user/tos_form_element'
%div.right
= image_submit_tag "/images/buttons/submit_100x20.png", :id => 'submit', :name => 'submit'
For our /events/foo page, the generated HTML look like this:
<div id="accept_tosC">
<b>before form_for</b>
<div style="margin: 0pt; padding: 0pt;"><input type="hidden" value="put" name="_method"><input type="hidden" value="44c2bf7a64fc59baa3fc7129167f0e2c3e96abb6" name="authenticity_token"></div>
<b>after form_for</b>
The obvious question here is if 'Before form_for' and 'After form_for' make it into the document, why doens't the form tag form_for creates?
For a different page, say /groups/foo, we get exactly what we would expect:
<div id="accept_tosC">
<b>before form_for</b>
<form method="post" id="edit_user_595" class="edit_user" action="/users/595"><div style="margin: 0pt; padding: 0pt;"><input type="hidden" value="put" name="_method"><input type="hidden" value="44c2bf7a64fc59baa3fc7129167f0e2c3e96abb6" name="authenticity_token"></div>
<b>after form_for</b>
I tracked it down to a single partial well inside the code for the "bottom" layer (the page they requested, not the TOS overlay). This partial in question may or may not be viewable to any given individual so we have to check if the user can view this page. The result of that is held in the variable can_view:
:ruby
#some processing to set page info and can_view
return unless can_view
%div#statsC
...and so on...
This is what my code looked like and the form tag did not render. By making the following change, the form element tag showed up as expected for all pages:
:ruby
#some processing to set page info and can_view
- if can_view
%div#statsC
...and so on...
So here is the question: Why would returning from a partial prevent a form element tag from becoming part of the document?
The short answer is that templates work in mysterious ways, and return is just generally not safe to use within them.
The long answer is that, behind the scenes, templates are compiled into Ruby methods that build up a string of HTML code and return that code. I'm guessing that by returning without returning the proper code, you're making something go haywire and discard the string that the form_for is concatenating to.

Resources