Rails 4.2
I have a collection displaying from a partial - is there a way to add a fragment of code in after a certain number in the collection?
So I have a 10 blog posts being shown in a list, each post's formatting from the partial list. I'd like to insert my AdSense code after every 3 posts
<%= render partial: "list", collection: #posts %>
Is there a way to do that automatically, or would I have to do something like assign a numbered id to each post and have "if (id/3) % 1 == 0", and conditionally display it?
Well inside the partial _list.html.erb, you can do check the counter variable provided by Rails list_iteration. So your check will be inside the _list.html.erb partial as:
render 'ad' if list_iteration.index % 3 == 0
You can also use list_counter helper.
Read this Rendering a collection of partials
<%= render partial: "ad", collection: #advertisements %>
This will render “advertiser/_ad.html.erb” and pass the local variable ad to the template for display. An iteration object will automatically be made available to the template with a name of the form partial_name_iteration. The iteration object has knowledge about which index the current object has in the collection and the total size of the collection. The iteration object also has two convenience methods, first? and last?. In the case of the example above, the template would be fed ad_iteration. For backwards compatibility the partial_name_counter is still present and is mapped to the iteration's index method.
Something like:
<% #posts.each_slice(3) do |posts| %>
<%= render partial: "list", collection: posts %>
<%= render partial: 'ad_sense' %>
<% end %>
Might work
each_slice docs for further reading
You could do something with the loop index like
<% #posts.each_with_index do |post, index| %>
<%= render partial: 'list', locals:{post: post} %>
<% if index % 3 == 2 %>
#adsense code here
<% end %>
<%end %>
Related
the following view
<% #packageoffers.each do |packageoffer| %>
<% if #packageoffers_mss.include?(packageoffer) %>
<% elsif #availables.include?(packageoffer) %>
<%= render 'packageoffer', collection: #packageoffers %>
is returning an NameError undefined local variable or method 'packageoffer' when trying to process the partial _packageoffer.html.erb upon a line like the second taht follows:
<% item_sale_price = #item_price.sale_price * params[:quantity].to_i %>
<% markup_price = ((item_sale_price + (packageoffer.price * #r * #q)) * (1 + (#user.markup.to_d / 100) ) ) %>
note: #item_price is itself an item of an array section and had to be declared as an instance variable to pass it along <% #item_price = #allotments.select{ |a| a.section_id == section.id }.first
Thus, notwithstanding following the rails documentation guidelines,
I cannot process the array's item. Where lies the mistake?
You're using collection rendering incorrectly.
Your line...
<%= render 'packageoffer', collection: #packageoffers %>
Renders a single partial, and passes a local variable called collection with a value of #packageoffers.
The line you've written is a shorthand for:
<%= render partial: 'packageoffer', locals: { collection: #packageoffers } %>
If you want to render the entire collection and provide a partial name, you cannot use the render shorthand, you must use the explicit version of render partial:...:
<%= render partial: 'packageoffer', collection: #packageoffers %>
That said, it seems like your intent is to iterate over the collection, and conditionally render some items from it. In this case, you should not be using collection rendering at all, you should just use <%= render packageoffer %> to allow Rails to render the singular _packageoffer partial for each record.
Is the model called Packageoffer or PackageOffer? I think your problem is that Rails tries to infer the name of the variable from the model name. Can you try if there's a packge_offer?
If the model is PackageOffer, then you should use _package_offer as the partial name, package_offer as the variable name and also #package_offers. To be consistent with Rails conventions.
EDIT: if that's the problem, you can use your code with an as: :packageoffer option on the render to tell rails the name to use
Simple example:
index.html.erb:
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
I can refactor this and move content to the _post.html.erb partial:
index.html.erb:
<%= render #posts %>
_post.html.erb:
<%= post.title %>
So how Rails passes attributes of every post without creating a block?
My posts_controller index action has only #posts = Post.all defined.
I thought that maybe by the name of the partial (post), but looks like its another Rails convention (plural and singular naming). Is it?
Many thanks for sharing!
Rails determines the name of the partial to use by looking at the model name in the collection. The full syntax to render a collection is as follows:
<%= render partial: "post", collection: #posts %>
However there is a shorthand for this:
<%= render #posts %>
According to docs:
When a partial is called with a pluralized collection, then the
individual instances of the partial have access to the member of the
collection being rendered via a variable named after the partial. In
this case, the partial is _post, and within the _post partial, you can
refer to post to get the instance that is being rendered.
You may find detailed explanation in rails guides
I am new to caching and I'm not sure what my best course of action is.
I want to cache a part of my view that relies on a complex query. The query looks something like:
#sessions_next_week = group_by_wday(LittleClassSession.location_only([1,2]).age_range_only(age_from, age_to).supports_dropins_only(support).approved_users_only.next_week)
Above you'll see a number of scopes and methods called. The view renders an instance variable named #sessions_next_week like so:
<% #sessions_next_week.each do |wday, lcs| %>
<h3><%= wday %></h3>
<%= render partial: 'table_head' %>
<% lcs.each do |s| %>
<%= render partial: 'table_row', :locals => {:s => s, :show_day => true} %>
<% end %>
<%= render partial: 'table_foot' %>
<% end %>
As you can see, #sessions_next_week is iterated through, and its children are iterated through. Given this, and given the nature of the query results in the instance variable, I'm not sure where to implement the caching. In the model? In the view?
So my questions are:
Do I need model caching or can I do this in the view?
What's the correct implementation?
The solution is to simply add two character:
#sessions_next_week ||= group_by_wday(LittleClassSession.location_only([1,2]).age_range_only(age_from, age_to).supports_dropins_only(support).approved_users_only.next_week)
This is called memoization, and you can look it up. Here's one source: http://www.justinweiss.com/articles/4-simple-memoization-patterns-in-ruby-and-one-gem/
I'm trying to insert some images in between my topics (one in between every 3 topics for the first 3 groups of topics -- ie. 3 images in total), but I'm confused as to where since my forums/show.html.erb only has <%= render #topics %> and not some sort of each loop that I could manipulate.
If you are not looking for a very fancy ruby way to do it, just do it the dirty way:
<% #topics.each_with_index do |topic, index| %>
<% if index != 0 && index%3==0 %>
<%= render #ad %>
<% end %>
<%= render topic %>
<% end %>
or if your partial takes the entire array do that in your partial logic. However if you want a fancy way, this solution will help you: New row every 3 items
I have a resource called Exercises in my application. I currently have a partial called _exercise.html.erb that I use to render them. I have an outlying case where I'd like to render them in a much different way. Can I make another partial for exercises that has this other format and still be able to use <%= render #exercises %>?
If not what is the best approach? Should I out a variable in the controller that tells the partial which layout to use, this would have both layout in one file and one if to decide. Or is there some better way?
If you'd like to use business logic to determine when to show what partial for your #exercises collection you should use the to_partial_path method in the Exercise model to define that. See #4 in this post: http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/
Or, if this is more of a view-related decision (i.e. one view will always use the regular _exercises.html.erb and another view would always use e.g. _alternate_exercises.html.erb) then you can specify as such:
<%= render partial: 'alternate_exercises', collection: #exercises, as: :exercise %>
This will render the _alternate_exercises.html.erb partial once for each item in #execrises passing the item in to the partial via a local_assign called exercise.
In this case, I suppose you have two options:
1) Put the conditional code inside of _exercises.html.erb
eg.
<% if #exercise.meets_some_condition %>
you see this stuff
<% else %>
you see other stuff
<% end %>
This way, you can still make use of <%= render #exercises %>
2) Otherwise, your other option is to have separate partials and render them outside.
eg.
<% #exercises.each do |exercise| %>
<% if exercise.meets_some_condition %>
<%= render "exercises/some_condition_exercise" %>
<% else %>
<%= render "exercises/exercise" %>
<% end %>
<% end %>
This is the best approach for rendering partial. You can wrap that partial with if else statement in your code. Here is my example
rendering with form called _victim.html.erb
<%= render :partial => "victim", :locals => {:f => f }%>
rendering without form
<%= render :partial => "victim"%>