Strange routing in rails render partials - ruby-on-rails

I'm new to rails and thought I had finally figured out some of this routing stuff, but have been going in circles with this bit all day.
I was following a tutorial about building a twitter like service, and I've got the basics working from the tutorial, but with Mongo instead of mySql.
I've got 3 types of pages.
The home page which is showing all the posts ordered by date
The user page which is showing the posts from a specific user
The posts page which is showing posts from a users friends.
So for each page, I've done the following
1) created a method in the corresponding controller to get the correct posts
2) created a _posts.html.erb page with the display parameters, which are slightly different on each page
3) referenced the partial in the index.html.erb page for each view.
The controller entries look like this
def index
#posts = Post.all(:order => 'created_at DESC')
end
or
def posts
#posts = Post.all(:conditions => {'user_id' => params[:id]}, :order => 'created_at DESC')
end
and the partials are
<%= render :partial => #posts %>
In each view is a _posts.html.erb file, and each is slightly different
home/_posts.html.erb looks like this
<%= div_for post do %>
Posted <%= time_ago_in_words(post.created_at) %> ago
Posted By <%= post.user_id %>
<%= post.text %>
<% end %>
while posts/_post.html.erb looks like this
<%= div_for post do %>
Posted By <%= post.user_id %>
<%= post.text %>
<% if post.created_at > 52.hours.since %>
<%= distance_of_time_in_words_to_now(post.created_at) %>
<% else %>
<%= post.created_at.strftime("%c") %>
<% end %>
<% end %>
Now the strange part is that on all the pages index.html.erb, users/show.html.erb, posts/index.html.erb, the partial that is being displayed is the posts/_post.html.erb. The others are being completely ignored.
my understanding was that render :partial would take the #posts and render _posts.html.erb from the current view. But this isn't happening, as only the posts/_post.html.erb is being rendered from all views.
I've looked in the routes.rb file, but don't have anything in there that would cause this problem.
Can anybody tell me why I am not displaying the proper partials?
-----------Edited --------------------------------
The directory structure for views is as follows
views
- home
-_post.html.erb
-index.htlm.erb
- layouts
- posts
-_post.html.erb
-index.html.erb
-posts.html.erb
- sessions
- users
-_post.html.erb
-new.html.erb
-show.html.erb
I hope that helps.

"post", :collection => #posts%>
maybe rails automatically defines path to the partial when you pass only collection

You're passing the collection as the argument that rails is expecting to be the name of the partial. Your call to render should look like this
<%= render partial: "post", collection: #posts %>
This will render app/views/posts/_post.html.erb, passing the local variable post to the partial.
Additionally, (is sometimes handy) there's an iteration object that is made available to this view, partial_name_iteration, that has information about the total size of the #posts collection, and the index of the current object.

Related

How Rails render finds variable

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

How to render the index view, from inside a view in ruby-on-rails

I'm trying to render a the index view inside my ruby-on-rails application. How do a I render the index view, from inside a view passing an array of things to display? Using the link_to.
I do not want to re-route to the controller, I just want to link_to a view passing it the variables it needs, how can I do this?
EDIT:
I am trying to create a page type functionality in the index of my article model. So I have around 400 articles for example, and when the index action in the article controller is called, it of course renders the index view which is calling a partial for each article in the '#articles array' passed on by article controller's index action.
So in the view, I'm trying to do something like:
<% count = 0 %>
<% #articles.each do |article| %>
<% if count <10 %>
<%= render partial: 'index_articles', locals: {article: article} %>
<% count = count + 1 %>
<% end %>
<% end %>
<% #articles = #articles.drop(10) %>
<% if #articles.any? %>
<%= link_to "Next", 'articles', locals: {#articles => #articles} %>
<% end %>
Thank you in advanced for all of your help.
You'll need to use the render command, probably with a partial:
<%= render "controller/index", collection: ["your", "array"], as: :object_name %>
You will have to call a controller action to generate this. You cannot simply load it on your screen, unless it was preloaded inside your javascript for something:
#View
<%= link_to "Index", controllers_path(ids: ["1","2"]), remote: true %>
#app/controllers/your_controller.rb
class YourController < ApplicationController
def index
#posts = request.xhr? Post.find(params[:ids]) : Post.all
respond_to do |format|
format.js #-> app/views/controller/index.js.erb
format.html
end
end
end
#app/views/controller/index.js.erb
$(".element").html("<%=j render 'index' %>");
There are several issues with this approach...
Flow
First of all, your flow of your app should be as structured as possible.
In short, if you're calling the index view inside another action, it's not the index view any more.
What you should look at is how to use a partial in your app:
#app/controller/views/_partial.html.erb
<%= post.title %>
This way, you can adapt your index view and your other page to use the partial in their respective action layouts:
#app/controller/views/index.html.erb
<%= render "partial", collection: #posts, as: :post %>
This will allow you to "reuse" code much in the way you want. This will be much more appropriate than trying to invoke other action/views.
-
Resources
Secondly, you'll want to look at how your app functions.
Your index view is meant to show all the items for a particular object. Whilst you're free to change this as you want, the fact remains that you have to keep some structure.
You should read up on the routes for your actions, and how they're meant to work in your application. This will give you some perspective on the resourceful nature of Rails routes, and how you'll have to call specific routes with specific actions.
Your problem is probably that the file needs to be named _index.html.erb. You can have another file named index.html.erb which just renders _index.html.erb.
If you need a full guide on using AJAX, look up the railscast. If you're not using AJAX and you just want to render it, then you don't use link_to. You just do <%= render :index %>.

How to limit which objects get rendered in my index view in ruby on rails?

I'm trying to limit the posts that will render in my view based on if they match the current_user's interest_list (set of tags).
So as a preface, it's a simple blog type website on rails. I have a user model, and a post model, each of them with controllers. I have a user that has an interest_list, and posts which have a tag_list.
In my posts index.html.erb file I have
<p id="notice"><%= notice %></p>
<h1>Relevant Posts</h1>
<% #posts.each do |post| %>
<%= render partial: 'index_post', locals: {post: post} %>
<% end %>
I would like, the logic to be like this
#posts = #posts.tagged_with(#current.user.interest_list, :match_all => true)
Then render the form for each post that has a tag in common with the current users interest list.
Now, these tags are dynamic, a user has the ability to change their interest and same with a post, it can be edited.
Please help me, I've never used acts_as_tagable before, and so I'm trying to learn.
Thank you very much for your help in advanced.

Render in rails a view

Sorry for a simple question but i am a bit confused trying to follow ruby on rails tutorial book
I am at the chapter 10 and confused, yes i trick a bit my version for learning purpose
So I have a controller called customer
customers_controller.rb
def show
#customer = Customer.find(params[:id])
#posts = #customer.posts
end
I then have the following folder
_post.html.erb
Welcome to a post
Which his called from the show customer file has follow
/view/customer/show.html.erb
<% provide(:title, #customer.name) %>
<aside class="customer_show_nav">
<h1><%= #customer.name %></h1>
<%= #customer.email %>
</aside>
<div class="events">
<%= render #posts %>
</div>
But when loading nothing his appearing not even Welcome to a post. What i am doing wrong?
Thanks in advance. I am following the tutorial http://ruby.railstutorial.org/chapters/user-microposts#top 10.22
if _post.html.erb is in view/customers
you do this in view/customers/show.html.erb
<%= render 'controller_where_post_lives/post' %> which will look for customers/_post.html.erb
Sometimes, you also need = in <%= %> with rails 3
Also, show is used to show one item, and index is used to show all items.
So to render you will do
<%= render :partial => "post", :collection => #posts %>
Edit:
When you call render you give it the view, no objects here. Unless like above passing a collection.
http://guides.rubyonrails.org/layouts_and_rendering.html
Also if you just want to render text you can do render :text => "OK"
Look for partials explanation.

ruby-on-rails: rendering partials on each item in a list

I have the following in a view (.html.erb) :
<% #posts = GetAllPostsFunctions %> (removed for berivity)
<% #posts.each do |post| %>
<%= post.title %>
<%= render :partial => "posts/post_show" %>
<% end %>
the posts_show partial has the following:
....
<td><%=h #post.title %> </td>
But I get the following error
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.title
Any ideas?
You can also simply things by using the :collection for render :partial. Which pass each item in the value for :collection to a local variable sharing the name of your partial.
<% #posts = GetAllPostsFunctions %> (removed for berivity)
<%= render :partial => "posts/post_show", :collection => #posts %>
In this case, Rails will render post_show for each item in #posts with the local variable post_show set to the current item. It also provides handy counter methods.
Successfully using this approach would require renaming the app/views/posts/_post_show.html.erb partial to app/views/posts/_post.html.erb to or changing every occurance of post in your partial to post_show. If you renamed the partial to the conventional _post.html.erb which will then allow you to simply do:
<%= render :partial => #posts %>
Which will render the partial for every single post in the #posts variable.
Since the post variable in the each loop is a locale variable you have to make it available to the partial:
<%= render :partial => "posts/post_show", :locals => {:post => post} %>
You can then access the title through the local variable post:
<td><%=h post.title %> </td>
You could also simplify the whole thing by rendering the posts as collection. Take a look at the Rails documentation for more information:
http://api.rubyonrails.org/classes/ActionController/Base.html#M000658
It doesn't look like you're setting the #post of the partial, so when it goes to evaluate the partial it gets a null reference.
Alternately, ensure that your post fetching functions are actually returning something
I'm not positive, but I think in the partial you have to do post.title not #post.title
Sorry if I misunderstood you, I'm new to rails.

Resources