I'm trying to render a view in a different controllers view but I'm getting:
undefined method `each' for nil:NilClass
I'm rendering the view in 'views/users/show' as:
<%= render :template => 'groups/index' %>
The view itself is under 'views/groups/index':
<% #groups.each do |group| %>
<li>
<%= group.name %>
<%= group.description %>
</li>
<% end %>
And my groups controller for index looks like this:
def index
#groups = Group.all
end
I think it's a problem with how i'm rendering the view since if I make an instance variable in my index controller and call it in the view it won't appear. There are entries in the Group table in my database.
Any help would be appreciated.
Thanks in advance.
I think it should be enough to replace the template: with a partial: parameter.
Try this:
<%= render partial: 'groups/index' %>
You will have to rename/copy groups/index.html.erb with groups/_index.html.erb
This only works for rendering a view, but will not implement the functionality of your GroupsController.
Edit
You will have to redefine the groups inside your UsersController
# UsersController
def index
#groups = Group.all
end
Depending on how many times you will need to present all these groups to your user, this can become hard to maintain. If you use it frequently, consider adding
# i.e. ApplicationController
def groups
Group.all
end
inside your ApplicationController (or some module you want to include in different controllers). Then you could call
# UsersController
def index
#groups = groups
end
and still <%= render partial: 'groups/index' %>
Change:
<%= render :template => 'groups/index' %>
To:
<%= render 'groups/index' %>
and make sure the file name of your index action is _index.html.erb and not index.html.erb.
EDIT
When you render a view, you are only rendering the template, this does invoke a request on your index action. You must define #groups in your initial view's action.
Related
Is it possible to generate a dynamic method using the strong parameter I get from my view?
In my view I will generate a different path according to the card the user clicks on. Then, in the controller I want to generate a dynamic method using the parameter obtained from the view, but I'm not sure how to write that. Thanks!
show.html.erb
<div class="branch-names">
<% #branches.each do |branch| %>
<div>
<%= image_tag "cat.jpeg" %>
<%= link_to "#{branch.name} Posts", send("#{branch.branch}_posts_path") %>
</div>
<% end %>
</div>
posts_controller.rb
def self.define_category(name)
define_method(name) do |params[:id]|
#posts = Post.where(category_id = params[:id])
end
end
define_category("#{params[:id]}")
You shouldn't define method based on user input. It may cause security issue, and for sure it causes performance penalty related to method cache invalidation.
Instead you can create one method that have an alternarive on params[:id] and then decide what to show to the user:
class MyController
def branches
case params[:id]
when('cat')
do_cat_stuff
when('dog')
do_dog_stuff
end
end
end
For having routes like /posts/cats you do not have to add dynamic methods. Think of branch like of an id of category:
routes:
resources :post_categories, only:[:index, :show]
view:
...
<%= link_to "#{branch.name} Posts", post_category_path(branch.branch) %>
PostCategories controller:
def show
#posts = Post.where(category_id: params[:id])
end
Also you can make posts a nested resource under categories and use a more RESTful structure with /post_categories/some_branch/posts mapping to posts#index
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 %>.
I've got a module that lists events (event_box) and I want to define it as part of my application.html.erb:
<div id="left_sidebar">
<%= render 'shared/user_box' %>
<%= render 'shared/event_box' %>
<%= render 'shared/server_info_box' %>
</div>
However, the event_box uses #events, which so far needs to be passed to it:
def home
#events = Event.all
end
If it's going to be in the application layout, how do I pass #events to it without defining #events in every view in my application?
Define a method in ApplicationController which fetches all the events.
Use this method as a before_filter in ApplicationController. Filters called in ApplicationController will apply to all the controllers inheriting from it.
application_controller.rb:
before_filter :fetch_events
def fetch_events
#events = Event.all
# #events = Event.where({}) can be used to lazy load the events
end
Since this is going to be executed before every action, consider using Fragment caching for that particular portion of the view.
You can try below code also in shared/event_box partial. It will work.
<% #events = Event.all %>
<% #events.each do |event| %>
<p><%= event.column_name %></p>
<% end %>
Is there a way to display the new.html.erb form_for div in index.html.erb?
I'd like to be able to add a new entry without leaving the homepage. Maybe a partial?
You can't render part of the template, only whole templete.
If you have a part that same for several templates, than put it to the partial and render partial as part of the template.
This is very simple example:
_partial.rb:
<%= form_for ... %>
...
<% end %>
new.html.erb:
render 'partial'
index.html.erb:
render 'partial'
More about partials and rendering you can read in rails guides.
I got it to work by creating a #article = Article.create in the index module of the controller. Works like a charm. No partials needed.
This method works for me.
In the links_controller.rb I added the #link to the index controller
def index
#links = Link.all
#link = Link.new
end
In the index.html.erb I added only the partial
<%= render 'form' %>
Ended up with the screen of this:
Yes partial would be better in that case. You can have a partial for that "_form.html.erb".
In that partial just put the form_for content. Let you have a Blog model and in the index you are showing the blog lists.
def index
#blog = Blog.new
#your rest code goes here
end
index.html.erb
<YOUR HTML CONTENT>
<%= render "/blogs/form" %>
_form.html.erb
<%= form_for(#blog) do |f| %>
Your code for the form
<%= end %>
If you want to keep the new action will show only the form, then you need to change the action and new.html.erb
def new
#blog = Blog.new
end
In new.html.erb
<%= render '/blogs/form' %>
I have tried to set up a separate section of my app using a subdirectory called controlpanel to manage various parts of the site.
I've set up the namespace in my routes.rb
map.namespace :controlpanel do |submap|
submap.resources :pages
# other controllers
end
And placed the controller and views into the relevant subdirectories.
Controlpanel::PagesController
def new
#page = Page.new
end
def create
if #page = Page.create_with_author(current_user, params[:page])
flash[:notice] = 'Page was successfully created.'
redirect_to ([:controlpanel, #page])
else
render :action => 'new'
end
end
Using this mixed in class method
def create_with_author(author, params)
created = new(params)
created.author = author
if created.save
created
end
end
And the view (controlpanel/pages/new.html.erb renders a partial called _form
<%= render :partial => 'form' %>
Which is as follows:
<% semantic_form_for([:controlpanel, #page]) do |form| %>
<% form.inputs do %>
<%= form.input :title %>
<%= form.input :body %>
<% end %>
<%= form.buttons %>
<% end %>
If I fill in the form correctly, it works as expected, redirecting me to the new page, however, if I leave fields blank, violating the validation constraints, I get the following error:
RuntimeError in Controlpanel/pages#create
Showing app/views/controlpanel/pages/_form.html.erb where line #1 raised:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Can anyone see what is going wrong?
I'm using the formtastic plugin to create the form, but it still happens if I use a regular form.
Any advice greatly appreciated.
Thanks.
Given that the create action is called and new is rendered, Page.create must evaluate to nil.
You probably want to pass params[:page] to create.