rails and ajax request - ruby-on-rails

I have started to learn rails and javascript.
How i canmake properly ajax request to rails controller with jquery?
I write in js file
$.get('http://localhost:3000/take/show',{},function(s){
alert(s);
},'text');
in controller:
class FirstController < ApplicationController
def show
render :json => "Hi!"
end
end
but instead i see only blank alert dialog. What i have done wrong? In all tutorials i see thatthe URL in $.get should be like this "take/show" but it would not work in my case, so why?

Related

Can I render rails welcome page from my controller?

When I want to show default welcome page by routes.rb,
I can add route like this:
root "rails/welcome#index"
Then, I want to render the same template in my controller out of curiosity.
The template is in rails/railties/lib/rails/templates/rails/welcome/index.html.erb
I thought `render "controller/action" works for my own files,
but it doesn't seem to work for built-in files.
def index
render "rails/welcome/index" # This shows error `Missing template rails/welcome/index`.
end
So, Is there a handy way to render built-in template?
Yes you can render the rails welcome page from your controller by using the Rails::WelcomeController
class WelcomeController < Rails::WelcomeController
end
Don't define the index method in WelcomeController. Rails will pick the index method of Rails::WelcomeController and will render the default welcome page.

How to properly get an AJAX request to React from Rails

I'm fairly new to Rails, although I generally understand the structure/how it works. Side-note, my goal here is to have 1 javascript import tag in a views/home/application.html.erb that will import a single React file, which will then import the rest of my components in a tree-like structure. I'm used to this method because of my experience with Express so please let me know if this is not the standard way of doing things with Rails.
The current issue I'm facing however is that I can't/don't know how to get my Rails controller to send my instance variable as a response to my axios request. I'm expecting my browser to console.log('TESTING MY RAILS ROUTE'), but rather it's logging the entire HTML response.
Index.jsx (in javascript/components)
import React from "react"
import ReactDOM from 'react-dom'
import axios from 'axios'
class Index extends React.Component {
componentDidMount() {
axios.get('/login')
.then(res => {
console.log(res.data)
})
}
render() {
return (
<div>
<h1>Testing Axios</h1>
</div>
)
}
}
export default Index
config/routes.rb
Rails.application.routes.draw do
get 'welcome/index'
resources :login
root 'welcome#index'
end
controllers/login_controller.rb
class LoginController < ApplicationController
def index
#test = 'TESTING MY RAILS ROUTE'
end
end
index.html.erb (in views/welcome)
<%= react_component('Index') %>
You need to configure your Rails controller to respond with json as it is currently responding with HTML type response.
Since you are using React with Rails, I'm assuming that you want your Rails API to always return JSON for React to render.
Using the responders gem can help simplify this implementation, and have less code in your controllers.
Add gem 'responders' to your Gemfile.
Also, identify the login resource in your routes.db to be json by default, like so:
resources :login, defaults: {format: :json}
Now apply this change at the controller level to always respond with JSON. Add respond_to :json at the top of your controller. Then use respond_with in your controller actions. respond_with will render json in all actions of your controller, as long as respond_to :json is defined at the top.
class LoginController < ApplicationController
respond_to :json
def index
#test = 'TESTING MY RAILS ROUTE'
respond_with #test
end
end
Alternatively, you can also respond with json for an individual controller action only, by using respond_to within the controller action.
Rails has a convention that you need to choose the format to respond to if it's not the default. By default, Rails controller actions respond to html requests.
You should be able to configure this controller action to respond to both html and Ajax requests by adding the following code.
def index
#test = 'TESTING MY RAILS ROUTE'
respond_to do |format|
format.js json: #test, status: :ok
format.html
end
end

Get html code of erb template in controller

I have home_controller and there are [:index, :process_img] actions within.
I need to get the whole html source of :index action from the action :process_img. Need to access that code in controller.
class HomeController < ActionController::Base
def index
end
def process_img
index_html_code = "the html source of index action should be here"
end
end
How can I achieve that? Thanks in advance!
You can use render_to_string (renders according to the same rules as render, but returns the result in a string instead of sending it as the response body to the browser):
render_to_string :index
Although I think render_to_string is an idiomatic option here's a way to do it which would work in plain ruby as well:
ERB.new(File.read "app/views/home/index.html.erb").result binding

Rails Override Render

Is it possible to override Rails' render behavior for :html responses? I'd like to always render the same template (ignoring the magic view finding).
I'm writing a single page app, and this seems like it should be possible...basically if it's requested as :json it should render JSON, but if it's requested as :html it should pass the data on to the same view no matter what (where it will be rendered as JSON in the body).
Try to delete the yield part on your application.html.erb, then you will alway get the application.html.erb without any partials.
What if you define one single view and then after every action on every controller you render that view? Like this:
app/controllers/home_controller.rb
class HomeController < ApplicationController
def home
end
end
app/views/home/home.html.erb
<!-- Whatever html code and script tags here -->
app/controllers/another_controller.rb
class AnotherController < ApplicationController
def action
render "home/home"
end
end
You could even define an after_filter
Edit
I tried this and it works. The after filter doesn't seem to work though.
Why not pass the JSON data as an instance variable?
controller
#json_data = whatever_model.to_json
application.html.erb
<script>
<%= #json_data %>
</script>

How can I debug/test a json response from my rails controller?

I have written a simple jquery response in my rails 3 controller, I just want to test to see the result this returns (not automated testing).
My code looks like this:
class AppointmentsController < ApplicationController
def jsonlist
#appointments = Appointment.find(:all)
render :json => #appointments
end
Can I access this from a URL like: http://localhost:3000/appointments/jsonlist?
When I try, I get this error:
Couldn't find Appointment with
ID=jsonlist
The error you're getting does not appear to come from that action, it appears to be a conflict in your routes for whatever you have defined as your show action. Try defining your route for jsonlist before you define your route for show.
to debug a json response from your controller
render json: JSON.pretty_generate(JSON.parse(#appointments.to_json))

Resources