Rails testing: assert render action - ruby-on-rails

How can I write a test to assert that the action new is rendered?
def method
...
render :action => :new
end
I'm looking for something like the lines below, but to assert that the action was called, not the template:
assert_equal layout, #response.layout
assert_equal format, #request.format
I know I can't do #response.action
Thanks in advance!
Deb

For future people that find this, the correct method is:
assert_template :new

Let's say you have a controller action for create, as follows:
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
format.xml { render :xml => #post, :status => :created, :location => #post }
else
format.html { render :action => "new" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
end
And here is the standard Scaffold 'posts#new' view
<h1>New post</h1>
<% form_for(#post) do |f| %>
<%= f.error_messages %>
...... # just to show, it's bigger....
Now, if a Post is succesfully created you want to be redirected, but if it fails, we just want to re-render the NEW action. The test below uses what our main man DJTripleThreat said to use assert_template.
test "should not create post and instead render new" do
post :create, :post => { }
assert_template :new
#added to doubly verify
assert_tag :tag => "h1", :child => /New post/
end
If that still doesn't float your boat, I'd even add an assert_tag to make sure some of the view is coming up, so you know that it is displayed/rendered to the end user.
Hope this helps.

As of Rails 5.0.0, you can test that the action is rendered properly by testing the displayed template.
You first need to add the rails-controller-testing gem to your Gemfile (as it was extracted outside of Rails since version 5). Then, in your test, simply use:
assert_template :new

My original answer is wrong. As #Mohammad El-Abid indicated below, the correct method is:
assert_template :new
Original answer:
The view would be rendered, the action called.
Try this:
#controller.expects(:new)

Related

Writing method for form posts a blank field

I am running rails 3.2
I have created a nested form (requests > tags) with coffeescript handling the addition of new tags.
Everything works with the exception of the form posting a blank tag.name
I am trying to write a method to delete the blank field before the form posts. I realize this may be the wrong approach, but I am still a beginner:
requests_controller.rb
def create
#request = current_user.requests.build(params[:request])
#tag = Tag.new
if #tag.name.blank?
destroy_blank
end
respond_to do |format|
if #request.save
format.html { redirect_to(#request,
:notice => 'Request was successfully created.') }
format.json { render :json => #request,
:status => :created, :location => #request }
else
format.html { render :action => "new" }
format.json { render :json => #request.errors,
:status => :unprocessable_entity }
end
end
end
request.rb
def destroy_blank
blank = #tag.name
blank.delete
end
I hope that's clear. If not let me know and I will include more information.
If you can't stop blank tags from coming in, you can create a before_create filter in the model to skip saving blank tags. Leave the controller clean and simple.
Good luck!

Rails 3.0: No route error on PUT member route

I have a Rails 3.0 application which features a simple voting mechanism that adds a count to a number of down votes. I've set up a PUT route in routes.rb and created a method in my controller to handle it. The down vote link itself renders properly, but on clicking it gives me a Routing Error No route matches "/venues/18/down_vote" error.
Here's my controller code:
def down_vote
#venue = Venue.find(params[:id])
respond_to do |format|
if #venue.update_attribute(:mon_closed_accuracy_downvotes => #venue.mon_closed_accuracy_downvotes + 1)
format.html { redirect_to(:back, :flash => { :success => "Shenanigans were successfully called on #{ #venue.name }'s closing time." }) }
format.xml { head :ok }
else
format.html { render :action => 'show' }
format.xml { render :xml => #venue.errors, :status => :unprocessable_entity }
end
end
end
Here's my route code for the down_vote route:
resources :venues do
put 'down_vote', :on => :member
end
View code (inside a partial for a list of venues):
<%= link_to 'Incorrect?', down_vote_venue_path(venue), :method => :put %>
Again, the view itself renders fine, and the link renders as expected:
Incorrect?
Any ideas?
Sounds like you've got a problem with your javascript. Are you including the proper files? What does your layout look like?

Rails3 Update Action Problem Nested Resource

I've got an problem with my update action for a nested resource.
In my app, my orders have many invoices.
Creating a new invoice, I correctly end up with the following url:
/orders/11/invoices/new
And when I edit the invoice, again, it's all correct:
/orders/11/invoices/3/edit
This works fine when the save is a success, however if the validation fails, it routes back to:
/invoices/3
I have the following in my invoices controller:
def update
# #order = Order.find(params[:order_id])
# #invoice = #order.invoices.find(params[:id])
#invoice = Invoice.find(params[:id])
respond_to do |format|
if #invoice.update_attributes(params[:invoice])
format.html { redirect_to(order_invoice_path(#invoice.order, #invoice), :notice => 'Invoice was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #invoice.errors, :status => :unprocessable_entity }
end
end
end
def edit
#invoice = Invoice.find(params[:id])
3.times { #invoice.invoice_items.build }
end
I'm assuming I need to edit the #invoice.errors part but I don't know what to change it to?
Any help appreciated. Jx
When updating failed, you use "render" (comparing with the "redirect_to" in the succeeding path), this brings you to invoice editing path by default. You can use "redirect_to" here to keep the URI path you want, but need remembering to preserve the models' states so your users don't need to fill the entire form all over again.
A detail instruction can be found here: How to make a render :edit call show the /edit in the address bar
Yan
in your form you should add your order, like this:
<%= form_for [#order, #invoice] ... do |f| %>
...
<% end %>
And then uncomment this two lines
# #order = Order.find(params[:order_id])
# #invoice = #order.invoices.find(params[:id])
so your form will send its request to POST /orders/XX/invoices/XX

Having problems creating a Renew action and view in Rails3

please can somebody help me with this .i want to create a renew link which will update some of the fields in a table called members,am using rails 3 and i have created my action and the corresponding view but i still have an error that states
"undefined method'renew_member_path' for #<#:0xb66bcae0>"
below is the action i created in the members_controller
Class MembersController
def renew
#member = Member.find(params[:id])
respond_to do |format|
if #member.renew_attributes(params[:member])
format.html { redirect_to(#member, :notice => 'Member was succesfully Renewed.'}
format.xml {head :ok }
else
format.html { render :action => 'renew'}
format.xml { render :xml => #member.errors, :status => :unprocessable_entity}
end
end
end
I created a view called renew.html.erb
Your route is not set. You need to update your routes.rb file to something like this:
match 'members/renew' => 'members#renew', :as => :renew_member

Nice way of doing dual column validation

I'm using Rails 3 for this one. I've got a collections model, a user model and an intermediate subscription model. This way a user can subscribe to multiple collections, with a particular role. However, I don't want a user to be able to subscribe to the same collection twice.
So in my Subscription model I've got something like:
validate :subscription_duplicates
def subscription_duplicates
self.errors.add_to_base "This user is already subscribed" if Subscription.where(:user_id => self.user.id, :collection_id => self.collection.id)
end
However this seems ugly. Also, it breaks when I want to do something like the following in my collection controller:
def create
#collection = Collection.new(params[:collection])
#collection.subscriptions.build(:user => current_user, :role => Subscription::ROLES['owner'])
#collection.save
respond_with(#collection)
end
When I do the build the subscription does not have an id so I get a "Called id for nil" error.
Thanks for any guidance!
use validates_uniqueness_of
validates_uniqueness_of :user_id, :scope => :collection_id
First of all, your create action should always test if the object was saved, and if not then handle that (usually by re-rendering the new/edit page and showing the errors to the user).
A standard sort of create action would look like this (for a #post in this case):
def create
#post = Post.new(params[:post])
#created = #post.save
respond_to do |format|
if #created
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to #post }
format.xml { render :xml => #post, :status => :created, :location => #post }
format.js
else
format.html { render :action => :new } #or edit or wherever you got here from
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
format.js
end
end
end
Shingara's approach to avoiding duplicates should work fine for you.

Resources