i'm trying to update the user information when on mobile but rails log show:
someone know why this happen on mobile mode?
Missing template users/update, application/update with
{:locale=>[:"en"], :formats=>[:mobile], :handlers=>[:erb, :builder,
:coffee]}. Searched in:
def update
#user = User.find(params[:id])
respond_to do |format|
format.html do
#states = State.all
#cities = City.where('state_id = ?', State.first.id)
if #user.update_attributes(params[:user])
redirect_to(action: :edit, id: #user, only_path: true, format: :html)
flash[:notice] = 'updated'
else
render :edit
end
end
format.json do
#user.update_attributes(params[:user])
render nothing: true
end
end
end
You have format.html do and format.json do but you don't have a format.mobile do block.
Since the html and json blocks aren't executed, the code falls through and the default for any action is to render the format with the name of the action, so you're in the action update therefore rails by default looks for a view update.html.erb or update.html.haml
Related
I have a rails controller where every action has the same respond_to block for every action, eg:
def some_action
respond_to do |format|
format.html { redirect_to :back }
format.js { render layout: false }
end
end
Is there a way that I can set this as the default response for all actions? I know that I can use
respond_to :html, :js
at the top of the controller, but can this be used to set the specific responses for each format?
Going though respond_with and respond_to documentation and source code. You can either
Use respond_to
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to(#user) }
format.xml { render xml: #user }
else
format.html { render action: "new" }
format.xml { render xml: #user }
end
end
end
OR respond_with
respond_to :html, :xml
def create
#user = User.new(params[:user])
flash[:notice] = 'User was successfully created.' if #user.save
respond_with(#user)
end
A work around is to create your own custom respond method, or manually check for the mime type as follows:
****NOTE: this is a really bad practice, I recommend sticking to conventions.
def some_action
render json: {"a" => "s"} if request.format.json?
render :some_action if request.format.html?
end
If you want all actions to respond exactly the same, move the respond_to block into a method.
def some_action
# do things
respond
end
def another_action
# do more things
respond
end
def special_action
# do special things
respond
end
private
def respond
respond_to do |format|
format.html { redirect_to :back }
format.js { render layout: false }
end
end
This will DRY up your controller, which I assume was the question.
I have a controller "UserController" that should respond to normal and ajax requests to http://localhost:3000/user/3.
When it is a normal request, I want to render my view. When it is an AJAX request, I want to return JSON.
The correct approach seems to be a respond_to do |format| block. Writing the JSON is easy, but how can I get it to respond to the HTML and simply render the view as usual?
def show
#user = User.find(params[:id])
respond_to do |format|
format.html {
render :show ????this seems unnecessary. Can it be eliminated???
}
format.json {
render json: #user
}
end
end
As per my knowledge its not necessary to "render show" in format.html it will automatically look for a respective action view for ex : show.html.erb for html request and show,js,erb for JS request.
so this will work
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
also, you can check the request is ajax or not by checking request.xhr? it returns true if request is a ajax one.
Yes, you can change it to
respond_to do |format|
format.html
format.json { render json: #user }
end
The best way to do this is just like Amitkumar Jha said, but if you need a simple and quick way to render your objects, you can also use this "shortcut":
def index
#users = User.all
respond_to :html, :json, :xml
end
Or make respond_to work for all the actions in the controller using respond_with :
class UserController < ApplicationController
respond_to :html, :json, :xml
def index
#users = User.all
respond_with(#users)
end
end
Starting from Rails 4.2 version you will need to use gem responder to be able to use respond_with.
If you need more control and want to be able to have a few actions that act differently, always use a full respond_to block. You can read more here.
In the Update action of Rails controllers usually there is code that looks like this:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
render :edit
end
end
In the else case, this will render the edit template. But what if I wanted to use a respond_to, exactly the same way that I have in the edit action, as:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
So, if the Update fails, be sure you are returning a json or html depending on the requested format. Does that makes sense? If so, how would you avoid the error: "Render and/or redirect were called multiple times in this action"
Makes sense to me. The answer should be simple, just return after redirect_to.
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
return
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
Not sure exactly how you're rendering multiple times, but assuming you are, a well-placed return should tell RAILS to stop processing any further renders after redirecting. If that's all true, it's likely that there's an after_filter interfering from somewhere.
This is a follow up question to: Rendering different views in one action
The error I am getting is:
Template is missing
Missing template items/show, application/show with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}.
It should be noted, that I copied the show.html.erb file to two files show_with_edit.html.erb and show_with_star.erb, and deleted show.html.erb to avoid duplicates.
My Code in posts_controller.rb
def show
if signed_in?
show_signed_in
else
show_not_signed_in
end
end
def show_signed_in
#add methods here
#post = Post.find(params[:id])
respond_to do |format|
format.html # show_with_edit.html.erb
format.json { render json: #post }
end
render 'show_with_edit'
end
def show_not_signed_in
#add methods here
#post = Post.find(params[:id])
respond_to do |format|
format.html # show_with_star.html.erb
format.json { render json: #post }
end
render 'show_with_star'
end
I am aware that for now the two different views are identical, I just put there different text for now. Once I have this nailed down I'll add to each view its own methods and content etc.
You've put render in the wrong places.
def show_signed_in
#add methods here
#post = Post.find(params[:id])
respond_to do |format|
format.html # show_with_edit.html.erb
format.json { render json: #post }
end
render 'show_with_edit'
end
should be
def show_signed_in
#add methods here
#post = Post.find(params[:id])
respond_to do |format|
format.html { render 'show_with_edit' }
format.json { render json: #post }
end
end
Note the render that is moved to the format.html block.
The same applies for show_not_signed_in.
please check your route.rb file is properly written , eg: consider following
resources :posts
collection
get :show_not_signed_in
get :show_signed_in
end
collection you write the method that is get or post
I've come across a really strange error. I've installed 'Blogit' and am trying to add on a few bits and pieces. I'm encountering a strange error when I submit a new entry:
Template is missing
Missing template blogit/posts/create, blogit/application/create, application/create with
{:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: *
"/Users/James/Documents/Websites/Backpack Bug/app/views" * "/Users/James/.rvm/gems/ruby-
1.9.3-p0/gems/blogit-0.4.8/app/views" * "/Users/James/.rvm/gems/ruby-1.9.3-
p0/gems/kaminari-0.14.1/app/views" * "/Users/James/.rvm/gems/ruby-1.9.3-p0/gems/devise-
2.1.2/app/views"
I have a feeling this is to do with my routing. Here is routes.rb
appname::Application.routes.draw do
root :to => 'locations#index'
devise_for :users
resources :locations do
collection do
get 'location'
end
end
mount Blogit::Engine => "/blog", :as => "blog"
end
Here is the posts controller:
module Blogit
class PostsController < ApplicationController
unless blogit_conf.include_admin_actions
before_filter :raise_404, except: [:index, :show, :tagged]
end
blogit_authenticate(except: [:index, :show, :tagged])
blogit_cacher(:index, :show, :tagged)
blogit_sweeper(:create, :update, :destroy)
def index
respond_to do |format|
format.xml {
#posts = Post.order('created_at DESC')
}
format.html {
#posts = Post.for_index(params[:page])
}
format.rss {
#posts = Post.order('created_at DESC')
}
end
end
def show
#post = Post.find(params[:id])
#comment = #post.comments.new
end
def tagged
#posts = Post.for_index(params[:page]).tagged_with(params[:tag])
render :index
end
def location
#georesult = Geocoder.search(params[:location])
respond_to do |format|
format.html {render :layout=>false}# venues.html.erb
end
end
def new
#post = current_blogger.blog_posts.new(params[:post])
#location = #post.locations.build
end
def edit
#post = current_blogger.blog_posts.find(params[:id])
#location = #post.locations.new
end
def create
#post = current_blogger.blog_posts.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, :method => :get, notice: 'Blog post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def update
#post = current_blogger.blog_posts.find(params[:id])
if #post.update_attributes(params[:post])
redirect_to #post, notice: 'Blog post was successfully updated.'
else
render action: "edit"
end
end
def destroy
#post = current_blogger.blog_posts.find(params[:id])
#post.destroy
redirect_to posts_url, notice: "Blog post was successfully destroyed."
end
private
def raise_404
# Don't include admin actions if include_admin_actions is false
render file: "#{Rails.root}/public/404.html", status: :not_found, layout: false
end
end
end
All I've changed from the source so far is, I've basically created a multipart form which allows searches for locations and submits them to a locations table in the same post action. Not sure if this has anything to do with it. I can post up all this code but it's pretty lengthy. Let me know if you think this would be useful too.
Thanks a lot for all your help! Frankly, I'm stumped.
James
Just a hunch: see if your location action is getting called. I just experienced a slightly different error where any calls to redirect_to in my controller were causing my location method in the same controller to get called. (Putting a raise at the beginning of the location method will quickly let you know.)
I haven't tried investigation exactly why this was happening, but renaming my location action fixed this (obviously, this required changing any other code that referenced that endpoint, like AJAX requests in my JavaScript). Rails magic, no doubt.