7

I am calling this js from a link:

function createNewTopLevelEntry(){
var user_id = $("#user").val();
var header = prompt("Enter the name");  
$.ajax( '/users/' + user_id + '/entries', {
    data: { 
        entry: { header: header,
                 user: user_id } },
    type: 'POST',
    cache: false,
    dataType: 'json',
    success: displayTopLevelEntries
});

}

It hits this controller:

def create
  @entry = Entry.new(params[:entry])
  respond_to do |format|
    if @entry.save
      format.html { redirect_to @entry, notice: 'Entry was successfully created.' }
      format.json { render json: @entry, status: :created, location: @entry }
    else
      format.html { render action: "new" }
      format.json { render json: @entry.errors, status: :unprocessable_entity }
    end
  end
end

This is the response on the server:

Started POST "/users/1/entries" for 127.0.0.1 at 2013-03-25 21:50:36 -0700
Processing by EntriesController#create as JSON
Parameters: {"entry"=>{"header"=>"Hi", "user"=>"1"}, "user_id"=>"1"}
(0.1ms)  begin transaction
SQL (0.5ms)  INSERT INTO "entries" ("completed", "created_at", "endtime", "header", "parent", "starttime", "starttimeset", "text", "totaltime", "updated_at", "user") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["completed", nil], ["created_at", Tue, 26 Mar 2013 04:50:36 UTC +00:00], ["endtime", nil], ["header", "Hi"], ["parent", nil], ["starttime", nil], ["starttimeset", nil], ["text", nil], ["totaltime", nil], ["updated_at", Tue, 26 Mar 2013 04:50:36 UTC +00:00], ["user", "1"]]
(2.5ms)  commit transaction
Completed 500 Internal Server Error in 10ms

NoMethodError - undefined method `entry_url' for #<EntriesController:0x007fb22b9f7fd8>:
(gem) actionpack-3.2.11/lib/action_dispatch/routing/polymorphic_routes.rb:129:in `polymorphic_url'
(gem) actionpack-3.2.11/lib/action_dispatch/routing/url_for.rb:150:in `url_for'
(gem) actionpack-3.2.11/lib/action_controller/metal/rendering.rb:60:in `_process_options'
(gem) actionpack-3.2.11/lib/action_controller/metal/streaming.rb:208:in `_process_options'
(gem) actionpack-3.2.11/lib/action_controller/metal/renderers.rb:34:in `block in _handle_render_options'

What is the entry_url? Why is it looking for it? Do i need to include something in the model. Its just has attr_accessors for the vars.

class Entry < ActiveRecord::Base
  attr_accessible :completed, :endtime, :header, :starttime, :starttimeset, :totaltime, :user, :text, :parent
end

Heres is my routes file:

Tasks::Application.routes.draw do
  match '/users/:id/projects' => 'users#show_projects_for_user'
  authenticated :user do
    root :to => 'home#index'
  end
  root :to => "home#index"
  devise_for :users
  resources :users do 
    resources :entries
  end
end

Thanks for the help.

Maks Demin
  • 183
  • 2
  • 7
  • the entry_url is what you're asking it to redirect to when you say redirect_to @entry – Richard Jordan Mar 26 '13 at 05:10
  • but the dataType is json shouldn't the formal.html not get called then? – Maks Demin Mar 26 '13 at 05:15
  • i removed the format.html line and the same error was there? – Maks Demin Mar 26 '13 at 05:16
  • right - same thing is happening in the json line - you're using a url for just entry - there isn't an entry_url only a user_entry_url so you have to pass [ user, entry ] to location: which is looking for the url (it won't let me type the @ sign before user and entry in a comment) – Richard Jordan Mar 26 '13 at 05:18
  • see addition to the answer below - might make it clearer as the comment won't let me type it nicely here – Richard Jordan Mar 26 '13 at 05:21

2 Answers2

9

The entry_url is what it's asking you to redirect to when you say redirect_to @entry

You don't have an entries resource in the routes file. You do have one nested within user, but then you need to pass as well as the entry.

redirect_to [ @user, @entry ]

just saw your comment - if it's doing this on the JSON path similarly you need to have

location: [@user, @entry]

Basically anywhere you're asking rails to build a url for an entry you need to pass the entry's user in because you have entry nested within user in the routes and not as a standalone resource routing.

Adding an edit to respond to the comment because there's no formatting in comments:

Yes, this it will work to delete the location as it will no longer call the helper to build that location in the json, but I am presuming you want that. So try this to make the location work:

format.json { render json => { :entry => @entry, :status => created, :location => [@user, @entry] }}

from your comment... if that's not working then let's try calling the url helper directly

format.json { render json => { :entry => @entry, :status => created, :location => user_entry_url(@user, @entry) }}
Richard Jordan
  • 8,066
  • 3
  • 39
  • 45
  • I think you meant more to come in that comment - you cannot do a multi-line comment :-) ...but the above answer should answer the question you asked - give it a try. – Richard Jordan Mar 26 '13 at 05:26
  • I change the code to this and its still throwing the error. Removing the location: works. format.json { render json: @entry, status: :created, location: [@user, @entry] } – Maks Demin Mar 26 '13 at 06:07
  • try explicitly calling the url helper - i.e. location: user_entry_url(@user, @entry) or user_entry_path(@user, @entry) – Richard Jordan Mar 26 '13 at 06:34
  • The identification of the problem, per my answer, is correct. We just have to get the syntax right building the json response – Richard Jordan Mar 26 '13 at 06:43
  • You got it. format.json { render json: @entry, status: :created, location: user_entry_path(@user, @entry) } works. But what does that even do? I proceeded fine without the location:. Thanks for your help! – Maks Demin Mar 26 '13 at 06:47
  • Phew, this one was driving me nuts :-) ...the location is including in the response json something like "location":"http://www.myapp.com/entries/4" which is good practise to include because it tells the json consumer programmatically where to look for the item if they want to access it again... if you don't give them that info then they have to know that to turn the @entry into a url they need to get its ID and append it to your url/entries... that's messy... is that clear? – Richard Jordan Mar 26 '13 at 06:50
  • ugh - the comment thread just turned my url into an actual url - in the json example i just included in that last comment the value in the key value pair should be the full url of where to find that entry as in "http : / / www . myapp . com / entries / 4" without the spaces – Richard Jordan Mar 26 '13 at 06:52
  • Ok that makes sense, so its a best practice because it makes it easier for people. Even though the object should include the info they would use to make the request, like user and id? – Maks Demin Mar 26 '13 at 06:59
  • Right - ultimately you should tell the user where to go on your system, not let them build that themselves... ideally you go all the way to HATEAOS http://en.wikipedia.org/wiki/HATEOAS - which is where your JSON API consumers can navigate your entire app from the links you include in each response to every interaction they have with the system - but baby steps :-) - start by at least giving the users the url of objects they create so they can access the objects... it's better for them as if you change your API they don't have to change their own code... – Richard Jordan Mar 26 '13 at 07:10
0

If you are using Rails3, this might case because with rails3, the url has become path

Ex:

#rails2
entry_url

#rails3
entry_path

So try entry_path instead of entry_url

sameera207
  • 16,547
  • 19
  • 87
  • 152
  • No, this is not correct. The problem is because he is not passing the requisite information to the path helper. Look at the routes. – Richard Jordan Mar 26 '13 at 06:32
  • **_url** refers to the full URL like `http://www.example.com/foo` while **_path** refers to the relative path like simply `/foo`. Both are useful and valid. – user569825 Oct 04 '13 at 20:25