I think there are several sources of errors here:
undefined method `link_to'
This is highly unusual, since link_to
is a standard view helper. Are you sure the space before link_to
is really a space and not some sort of other invisible char (you sometimes get those for example on OSX when you use space
while holding alt
). Furthermore, your js erb has to be in your controllers view namespace, but since it gets executed when you render the action, this seems to be the case.
$(document).ready(function(){
You won't need to use this in .js.erb
templates, since there is no ready event fired. jQuery executes the script right away if the DOM is ready anyway, so it won't hurt (usually), it's just unnecessary.
$("#new_post").bind('ajax:success', function(xhr, data, status){
This is a bigger problem. The way you attach your handler now, it will be attached every time the form gets submitted and the server returns data. So, if there's an error, and the form gets submitted and returned a second time, you will either have the console
message or the anchor insertion executed two times. So better be ready for this kind of event:
$("#new_post").not('.registered').addClass('registered').bind('ajax:success', function(xhr, data, status){
This will prevent multiple event handlers.
Then there's the third problem:
var user_name = data.user; // json is contained in data variable
$("#recent_posts").prepend("<%= j link_to(user_name, '#') %>");
Here, you're trying to use a variable you assigned in javascript in the erb
inline ruby. This won't work, since the ruby variable user_name
is evaluated serverside when the template is rendered. The javascript variable assignment on the other hand is evaluated in the browser when the client receives the rendered template from the server. So, what can you do?
link_to
is not all that magic. It just renders an anchor tag. So, the same can be written like this:
var user_name = data.user; // json is contained in data variable
$("#recent_posts").prepend(["<a href='#'>", user_name, "</a>"].join(''));
So far, so good. The biggest problem you have though is: The server can not return both a rendered .js.erb
template and json
data at once. So the data you get in your javascript function will just be the rendered .js.erb
template string. Communication with the server in JSON
is really the best thing, so let's forget about the rails integrated form handling and write it ourselves:
Delete
:remote => true
from the form optionsAdd
:format => :json
to yourcreate
routeresources :posts, :only => [:create], :format => :json resources :posts, :except => [:create]
Add javascript in your assets that handles your form remotely
// after DOM ready var form = $('#new_post'); form.on('submit', function(e) { $.ajax({ url: form.prop('action'), type: form.prop('method') || 'POST' //for create action, data: form.serializeArray(), dataType: form.data('type') || 'json', success: function(data, status, xhr) { var user_name = data.user; // json is contained in data variable $("#recent_posts").prepend(["<a href='#'>", user_name, "</a>"].join('')); }, error: function(xhr, status, error) { console.log('error') } }); return false; //prevent normal submit });
Now you're ready to return pure
JSON
from the server:render :json => resource.to_json(:include => :errors)