Ruby on Rails - render a collection within a collection? - ruby-on-rails

My user model has many projects, and each project has many invoices.
I am calling the following render
render :partial => "layouts/allInvoices", :collection => #projects, :as => :p
And inside the allInvoices, I wish to iterate over each project's invoices.
I can use
- p.invoices.each do |i|
But I'd rather use a collection. I'm not sure how to phrase it though
= render :partial => "layouts/invoiceItem", :collection => p.invoices, :as => :i
Doesn't work. Do I need to set up the nested iteration inside the controller?
Thanks

Do you mean something like...
= render "layouts/allInvoices", :p => #projects
Then
- # layouts/allInvoices
- p.invoices.each do |invoice|
= render "layouts/invoiceItem", :i => invoice
- # layouts/invoiceItem
= i.id # this gives id of Invoice

Related

Add a single attribute to a model's Json

I have the following code in one of my controllers;
render :json => Article.order("ID Desc").limit(3)
Which outputs an array of articles like:
[{"id":1, "content":"Blah"},{"id":2, "content":"Blah"}, {"id":3, "content":"Blah"}]
All I want to do is add a count attribute to each model. So it would be something like:
[{"id":1, "content":"Blah", "count":3},{"id":2, "content":"Blah", "count":1}, {"id":3, "content":"Blah", "count":6}]
Is there anyway to go about this in my controller without overriding the as_json method?
I saw a merge method called in another question, so I tried this:
render :json => Article.order("ID Desc").limit(3).merge(:count => 2)
with no luck.
It's better for you to handle this json yourself, but not to_json method( of Arrays or active_record)
articles = Article.order("ID Desc").limit(3)
render :json => articles.map { |article|
{
:id => article.id,
:content => article.content,
:count => 3 # or 2 or 1
}
}

Rails - increment variable in fields_for loop

I'm hoping this is a simple question - I have the following helper code:
module ApplicationHelper
def add_feature_fields(feature_types, object_form_builder, actions_visible)
feature_types.length.times {object_form_builder.object.features.build}
i = 0
fields = object_form_builder.fields_for :features do |features_builder|
render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => feature_types[i], :form_actions_visible => actions_visible}
i = i + 1
end
end
end
The code is working as expected, except for the line i = i + 1. For some reason, this seems to be breaking the loop, and nothing is rendered. Evidently, I am doing this wrong somehow - perhaps fields_for is not a normal loop?
How can I increment i by 1 each time the loop runs?
I'm not sure about the below code, but something around this should work and fix the issue. Give a try
object_form_builder.each.with_index do |builder,index|
object_form_builder.fields_for :features, builder do |feature_builder|
render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => feature_types[i], :form_actions_visible => actions_visible}
end
end
I was able to get this working by doing the following:
module ApplicationHelper
def add_feature_fields(feature_types, object_form_builder, actions_visible)
feature_types.length.times {object_form_builder.object.features.build}
i = -1
object_form_builder.fields_for :features do |features_builder|
i = i + 1
render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => feature_types[i], :form_actions_visible => actions_visible}
end
end
end
I believe what was happening was that when I did i = i + 1 after I called render, the return value was the iterator and not render (since the method returns the last value).

Render heterogenous collection with custom object name

In my Rails app I have an #events collection of objects inherited from Event::Base < AR::Base model.
If rendering it like render :partial => 'event', :collection => #events it's possible to give an option :as => :event to change the name of a local variable corresponding to the object inside of the partial. But what to do when the name of the partial is not constant? The aforementioned way (render #events, :as => :event) doesn't work.
PS. There's a solution at blog.obiefernandez.com but it uses the last part of the partial name and this just doesn't fit for me.
I haven't tried this myself to verify, but this might work:
class Event < ActiveRecord::Base
def to_partial_path
# assuming that you need different partials based on an attribute "variety"
"events/#{variety}"
end
end
You may also need to use the :partial key, eg: render :partial => #events, :as => :event instead of render #events, :as => :event
EDIT: This only works in Rails 3.2+ ... see Obie's writeup on the topic.

Ruby on rails: Render 2 partials or figure out the kind of class and object is

I want to display different types of objects in the same ajax called controller function. I want to render out when I send back an ajax call. The problem is I want the "title" attribute of one object and the "name" attribute of another object. I can't render 2 partials and can seem to figure out how to check the type of object an object is. How do I solve this problem?
Here is my current controller setup (NOT CORRECT)
#objects = Obj.find(:all,:conditions => ["name Like ?", "#{prefix}%"])
#moreObjects = ObjTwo.find(:all,:conditions => ["title Like ?","#{prefix}%"])
if #objects.empty?
render :text => "No Matches"
else
render :partial => 'one', :collection => #objects
end
if #moreObjects.empty?
render :text => "No Matches"
else
render :partial => 'two', :collection => #moreObjects
end
try something like
<%= obj.title if obj.respond_to?(:title) %>
Here's one option that doesn't involve checking its type - in your Obj and ObjTwo classes add a new method:
def fancy_pants
title
end
def fancy_pants
name
end
Then you can combine #objects and #moreObjects - you'll only need one if statement and one partial.
#search_domination = #objects + #moreObjects
if #search_domination.empty?
render :text => "No Matches"
else
render :partial => 'one', :collection => #search_domination
end
You could use Object.is_a? but that's not a very clean solution. You could also try mapping your data before presentation to help keep your views lightweight.

Rendering a collection of different classes in Rails

I have a collection that contains instances of several different classes, and I want to render the partial for each instance. I can do this using the following code:
<%= render #results %>
My question is: How can I render the different partials in a different base directory? The above code will look for app/views/stories/_story.html.erb, however, the partials for this action are all kept in a different directory - app/search/_story.html.erb. Is there any way of specifying this?
You could create a helper method like this:
def render_results(results)
result_templates = {"ClassA" => "search/story", "ClassB" => "something/else"}
results.each do |result|
if template = result_templates[result.class.name]
concat render(:partial => template, :object => result)
end
end
end
And then in the view call <% render_results(#results) %>
or you can use is_a?(Object)
if is_a?(classA)
render something_A
elsif is_a?(classB)
render something_B
end
I have a similar situation where I have multiple classes so I use a partial for each class like:
for result in #results
= render :partial => "result_#{result.class.to_s.downcase}", :locals => {:item => result}
end

Resources