How do i post a form in rails using ajax? - ruby-on-rails

I have a rails app that I need to use Ajax to post on my model.
I have only this line in my filename.js.erb
$('#new-band a').html('<%= j render 'form'%>')
Here is my error:
Showing /<snip>/ajax/app/views/layouts/application.html.erb where line #8 raised:
undefined method `render' for #<#<Class:0x00007fad63eb3b98>:0x00007fad5e2c13f8>

Try changing your single quote to double quotes around the form. For example:
$('#new-band a').html('<%= j render 'form'%>')
Changes to:
$('#new-band a').html('<%= j render "form" %>')

You can try this:
$('#new-band a').html("<%= j render(:partial => 'form') %>");

Related

Rails coflict ajax and URI.encode

I have a search string that, through my controller, connects to my written library, and sends a get request to a third-party api. The form:
<%= form_with(:url => url_for(:controller => 'orders', :action => 'find_drug'), method: "get") do %>
<%= text_field_tag :drug_name, nil, class: "search_drug", placeholder:"Find drug..." %>
<%= button_to "Find", nil, class: "search_drug_button" %>
<% end %>
Ajax:
$('document').ready(function() {
$('.search_drug_button').click(function(){
$.ajax({
url: 'orders/find_drug',
}).done(function(data) {
console.log(data);
});
});
});
controller OrdersController:
def find_drug
response = ApiParser::Parser.new
drugs = response.get_drug(params[:drug_name]).response
respond_to do |format|
format.json { render json: drugs.body}
end
end
Method in my library (written using the HTTParty gem):
module ApiParser
class Parser
include HTTParty
...
def get_drug(drug)
options = "?search.drugs={\"ls\": \"#{URI.encode(drug)}\"}"
self.class.get(options, format: :json)
end
...
end
end
In the console, 2 requests are sent (one of the form, directly to the controller with code 200, the second via ajax) and ajax gives me an error 500
NoMethodError in OrdersController#find_drug
undefined method `gsub' for nil:NilClass
Extracted source (around line #305):
#303 unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false)
#304 end
*305 str.gsub(unsafe) do
#306 us = $&
#307 tmp = ''
#308 us.each_byte do |uc|
Extracted source (around line #104):
#102 def escape(*arg)
#103 warn "#{caller(1)[0]}: warning: URI.escape is obsolete" if $VERBOSE
*104 DEFAULT_PARSER.escape(*arg)
#105 end
#106 alias encode escape
#107 #
Extracted source (around line #38):
**#this is my code**
*38 options = "?search.drugs={\"ls\": \"#{URI.encode(drug)}\"}"
#39 self.class.get(options, format: :json)
request in console Chrome 200:
...localhost:3000/orders/find_drug?utf8=%E2%9C%93&drug_name=%D1%8F%D1%80%&authenticity_token=Ndao2...
500:
...localhost:3000/orders/find_drug
If, in the controller, instead of params[:drug_name], I simply pass the string I want to find, both queries with code 200 work. Having written the whole question, I thought that my ajax is not receiving this particular params[:drug_name] , and can not search for an empty value(but it is not exactly). Just starting to work with javascript
I tried to perform such an Ajax request:
$('document').ready(function() {
$('.search_drug_button').click(function(e){
e.preventDefault();
$.ajax({
url: 'orders/find_drug',
data: new FormData($(this).closest("form")[0])
}).done(function(data){
console.log(data);
});
});
});
but I got an error
jquery-3.3.1.min.js:2 Uncaught TypeError: Illegal invocation
at i (jquery-3.3.1.min.js:2)
at jt (jquery-3.3.1.min.js:2)
at Function.w.param (jquery-3.3.1.min.js:2)
at Function.ajax (jquery-3.3.1.min.js:2)
at HTMLInputElement.<anonymous> (Аптечная_сеть:551)
at HTMLInputElement.dispatch (jquery-3.3.1.min.js:2)
at HTMLInputElement.y.handle (jquery-3.3.1.min.js:2)
First let me tell you why your code isn't working.
You're using form and jQuery together
If you want to use jQuery you should block all the default actions which is happening on your submit button by using event.preventDefault(); otherwise you'll be sending two requests one with default form submission and other with jQuery.
Solution:
you can use rails default functionality by using js.erb.
To get this working.
Use this in your controller code.
def find_drug
response = ApiParser::Parser.new
#drugs = response.get_drug(params[:drug_name]).response
end
comment out all your ajax code.
replace your code with form_with(url: '/orders/find_drug', method: :get)
create a file in orders folder as find_drug.js.erb
write console.log('<%= #data %>'); in find_drug.js.erb
now check it. If you're still facing problems do let me know.

Integrate ruby variable into a js

How I can integrate ruby variable into a js file. I would like to render a partial relative to the current step of registration of my User.
But I can't succeed it, Rails do not translate #flat.current_step in his value (which is a integer). Any ideas ?
$('.flats').replaceWith("<%= j render partial: 'flats/steps/step#{#flat.current_step}' %>");
Error
ActionView::Template::Error (Missing partial flats/steps/_step#{#flat.current_step}
Ruby does not interpolate the #{} when wrapped in single quotes. Change your call to:
$('.flats').replaceWith('<%= j render partial: "flats/steps/step#{#flat.current_step}" %>');

locals not working for controller rendering in rails 5.1

I have a controller action that renders a printable version of the page using a print.html.erb template. The controller code is:
def print
#title = 'Print - Drill'
render :show, layout: 'print', locals: { back_pth: drill_path(#drill) }
end
and in print.html.erb there is a line:
<%= link_to 'Back', back_pth, class: 'print_link' %>
but this generates an error:
ActionView::Template::Error:
undefined local variable or method `back_pth' for #<#<Class:0x007fd6004e1230>:0x007fd5f7da57d0>
The print template is called by many different controller actions, so how do I fix this? This code worked in rails 5.0.6.
As pointed out by FarazPantakar this is an issue in the rails 5.1 ActionController. The issue report has a workaround which is to use local_assigns in the html, so the link becomes
<%= link_to 'Back', local_assigns[:back_pth], class: 'print_link' %>
I am not very sure if this classifies as an answer but this might be what you're experiencing?
Perhaps, for now, you could move your code to the show action as that'd work even though it doesn't work inside the layout.

Rails js.erb response not sending locals to Haml partial

I realize this is similar to some other questions, but I have been through a fair number of those and I think I'm doing what they suggested, but my code is still not working.
So, as the title says, I'm attempting to load a partial from a js.erb file (in response to an AJAX call.) However, it is not working correctly.
full_list.html.haml:
=link_to(test_path(#work), id: "privacy-button", remote: true) do
= render "privacy_button_content", locals: {:show_others => #work.show_others}
_privacy_button_content.html.haml:
-if locals[:show_others] == false
-test_string = "twas false"
-else
-test_string = "twas true"
%p = test_string
works_controller.rb:
def test_function
#work.model_function
respond_with(:layout => false)
end
test_function.js.erb:
$("#privacy-button").html("<%= escape_javascript render(:partial => 'privacy_button_content', locals: {:show_others => #work.show_others}) %>");
So the full_list has privacy_button, which is rendering the partial, and the response to clicking the #privacy-button should be to modify something in the controller, and get the response.js.erb.
This works correctly on page load (so passing the local to the partial does work,) but whenever I run the AJAX call I'm getting
(undefined local variable or method `locals' for #<#<Class:0x00000005006338>:0x000000068481f8>):
Any help would be appreciated.
Update _privacy_button_content.html.haml as below:
-if show_others == false
-test_string = "twas false"
-else
-test_string = "twas true"
%p = test_string
When you pass show_others in locals hash, a local variable would be created for you named show_others. You can access it as show_others in the partial and not locals[:show_others].
Refer to Passing local variables in Rails Guides.
Apply Kirti Thorat's change and then change
= render "privacy_button_content", locals: {:show_others => #work.show_others}
for
= render "privacy_button_content", show_others: #work.show_others
Also remember that views should not have logic, it should be in a helper or in a decorator
BTW: I think %p = test_string should be %p= test_string
So, I've figured it out. It seems that specific error I was getting had to do with the render syntax when working when haml (I got the same issue when I specified render :partial from the view, so it wasn't unique to the js.erb.)
The code in partial.js.erb now looks like:
$("#privacy-button").html("<%= escape_javascript render("privacy_button_content", :locals => {:show_others => #work.show_others}) %>");
As you can see, the main difference is having render "works_group_list" rather than render( partial: => "works_group_list". As I said, I believe this may be related to my views being written in Haml, though it should be noted that the render(partial:...) syntax does work when not attempting to pass local variables from a js.erb.
I was also getting some little issues because I kept referring to something as #my_element in the js when in the html it was #my-element. So if you're encountering this issue, checking your spelling (for the thirtieth time) never hurts.
Edit:
Just a note, as others have pointed out using the locals hash is not mandatory. So the line of code could instead be
$("#privacy-button").html("<%= escape_javascript render("privacy_button_content", :show_others => #work.show_others ) %>");
This will work as long as you update your partial appropriately (referring to var instead of locals[:var]).

Rails: Calling Render From Within a Generator

I've just started experimenting with generators. In one of my generated view templates, I want to call render like so:
index.js.slim
transition("#main", "<%= escape_javascript(render 'index') %>");
When I try using the generator, I get this error:
(erb):1:in `template': undefined method `render' for #<Slim::Generators::ScaffoldGenerator:0x000000041b2a20> (NoMethodError)
Is Rails really incapable of calling render from within a generator? Or am I doing something wrong?
Railscast 218 goes into more detail:
The first thing to note is that because we’re using the template
method, all of the erb tags in the code will be executed when the
generator runs. If we want to include any erb in the generated file
we’ll have to escape the percent sign at the beginning of each erb tag
and we’ve done that for most of the erb code above.
In this instance:
transition("#main", "<%= escape_javascript(render 'index') %>");
should become:
transition("#main", "<%%= escape_javascript(render 'index') %>");
All it needed was an extra % to escape the erb.

Resources