I am trying to render a templated under
public/index.html.erb
def public_index
#post = Post.all
render 'public/index'
end
Missing template public/index
I don't see anything wrong with it. Is public a reserved word or something?
Try using:
render :file => "#{RAILS_ROOT}/public/index.html.erb"
Try
render :template => 'public/index'
If this will not help then try following ways
render :edit
render action: :edit
render "edit"
render "edit.html.erb"
render action: "edit"
render action: "edit.html.erb"
render "books/edit"
render "books/edit.html.erb"
render template: "books/edit"
render template: "books/edit.html.erb"
render "/path/to/rails/app/views/books/edit"
render "/path/to/rails/app/views/books/edit.html.erb"
render file: "/path/to/rails/app/views/books/edit"
render file: "/path/to/rails/app/views/books/edit.html.erb"
Check http://guides.rubyonrails.org/layouts_and_rendering.html
You can do like this:
Add this, into your routes.rb file.
match '/index', :to => redirect('/index.html')
Update
In Rails 4, it should use "get", not "match":
get '/index', :to => redirect('/index.html')
Related
I'm new to Rails and was trying to use Action Cable to update clients when a new record is saved in database.
To do so, I have this posts_controller.rb:
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
picture = params[:post][:picture]
respond_to do |format|
if #post.save
#post.picture.attach(picture) if picture.present?
PostsChannel.broadcast_to #post, html: render(partial: 'post', locals: { post: #post }) #<--- render
format.html { redirect_to posts_url, notice: 'Post was successfully created.' } #<--- redirect
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
And _post.html.erb:
<div class="cd-timeline__block js-cd-block">
<div class="cd-timeline__img cd-timeline__img--picture js-cd-img">
<p>😃</p>
</div>
<div class="cd-timeline__content js-cd-content">
<%= image_tag post.picture.variant(resize: '400x400') %>
<p><%= post.text %></p>
<span class="cd-timeline__date"><%= post.created_at.strftime('%d/%m/%Y %T') %></span>
</div>
</div>
This ends up with the error AbstractController::DoubleRenderError because of the partial render and the redirect. The thing is that I have no idea how to do this otherwise. I don't want to generate the HTML in JS file as saw is some code examples(I would have a code duplication for my post template). I've been looking for other examples but nothing really helped me out.
The same problem was discussed here and here but I don't see how to use flash to get what I want.
Any advice?
Can you try moving the render to an after_action callback? you'll have access to #post so you can call #post.valid? to know if you have to broadcast that. I'm not sure if that works, but you can give it a try.
I wouldn't broadcast the render of a partial, though. Maybe it would be faster to broadcast the #post as json and update the view with javascript clientside.
EDIT: try with render_to_string https://apidock.com/rails/AbstractController/Rendering/render_to_string
It renders views and partials but it doesn't set the requests' response body. Just tried locally and it works with two renders.
Ok, so I got it working! :)
There is a rails function that does exactly what I want: render_to_string which doesn't send http response.
I had some issues with websockets so I installed Redis + changed the way I was broadcasting and now everything is working fine!
For the records, here is all of it:
# config/routes.rb
Rails.application.routes.draw do
resources :posts
mount ActionCable.server => '/cable'
end
-
# config/cable.yml
development:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
-
# app/channels/posts_channel.rb
class PostsChannel < ApplicationCable::Channel
def subscribed
stream_for 'post'
end
end
-
// app/assets/javascripts/channels/posts.js
App.cable.subscriptions.create('PostsChannel', {
received: function({ html }) {
$("#timeline-container").prepend(html);
}
});
-
<!-- app/views/posts/_post.html.erb -->
<div class="cd-timeline__block js-cd-block">
<div class="cd-timeline__img cd-timeline__img--picture js-cd-img">
<p>😃</p>
</div>
<div class="cd-timeline__content js-cd-content">
<%= image_tag post.picture.variant(resize: '400x400') %>
<p><%= post.text %></p>
<span class="cd-timeline__date"><%= post.created_at.strftime('%d/%m/%Y %T') %></span>
</div>
</div>
-
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
picture = params[:post][:picture]
respond_to do |format|
if #post.save
#post.picture.attach(picture) if picture.present?
ActionCable.server.broadcast 'posts:post', html: render_to_string(partial: 'post', locals: { post: #post })
format.html { redirect_to posts_url, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
Rails 4.1, reaching the driver knowing edit and use _form.html.erb again. I tried to do the following:
Â
<% = Form_for #user, :controller => "admin/users" do | f |%>
<button type='submit'>Guardar</button>
<% end %>
#Controller
===============
def new
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to admin_users_url, notice: "User ##user.name} was successfully created." }
format.json { render :controller => 'admin/users', action: 'show', status: :created, location: #user }
else
format.html { render :controller => 'admin/users', action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
But it does not work I can not get to the route that is my controller ("admin / users"), if anyone can help me
I assume that you have your admin routes defined in your config/routes.rb like this:
# in config/routes.rb
namespace :admin do
resources :users
end
See: Rails Guide about namespaces in routes
Then this should work for an admin namespaced form in your view:
<%= form_for [:admin, #user] do |f| %>
...
<% end %>
See: Rails Guide about namespaces and form helper
Your controller code looks okay, but please ensure that the controller is namespaced too:
# in app/controllers/admin/users_controller.rb
module Admin
class UsersController
# ...
end
end
I always get the error
No route matches {:action=>"index", :blog_id=>nil, :controller=>"comments"} missing required keys: [:blog_id]
when I'm rendering the show action from a different controller:
def create
#blog = Blog.find params[:blog_id]
#comment = #blog.comments.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to #comment, notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render template: 'blogs/show' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
The error happens after validating. The specific line of code responsible for this is format.html { render template: 'blogs/show' }
Any ideas?
Edit
Here's my routes.rb
Rails.application.routes.draw do resources :comments
devise_for :users
resources :blogs do
resources :comments
member do
get '/update/(:status)', to: 'blogs#update_blog_status'
put :rename
end
collection do
put :destroy_multiple
end
root 'blogs#index'
end
As you can see from the error, why is rails matching me with :action => 'index', controller: 'comments' when I clearly want to render blogs/show?
Edit 2
If you're wondering what I'm doing, I wanted to comment on a blog. So the comment form is in blogs/1 and I wanted to test if validation works. When I didn't enter anything in my comment text area, I'm getting the error.
Edit 3 Posting my blogs/show.html.haml
Forgive me but my show.html is in haml format. If you're not familiar with haml, convert it to erb here http://www.haml-converter.com/
blogs/show.html.haml
%p#notice= notice
%h1
%strong= #blog.title
%hr
%p
= #blog.content
%hr
%p
%strong Comments:
= form_for #comment, url: blog_comments_path(blog_id: params[:id]) do |f|
= f.text_area :message
%br
= f.submit "Post Comment"
%br
%p
%strong All Comments:
- #all_comments.each do |comment|
.panel.panel-default
.panel-body
= comment.message
= link_to 'Edit', edit_blog_path(#blog)
|
= link_to 'Back', blogs_path
Try this in the view:
blog_comments_path(#blog)
The POST with the comment is made to the URL: /blogs/:blog_id/comments.
When the validation fails, you trying to build the form's URL using params[:id] which is nil. Using #blog instance should solve the problem.
The problem come as blog resources create 'index' method routes '/blogs', so when you are trying to access 'blogs/show', its try to find 'index' method for that controllers.
what should the controller action look like for a button_to with :remote => true.
I am new to ajax reqs so I don't know what I am doing. as I understand it, the :remote => true sets it up to be an ajax request.
<%= button_to "Generate Code", add_code_band_path(#band), :method => :post, :remote => true %>
My current action:
def add_code
#band = Band.find(params[:id])
if user_signed_in?
#code = current_user.codes.build(params[:code])
respond_to do |format|
if #code.save
format.html { redirect_to #band, notice: 'Reward was successfully created.' }
format.json { render json: #band, status: :created, location: #band }
else
format.html { render action: "show" }
format.json { render json: #band.errors, status: :unprocessable_entity }
end
end
else
redirect_to #band, :alert => "Your Not Logged In! You must be logged in to create a code"
end
end
You can't use redirect_to with Ajax calls. You should do something like this to redirect (when using ajax):
render :js => "window.location = 'path_to_redirect_to'"
If the problem still persists, try including format.js, in your respond to block.
If the page is just refreshing as you mentioned, ensure you have included and are correctly referencing the unobtrusive scripting adapter for jQuery (if you're using jQuery that is.)
https://github.com/rails/jquery-ujs
What is the difference between render :action => "new" and render :template => "users/new"? I have heard that rendering template, we can use for views from other controllers. Is that it or is there any difference in rendering layout also between the two? For render :template, is it neccessary to have an action defined or is the view page itself enough?
There is no difference. render :template => 'some/thing' is the same as just render 'some/thing', as well as the same as render :action => 'thing' if we are in the some controller.
From Ruby On Rails guide;
render :edit
render :action => :edit
render 'edit'
render 'edit.html.erb'
render :action => 'edit'
render :action => 'edit.html.erb'
render 'books/edit'
render 'books/edit.html.erb'
render :template => 'books/edit'
render :template => 'books/edit.html.erb'
render '/path/to/rails/app/views/books/edit'
render '/path/to/rails/app/views/books/edit.html.erb'
render :file => '/path/to/rails/app/views/books/edit'
render :file => '/path/to/rails/app/views/books/edit.html.erb'
Previously, calling render "foo/bar" in a controller action was equivalent to render file: "foo/bar". In Rails 4.2, this has been changed to mean render template: "foo/bar" instead. If you need to render a file, please change your code to use the explicit form (render file: "foo/bar") instead.
http://guides.rubyonrails.org/4_2_release_notes.html#render-with-a-string-argument
render :action => 'some_controller_action', :layout => 'some_layout_in_layout_folder'
will render the view of that controller action and apply the asset settings (javascript, CSS) of the some_layout_in_layout_folder layout.
If you write this in a controller action, it will use the styling of the specified layout in conjunction with any layout defined at the beginning of the class, if any