Rails show views from a different controller - ruby-on-rails

In my Ruby on Rails application
I have a page Aboutus - This has a Controller and View. Has no model.
I have a Comments model (generated by the rails generate scaffold comment) - This has a Controller, view, model
On my Aboutus page, I want to show the "Comments" from the comments model, so I am thinking of using the Comments index action (to list comments) and new action (to create new comments) on my Aboutus page.
I am having trouble getting this right.
This is what I did:
Aboutus controller, I added
redirect_to :controller => "comments", :action => "index"
Aboutus views, I added
<%= render 'comments/index' %>
It doesnt work, gives me Undefined redirect_to and nil object #comments errors.
Could you advise me
1. A proper way to do this
2. Syntax
3. Any thing to do to config.rb ?

you want to create a partial that you use to render the comments in the comments index view, and also in your view for the aboutus page
# in about_us and in 'comments#index'
<%= render :partial 'path/to/_partial' %>
#in the about_us controller, or whatever controller dispatches the about us view
#comments = Comment.all.where(:my_conditions)
#partial view
<% #comments.each do |comment| %>
..
<% end %>

Related

rails link_to - pass hash of values to controller action

I have retrieved some records based on condition in a hash - #special_products. Now I want to pass the hash to a non-restful action(:special)/ of the same controller so that I can view the products.
I've tried this but how can link_to pass hash and how should the value be retrieved in action: special? which is in the same products_controller?Many thanks.
products_controller.rb
def show
#special_products = Product.by_company
end
show.html.erb
<%= link_to "Special Products", special_path(:anchor => "#{#special_products}") %>
If you're hitting the show action of the Products controller, you should be showing a product.
If you want to show a product in a special way, use the same show action, but render a different view for it.
def show
#product = Product.find(params[:id])
render #product.special? ? 'special_show' : 'show'
end
If you want to list some products in a different way (a filtered collection), you want to use an index. E.g. the products#index action.
def index
#products = Products.not_special
#special_products = Products.way_special
end
# app/views/products/index.html.erb
Special Products:
<%= #special_products.pluck(:name).to_sentence %>
Finally, note that the parameters you pass to link_to end up in the linked URL, which means that your example link_to is going to render something like #<Array []> in the href attribute.

Render view from another view : controller not called

I'm developing a litte blog like application and at the moment I'm facing a problem that I can't resolve.
I have 2 models at the moment :
1. Post
2. Comment
I can already manage my posts without difficulties but I have some problems with comments. I chose to make a relation has_many / belongs_to between my post and my comment models. I'd like to display all the comments related to a post when the user is on the post's page. My erb looks like this :
#some code
#...
#...
#render the comments
<%= render :template => "comments/index", :locals => {:post_id => #post.id} %>
My problem here is that the method index from my CommentsController is never called. I put some puts in the index method and they are never displayed in the console.
Should I use another tag to render the view ? Is there another way to do this ?
Thanks in advance for your help.
If the post view is the only page to show comments, you don't have to call comments/index to get comments, just show comments when rendering the post view, for example
In your post view
#some code
#...
# render comments
<% #post.comments.each do |c| %>
<%= c.content%>
# ...
<% end %>
Or put them in a partial with a post parameter if comments are used in many views
In app/views/partials/_comments.html.erb
# render comments
<% post.comments.each do |c| %>
<%= c.content%>
# ...
<% end %>
and render this partial where you want to show comments:
#some code
#...
# render comments
<%= render partial: "partials/comments", locals: { post: #post } %>
Using comments/index to get comments and showing them in a view is more likely the frondend tech such as Javascript/AJAX to load page parts dynamically. In this case, the comments/index is more likely an API call(render a JSON format instead of a html view).

Nested resource issue

I am struggling to pass an id successfully into my URL for the nested resource I have set up called Jobs.
The error I am getting when I try to pass the #job object into my link is as follows:
No route matches {:action=>"edit", :controller=>"jobs", :user_id=>1, :id=>nil}
Which clearly shows it can't find the id correctly and so is finding nil
At the moment I have my routes setup as so:
resources :users do
resources :jobs
end
and the link I have is <%= link_to "Edit", edit_user_job_path(#user.id,#job) %>
What is interesting is that if I pass the object #jobs with an 's' on the end it will load the page correctly but when I click on the link will try and add all of that users job id's.
In my controller for edit I have:
def edit
#user = current_user
#job = #user.jobs.find(params[:id])
end
Any help really would be much appreciated :)
UPDATE
Okay I was defining the object on the wrong page of my controller (under edit instead of index). The issue I am now having is Couldn't find Job without an ID
I updated my controller index definition to:
def index
#user = current_user
#jobs = #user.jobs.all
#job = #user.jobs.find(params[:id])
end
And have in my view (jobs#index)
<% #jobs.each do |f| %>
...
<%= link_to "Edit", edit_user_job_path(#user.id,job) %>
...
<% end %>
Any advice would be much appreciated if you know where I am going wrong :)
That error means that #job is nil.
The link is to the edit path, and the controller code you've provided is from the edit action in the controller. It seems unlikely that the edit page links to itself.
Look at the code that's actually rendering that page (it will appear in your stack trace) and you'll find that #job is not set. I suspect that you are on the index page and have something like:
<% #jobs.each do |job| %>
...
<%= link_to "Edit", edit_user_job_path(#user.id,#job) %>
...
<% end %>
If that is the case, then the link should be to job, not #job, i.e.
<%= link_to "Edit", edit_user_job_path(#user.id,job) %>
(expanding on iHiD's comment with his own post)
Using the restful resources means that you are going with the rails defaults, which consequently means that the index page gives you a list of all Jobs, and by default no single special job. If you run rake routes from the command line, you get all the routes, with parameters that are set from the URI. It should give you something like this:
user_jobs GET /users/:user_id/jobs(.:format) jobs#index
As you can see, there is no :id (params[:id]) for the index action.

form_tag action not working in rails

I have this form in my application.html.erb.
<%= form_tag(:action=>"index", :controller=>"posts") %>
<p>
// code here
</p>
I dont understand why is this getting directed to posts->create instead of posts->index?
Thanks.
Basically, Rails observes and obeys "RESTful" web service architecture. With REST and Rails, there are seven different ways to interact with a server regarding a resource. With your current code, specifying the form's action as index doesn't make sense: Rails' form helpers can either POST, PUT or DELETE.
If you wanted to create a post, then redirect to the index, you can do so in the applicable controller action:
class PostsController < ApplicationController
...
def create
#post = Post.new
respond_to do |format|
if #post.save
format.html { redirect_to(:action => 'index') }
end
end
While your form would look like:
<% form_for #post do |f| %>
# put whatever fields necessary to create the post here
<% end %>
You seem to be a little mixed up with respect to the uses for each action. Here's a quick summary of typical RESTful usage:
Index -> view a list of items
New/Edit -> form where items are added or edited
Create/update -> controller action where items are created/updated
The reason your routes file is not taking you to index is because index is not an action where posts are typically created or updated. The best way is to go RESTful. Unless you have a very unusual situation, the best way to set your system up is probably a little like this:
# routes.rb
resources :posts
# application.html.erb (or better: posts/_form.html.erb).
<% form_for #post do |f| %>
<% end %>
# posts controller, whichever action you want to use
def new
#post = Post.new
end
By putting the form in a partial called form you can access it in new, edit, or wherever else you need to manipulate a post in your system.

What to render on error in a Rails controller

In my rails application, I've got a partial view with an entry form on it. The form gets included on multiple pages across my app. The form in the partial posts to a RidesController to save with a create method like this:
RidesController.rb
def create
#ride = current_user.rides.build(params[:ride])
if #ride.save
flash[:success] = "Ride created!"
redirect_to root_path
else
#rides = current_user.rides.paginate(:page => params[:page])
render 'pages/home' # <---- WHAT GOES HERE?
end
end
I've commented the line where my question is. When we have an error, I need to present the same view that the user is presently on. But because this controller is being invoked from a partial instead of a full view, I don't know how to tell what context it's coming from.
Right now if there's an error on /rides/new, the user ends up redirected to the homepage which also has the form.
One way you could do this is pass the template path in with the form.
Add this to each main view that includes the form partial (e.g. pages/home, rides/new, etc):
<% #current_page_template = __FILE__ %>
In your form partial:
<%= form_for ... do |f| %>
<%= hidden_field_tag 'current_page_template',
#current_page_template.sub(File.join(Rails.root, 'app', 'views'), '') %>
In your controller:
def create
...
if #ride.save
...
else
...
render params[:current_page_template]
end
end

Resources