I'm using the respond_to and respond_with in a rails app, but in one use case I need to respond with just a text for just one of the resource formats (:json)... But I can't find how to do this...
I want something like this (I know this doesn't work)
def create
...
respond_with(:json, render :text => "Successfully Done!")
end
Any Idea??
Thanks!
It seems that this may be what you are looking for:
def create
respond_to do |format|
format.html
format.json { render :text => "Successfully Done!" }
end
end
Andres,
The solution is this:
class TextController < ApplicationController
respond_to :json, :text
def index
respond_with do |format|
format.json {
render :text => "I'm a text provided by json format"
}
format.text {
render :text => "I'm a text"
}
end
end
end
And at your routes.rb:
match '/text' => 'text#index', defaults: { format: 'text' }
Related
I'm trying to learn how to test Rails controllers right now and I'm stuck. Whenever I try to test my test/controllers/articles_controller_test.rb file I get this error message.
ArticlesControllerTest#test_should_update_article:
TypeError: can't cast ActionController::Parameters to integer
app/controllers/articles_controller.rb:67:in `update'
test/controllers/articles_controller_test.rb:50:in `block in <class:ArticlesControllerTest>'
The articles_controller_test.rb file is this:
require 'test_helper'
class ArticlesControllerTest < ActionController::TestCase
setup do
#article = articles(:welcome_to_rails)
end
test "should get index" do
get :index
assert_response :success
assert_template 'index'
assert_not_nil assigns(:articles)
end
test "should get new" do
login_as(:eugene)
get :new
assert_response :success
end
test "should create article" do
login_as(:eugene)
assert_difference('Article.count') do
post :create, :article => { :title => 'Post title',
:body => 'Lorem ipsum..' }
end
assert_response :redirect
assert_redirected_to article_path(assigns(:article))
end
test "should show article" do
get :show, :id => #article.to_param
assert_response :success
assert_template 'show'
assert_not_nil assigns(:article)
assert assigns(:article).valid?
end
test "should get edit" do
login_as(:eugene)
get :edit, :id => #article.to_param
assert_response :success
end
test "should update article" do
login_as(:eugene)
**put :update, :id => #article.to_param, :article => { :title => 'New Title' }**
assert_redirected_to article_path(assigns(:article))
end
test "should destroy article" do
login_as(:eugene)
assert_nothing_raised { Article.find(#article.to_param)}
assert_difference('Article.count', -1) do
delete :destroy, :id => #article.to_param
end
assert_response :redirect
assert_redirected_to articles_path
assert_raise(ActiveRecord::RecordNotFound) { Article.find(#article.to_param) }
end
end
I'm running Rails 4.1.10, and I'm pretty sure that my error has something to do with the Strong Params gem that Rails uses now. If someone could show me the problem with my code and explain why it's wrong that would be greatly appreciated.
This is the actual article_controller file, line 50 and line 67 are respectively outlined in stars:
class ArticlesController < ApplicationController
before_filter :authenticate, :except => [:index, :show]
def index
#articles = Article.all
respond_to do |format|
format.html
format.xml { render :xml => #articles }
end end
def show
#article = Article.find(params[:id])
respond_to do |format|
format.html
format.xml { render :xml => #article }
end
end
def new
#article = Article.new
respond_to do |format|
format.html
format.xml { render :xml => #article }
end
end
def edit
#article = current_user.articles.find(params[:id])
end
def create
#article = current_user.articles.new(article_params)
respond_to do |format|
if #article.save
format.html { redirect_to(#article, :notice => 'Article was successfully created.') }
**format.xml { render :xml => #article, :status => :created, :location => #article }**
else
format.html { render :action => "new" }
format.xml { render :xml => #article.errors, :status => :unprocessable_entity }
end
end
end
def notify_friend
#article = Article.find(params[:id])
Notifier.email_friend(#article, params[:name], params[:email]).deliver
redirect_to #article, :notice => "The message has been sent to your friend"
end
def update
**#article = current_user.articles.find(article_params)**
respond_to do |format|
if #article.update_attributes(params[:article])
format.html { redirect_to(#article, :notice => 'Article was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #article.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#article = current_user.articles.find(params[:id])
#article.destroy
respond_to do |format|
format.html { redirect_to(articles_url) }
format.xml { head :ok }
end
end
end
def article_params
params.require(:article).permit(:title, :location, :categories, :excerpt, :body, :published_at)
end
It looks like you defined the article_params method outside of your class. Just change the last five lines in your file from
end
def article_params
params.require(:article).permit(:title, :location, :categories, :excerpt, :body, :published_at)
end
to
def article_params
params.require(:article).permit(:title, :location, :categories, :excerpt, :body, :published_at)
end
end
Furthermore I think you should change this line in your controller
def create
#article = current_user.articles.new(article_params)
to
def create
#article = current_user.articles.build(article_params)
See what methods the has_many methods adds to a class: The method that returns a new record is called build, not new...
The class end is in the wrong place. Move it to before the article_params method definition.
Newbie to RoR here. I have built models with no namespace. One of them is called 'Brand'. I then proceeded to use rails g "admin/brands" to put maintenance functionality under an admin namespace, using rails generate scaffolding_controller "admin/brand" - which produced the views and the controller. The unit tests fail when I rake test:
NoMethodError: undefined method `admin_brands' for #<Admin::BrandsControllerTest:0x1034c0730>
test/functional/admin/brands_controller_test.rb:5:in `_callback_before_193'
in routes.rb I have:
# Administration routes
namespace :admin do
resources :brands
end
The generated controller code is as follows:
class Admin::BrandsController < ApplicationController
# GET /admin/brands
# GET /admin/brands.json
def index
#admin_brands = Brand.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #admin_brands }
end
end
# GET /admin/brands/1
# GET /admin/brands/1.json
def show
#admin_brand = Brand.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #admin_brand }
end
end
# GET /admin/brands/new
# GET /admin/brands/new.json
def new
#admin_brand = Brand.new
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #admin_brand }
end
end
# GET /admin/brands/1/edit
def edit
#admin_brand = Brand.find(params[:id])
end
# POST /admin/brands
# POST /admin/brands.json
def create
#admin_brand = Brand.new(params[:admin_brand])
respond_to do |format|
if #admin_brand.save
format.html { redirect_to #admin_brand, :notice => 'Brand was successfully created.' }
format.json { render :json => #admin_brand, :status => :created, :location => #admin_brand }
else
format.html { render :action => "new" }
format.json { render :json => #admin_brand.errors, :status => :unprocessable_entity }
end
end
end
# PUT /admin/brands/1
# PUT /admin/brands/1.json
def update
#admin_brand = Brand.find(params[:id])
respond_to do |format|
if #admin_brand.update_attributes(params[:admin_brand])
format.html { redirect_to #admin_brand, :notice => 'Brand was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => #admin_brand.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /admin/brands/1
# DELETE /admin/brands/1.json
def destroy
#admin_brand = Brand.find(params[:id])
#admin_brand.destroy
respond_to do |format|
format.html { redirect_to admin_brands_url }
format.json { head :no_content }
end
end
end
Not sure how to debug this type of issue... I gather that paths are messed up somehow, but that is much as I can fathom at this point. Help appreciated.
In our company we dont use scaffold, especially when we need to generate admin namespace.
You can simply write admin namespace yourself.
config/routes.rb
namespace :admin do
root :to => "base#index"
resources :pages
# resources :states do
# member do
# get :make_default
# end
# end
end
app/controllers/admin/base_controller.rb
class Admin::BaseController < ApplicationController
before_filter :authenticate_user!, :admin_user?
layout "admin/admin"
def index
#page = Page.all
end
private
def admin_user?
redirect_to root_path, :alert => 'This page is allowed for admin' unless current_user.admin
end
end
app/views/admin/base/index.html.haml
= link_to "New Post", new_admin_post_path
%ul
- #post.each do |post|
%li= post.title
I have a controller called "products_controllers.rb" that have this method:
def create
...
...
respond_to do |format|
if #product.save
???????
else
format.html { render :action => "new" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
Whenever the product is save I want to redirect it to an specific view called "suppliers", that belongs to the product views, how can I do that?
Thanks in advance!
If you're using restful routes and there is a relationship where product has many suppliers, you could use:
format.html { redirect_to product_suppliers_url(#product) }
with something like this in your routes.rb:
map.resource :products do |product|
product.resource :suppliers
end
or you could also just use this:
format.html { redirect_to :action => 'suppliers', :id => #product.id }
Something like
redirect_to 'product/suppliers'
Source:
http://guides.rubyonrails.org/layouts_and_rendering.html#using-redirect_to
Comment: Next time make sure to specify "in rails" in the text of your question since views and controllers are used by many frameworks.
In your controller:
def create
...
...
respond_to do |format|
if #product.save
???????
else
format.html { render :action => "suppliers" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
def suppliers
#Your suppliers code goes here
end
In routes.rb
resources :venues do
member do
get 'suppliers'
end
end
I want my Rails rest application has json as default output format , also I want remove html format. Any suggestions? Thanks
Yes you can do it.
In your controller,
respond_to do |format|
#format.html # show.html.erb
#format.xml { render :xml => #post }
format.json { render :json => #post }
end
or you can handle it as javascript
respond_to do |format| format.js { render :json { :only => :name}.to_json end
then you just access your action with ".js" in the end
Try like this
format.any(:xml, :html, :json) { render :json => #post }
I want to change the redirect on a create method, but I don't want to override the whole thing.
like, by default, if create (lets say) exists, it will have something like
respond_to do |format|
if #user.save(params[:user])
flash[:notice] = 'The user has been updated'
format.html { redirect_to :controller => "subscriptions",
:action => "show",
:id => #user.account_id }
format.xml { head :ok }
else
format.html { render :action => :edit }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
or something like that...
but where it says format.html...
I want to be able to change the redirect_to in my class that inherits this method... but I don't want to rewrite the whole thing. =\
ideas?
Calling super won't solve your problem, because you want to alter the inner workings of the method, not pass new parameters or add code to it.
What I would do, is create a third function (lets call it common_routine) that has the common functionality. Then you would call common_routine from both places that need to access it. However, to change the code as you need, you'll pass it a block, and yield that block inside the method to modify how the method works.
example:
def common_routine
respond_to do |format|
if #user.save(params[:user])
flash[:notice] = 'The user has been updated'
format.html { yield }
format.xml { head :ok }
else
format.html { render :action => :edit }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
Then you call it with:
common_routine { redirect_to :controller => "subscriptions", :action => "show", :id => #user.account_id }
or
common_routine { redirect_to root_path }
The code block that you pass to common_routine would be "yielded", which allows you to have the same functionality with minor tweaks as needed.
If you know what arguments the original method takes, you can call the super method.
class Foo
def foo(arg)
arg*2
end
end
class Bar < Foo
def foo(arg)
super(arg) + 3
end
end
a = new Foo
a.foo(2) # => 4
b = new Bar
b.foo(2) # => 7