I have 2 controllers: articles and comments. For each articles I need to display comments.
Both of them work fine on their own, but how can I get the comments/index inside the controller/show without messing everything up ?
In your show view you would do something like this (assuming you have a app/view/comments view folder and a _comment.html.erb inside):
render :partial => 'comments/comment', :collection => #articles.comments
You can make each comment render as a partial. So, from your comments index page, just render partial on all of the comments.
Then, from your articles show page, render the comments partial for the comments related to that article.
Take a look at using partials in Rails.
Related
Somewhat new to rails, longtime programmer. I've got a question about views, controllers and partials really - wondering if I have this setup well.
I've got a pages controller, and on the index page (really the pages index method) I've got a partial in layouts called featured (ie app/views/layouts/_featured.html.erb) -- I've also got a Featured class. I would like basically the index of the featured class to be drawn here. But of course it's not working. SO the question is:
In the page itself I've got the <%= render 'features/index' %> which I'm beginning to think is the wrong way to go..
Do I axe this partial method and just call <%= render 'features/index' %> and let everything progress natively or
What would be the proper way of routing the featured collection to the partial? Since the controller is actually Pages it seems like I'm fighting against the tide.
<%= render 'features/index' %>
Doing this is wrong given your description. This will try to render a partial from app/views/features/_index.html.erb which you haven't mentioned.
To render the partial at app/views/layouts/_featured.html.erb you would do (perhaps a bit more verbose that is necessary)
<%= render partial: "layouts/featured" %>
The best suggestion I can offer is to pass a collection to this partial
<%= render partial: "layouts/featured", locals: { features: #features } %>
Since it seems your intention is for this partial to appear as a piece of a layout I will assume you wish for this partial to appear on multiple pages. This means on multiple actions you will need to have assigned the set of Feature instances this #features instance variable. One way to do this is a before_action.
before_action :setup_features
# ...
private
def setup_features
#features = Feature.all
end
A good place to start learning more about filters is in the Rails Guide
The partial at "app/view/layouts/_featured.html.erb" can only be rendered with
render 'featured'
and not 'featured/index'
render 'featured/index' will render "app/views/layouts/featured/_index.html.erb
Since the pages controller is really rendering the main index page in it's def index, all I had to do was #features = Feature.all and the variable is available for the partial pulled into the index page.
I need to get used to how simple rails is coming from other languages / frameworks.
I have code like render #posts to render my posts collection in an index template which the PostsController renders.
Now I have an Admin::PostsController that also should render the collection but when my posts controller renders #posts it looks for the admin/posts/_post.html.erb partial. Do I now have to write the partial path explicity? Is this feature by design or a bug? It doesn't seem to make sense.
Yes, you need to supply the path explicitly. And yes, this is by design.
It actually makes sense because Rails is a MVC framework and if you create a controller under a different namespace one would expect separate views for that controller too. Think about convenience, if you wanted to quickly bootstrap an application with a few simple commands, an application where there's a public view of posts and an admin view where all of the admin goodies for editing are, you would EXPECT to have a different directory to store all that admin views.
render #posts is a shortcut for a longer method signature.
In case of PostsController, it is a short cut for render :partial => "post", :collection => #posts; the partial is _post.html.erb and it is expected to be in app/views/posts folder.
In case of Admin::PostsController, it is a short cut for render :partial => "admin#post/post", :collection => #posts; the partial is _post.html.erb, and it is expected to be in app/views/admin/posts folder.
If you want a different partial to be used, you should specify it explicitly.
See the Rendering Collections section of Rails Guides page on Layouts & Rendering for detailed explanation.
What I want to do is have 2 different controllers, client and test_client. The client controller is already built and I want to create a test_client controller that i can use to play around with the UI of the client and adjust it as needed. I am mainly trying to get around the validation i have built into the client and its dependence on an admin controller that loads the data.
so i want the test_client controller to load a sample data set and then render the client controller's index view so i can adjust the clients UI. That is all.
I tried this in the test_clients index method:
class TestClient
def index
render :template => 'client/index'
end
end
but i get an error because it cannot find the client partials as it is looking in the current controllers view for them...
So I have looked into this already and most people say that you should never make such a call but i think that this case is a reasonable usage...I just need to figure out how to get it to work.
You will need to adjust your view so that the path to the partial you need is in the form 'controller/partial'. In this case probably 'client/partial'. Then you can simply use render 'client/index' as before.
So say somewhere in your view you have this:
<%= render :partial => 'info' %>
You will want to change it to this:
<%= render :partial => 'client/info' %>
Convert your client controller views to partials, create empty views for all actions in test_client controller, render client partials for respective test_client views.
Example:
client view
index.html.erb to _index.html.erb
test_client view
index.html.erb
in this view, <%=render :partial => 'clients/index', :locals =>{ }%>
You could do this in a number of ways and everyone is different. One way you could do it, is by putting your finders into a presenter. Then turn some data in the index view into a partial or you can render the template with layout set to false.
Then in the client_test view you can render that index with the presenter associated with it.
I'm very new to RoR, moving from PHP. I have what I hope is a simple question.
Say I have a Model called Article, stored in the table articles.
If I want to display a list of articles on several pages in my site, I might have some simple markup such as;
<% Article.find_each do |article| %>
<div class="article_list_wrapper">
<h1><%= article.title %></h1>
<p><%= article.body %></p>
</div>
<% end %>
Where would I put this markup? I mean in what file; if I put it in a view, then I will have to copy it if I want a similar list in a different part of the site.
Putting it in the Model itself seems intuitive to me, the Article object should know how to render itself, right? But that seems totally against the CMV idea.
And what if I wanted to have several ways of rendering the same object? Like a list view, a full page view etc.
Many thanks, just trying to get into the correct habits from the start.
You would put that portion of HTML markup into what is known as a partial -- something that can be rendered as a small piece of a larger layout. You're right, you wouldn't want to store the format in the model, because you might wish to render that specific HTML for web browsers and render very similar XML or JSON for clients using an API and render some other very similar content into ASN.1 or YAML for further other clients. The "view" really should stay associated with the views.
With this specific example, you would probably go one further and provide the articles to render via a variable rather than letting the view find the articles itself:
Controller:
def flubber:
#articles = Article.find_each(some_criteria)
end
View:
<div class="article_list_wrapper">
<%= render :partial => "article_list", :collection => #articles %>
</div>
And then provide a View for the corresponding controller with the name _article_list:
<h1><%= article.title %></h1>
<p><%= article.body %></p>
If the <div class="..."> is going to be identical in every single use of this partial, you could either pass a :template to the partial, or put it into a view helper, or put the entire render with the :template argument in a view helper. (Either the first or last approach here is what I'd do -- the <div class="..."> doesn't seem so important to require its own file, but if it were more complicated, it might -- and then I wouldn't want to give the partial :layout argument every time I needed it.)
MVC (Model-View-Controller):
The Model has (primarily) the database piece and business logic.
The Controller controls application flow.
The View shows the info, e.g. the browser view.
So the markup you show which has a bunch of HTML goes in the view.
That is app/models/views/article.rb
The Controller is the part that gets the info.
You should actually have #article = Article.all in your controller and then just use #article.each instead of Article.find_each in your view.
If you have conditions you can apply them directly on the Controller find but the better approach is to learn about how you can use model finders with scopes and then use those scopes from the controller. Always try and push things up from View to Controller to View and follow the 'fat Model, thin Controller' approach when practical.
For reuse partials can help but as better understanding of rails will help more.
See railscasts by Ryan Bates. Incredible tutorials.
You might also like my own bookmarks for rails at my (rails) linker app.
You can use partials for this.
How do I render a view within another view... in rails... is it possible?
#hotdog_controller
def show
# by default renders template hotdog/show.html.erb
end
#hotdog/show.html.erb
<%= render :template => 'ketchup' -%>
Use view partials
See section 3.4 http://guides.rubyonrails.org/layouts_and_rendering.html
A complete view inside another a view? Normally the way you would handle something like this in rails would be with partials.
Create a set of shared partials, and then just render them in each of the views.
I do the same thing a few times, but I load the sub views in through AJAX. And that AJAX is instantiated within the partial.