In my RSpec tests, I need to simulate an AJAX GET request to the index action, and have been using the code as described in both the Rails docs and the RSpec book:
xhr :get, :index
This always fails though, as the test tries to load the show action (without any parameters) rather than the specified index action.
The controller action is:
def index
#contacts = Contact.all
respond_to do |format|
format.html
format.js {
render :update do |page|
page.replace_html :contact_search_results, :partial => 'contacts'
end
}
end
end
The error thrown by running the spec is (showing the :show action being used):
ActionView::TemplateError in 'ContactsController as an administrator user when
showing the index of contacts' as an AJAX request should render results into the
contact_search_results element'
contact_url failed to generate from {:action=>"show", :controller=>"contacts",
:id=>#<Contact id: nil, first_name: nil, ....>}
Does anyone know how I can simulate an AJAX call the index action in tests?
Thanks!
Actually I think you're misunderstanding the error. Somewhere along the way Rails is trying to call contact_url and the parameters are wrong. My suspicion is that it is indeed calling the index action which then renders the contact partial. If I'm right, the contacts partial is the location of the issue. I would recommend reviewing the contacts partial for any possible errors. If you're still having trouble, please post the body of your contacts partial.
You're trying to make a URL to a non-persisted Contact object. You can see that in the message: :id=>#<Contact id: nil
Related
I have two AJAX dropdowns, the first shows CountryObjs, and the second show the CityObjs belonging to that CountryObj. Selecting a different CountryObjs sends an AJAX request that updates the CityObjs for the new CountryObj. I'd like a simple test that passes a CountryObj and checks the CityObjs that are returned.
routes.rb
match '/update_cities', to: 'guides#update_cities', via: 'get'
Guide belongs_to CityObj and CountryObj, and they in turn has_many Guides.
guides_controller.rb
def update_cities
#cities = CityObj.where("country_obj_id = ?",
params[:country_obj_id]).order(:name)
debugger
respond_to do |format|
format.js
end
I'm still confused by testing in Rails. I'm not using rspec. Looking at my other tests that get :index and get :show, it seems like I should be able to do something like the following to pass a CountryObj and get into the update_cities method:
test "ajax dropdown" do
get :update_cities, city_obj: CityObj.last
end
But that gives an error
ActionController::UnknownFormat Exception: ActionController::UnknownFormat
To make an XmlHttpRequest (AJAX) request using GET you should try like this
test "ajax dropdown" do
xhr :get, :update_cities, city_obj: CityObj.last
end
I have a rails project with the following route:
get 'login', to: 'user_sessions#new', as: :login
In my UserSessionsController I have
def create
#user_session = UserSession.new(params[:user_session])
respond_to do |format|
if #user_session.save
# Do all the happy stuff
else
format.html { render :action => 'new' }
format.xml { render xml: #user_session.errors, status: :unprocessable_entity }
end
end
end
That's working ok, except that when the user enters incorrect parameters the route is via /user_sessions instead of /login, which is untidy (and means my test assertions are confusing).
Obviously I could just redirect_to login_path, but then my #user_session.errors don't seem to be available so by page doesn't show what was wrong.
How do I redirect back to /login and still have the errors show?
Edit:
It looks as if Rails makes this difficult because it's something I shouldn't try to do. The RESTful path isn't really something the user cares about so I shouldn't be using it as part of my UI testing. Instead, I am looking at the actual content of the rendered page, which the user does care about. Thanks all.
You can add
post 'login', to: 'user_sessions#create', as: :post_login
and change the form action accordingly.
This is happening because when you get validation errors in your form then you are on create action and not new action. Your create action simply render your new actions template with errors, it doesn't send a request to server and hence your url remains same so to fix it you can simply change the route for your create action to this:
post 'login', to: 'user_sessions#create', as: :login
Update:
You'll just have to change your route for create action and then make changes in your form, something like this:
<%= from_for #resource, url: login_path do |f| %>
// form fields
<% end %>
If you'll inspect your form you'll see that its method is POST so when you'll submit it, your form will send a POST request and when you hit /login in your browsers address bar it'll send a GET request so in first case you'll go to create action and in second one you'll go to new action
I'm redirecting from one controller to another. The receiving controller, uploads, doesn't have an index action, but has a create action, which I'm trying to use obviously. However when I redirect, I get the following issue
Unknown action
The action 'index' could not be found for UploadsController
redirect_to :controller => 'uploads', :action => 'create', flash: {error: "there was an error"}
Probably because the redirect_to is assuming that its redirecting with a GET request.
Since the index & create actions both go to the same path and depending on the HTTP verb, Rails decides which action to call...
So if the application gets a GET request to /uploads it will render the index action and if it gets a POST it will call the create action.
Furthermore, I don't think you can redirect_to a http POST... Are you sure that's what you want to do?
Try specifying :method => :post in the request. Create actions should only respond to that, unless you're doing fancy things with routes.
RESTful resource, default type routes. Creating an event is supposed to work as follows:
def create
#event = current_user.events.build(params[:event])
if #event.save
redirect_to #event, :flash => { :success => "Event created!" }
else
render :action => "new" # new_event_path
end
end
When invalid data is entered, it does render the "new" view/form again, but it renders this view at the "localhost:3000/events" URL, where the "index" action/view should be on.
My event routes seem like they ought to be pretty predictable:
resources :events
I just updated to Capybara 2, began using DatabaseCleaner, and set transactional_fixtures to false in preparation for testing some JS-enabled functionality but can't think of any other way I might have stuffed this up.
Is there some simple thing I'm missing that could cause a weird routing muck up like this?
Ideas, anyone, on where to start troubleshooting it?
This is the correct behavior. What is happening is that it is using the POST method for that URL when issuing the create action. Using a GET at the URL would be the index action. Also note that rendering a different template does not change the URL (that would require a redirect).
Check out section 2.2 in the Rails Routing documentation:
http://guides.rubyonrails.org/routing.html
When you create event from submitting form you using post method to /events route. And when data becomes invalid rails render events/new for your /events(POST) request at /events address.
But you can
redirect_to action: "new", event: #event.attributes
and add to new action
#item = Item.new(params[:item].except('protected attributes','created_at', 'updated_at', 'id'))
Is there any method that i should look at in rails3.2 source code so as to know where the navigation or the url part of the render call get resolved?
The reason is, i have a small app in which url is of the form
www.example.com/bob/edit
the above route as it suggests renders the edit form.EDIT: i was able to get to this route by modifying response on the link_to helper.
def update
#when validation passes
redirect_to #user
#when validation fails
respond_to do |format|
format.html {render :action => "edit"}
end
end
Now the problem is when a validation error occurs on submission to update action of users_controller,
the url becomes
www.example.com/users/bob/edit
config/routes.rb
get "users/new", to: => "users#new"
resources :users
as you can see there's nothing interesting happening in routes,
in models/user.rb
def to_param
"#{name}"
end
in views/edit.html.erb
form_for(#user) do |f|
end
Observation: here when the form is rendered afresh, form 'action' points to "users/bob" but when the form is re-rendered 'cos of validation error, form action mysteriosly changes to "users/" which is weired and if i remove the to_param in user.rb model it works fine
Though its not such a big deal, i was thinking where, if i needed to override the url that is generated on render call, to change?????
Any suggestions and pointers to explore are wecome....
I'm not sure how you're getting the URLs you're getting, but a general answer to your question would be it doesn't. The URL you see after sending a request is the URL the request was sent to (or redirected to), not that of the page you came from, nor that of the template you render in the end. In your case, I'm guessing the problem is that you created a custom URL for the edit page, but not for update, and your form_for(#user) is sending the request to your update URL (probably PUT "/users/bob").
To fix this, the first thing is to create your custom update route. Maybe something like:
put ":id/update", to: => "users#update"
And then have your form_for use that URL:
form_for(#user, :url => "#{#user.to_param}/update")