What does this line of code means in ruby? - ruby-on-rails-4

Someone please give me a rough meaning of this code
render json: {:status => 1}

The render function in rails does the heavy lifting of rendering your application content for use by a browser or client. You can text, JSON, XML, html.erb and others. Now adding json after render will send everything in json format. Like following example will send user information in your response
#user = User.first
render json: #user
Same we can send text
render html: "<h1>Hi this is html</h1>"
or we want to send xml
render xml: #user
# or
render xml: {:status => 1}
Now second part is actual hash where you define status as a key and value is 1 you can create hash like
hash = Hash.new(status: 1)
render json: hash
This will send all user information in json format.
but your code is making content in directly inline
render json: {:status => 1}
# or
render json: {status: 1}
# or
render json: {name: 'my name', age: 23, status: 1}
But this is data being sent if we want to send status code we can use
render json: {:status => 1},

One of the formats, You can use it with Ajax requests

It means that it is returning json.
This is the returned value and you can use it the same way as you can use any json code:
{ status: 1 }

Related

Unexpected token P in JSON at position 0 when trying to return Excel spreadhsheet

I have an emberJS application where I can make a POST AJAX call to a Django backend. A function in Django creates an xlsx file for a bunch of queried items based on IDs coming in the POST request. It goes through the Django view function without any issues, but when the HTTP response is returned to ember, I get the error
SyntaxError: Unexpected token P in JSON at position 0
at parse (<anonymous>)
at ajaxConvert (jquery.js:8787)
at done (jquery.js:9255)
at XMLHttpRequest.<anonymous> (jquery.js:9548)
at XMLHttpRequest.nrWrapper (base-content:20)
I'm setting the response content type to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, so I'm unsure as to why its trying to read the response as JSON.
Python Code
file_path = '/User/path_to_spreadsheet/content.xlsx'
fsock = open(file_path, "rb")
response = HttpResponse(fsock, content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename="content.xlsx"'
return response
EmberJS Code
export default Controller.extend({
actions: {
storeProductId(products) {
let product_ids = []
products.forEach(function(product){
product_ids.push(product.id)
});
let adapter = this.store.adapterFor('product-export');
adapter.export_products(product_ids).then(function(response){
console.log(response)
}).catch(function(response) {
console.log('ERROR')
console.log(response)
})
}
}
});
Product-Export Adapter Code
export default ApplicationAdapter.extend(FormDataAdapterMixin, {
export_products(products) {
let url = this.buildURL('unified-product');
url = `${url}export/`;
return this.ajax(url, 'POST', { data: {'products': products} });
}
});
By default, Ember Data makes some assumptions around how things should be handled (including that you’ll be receiving JSON data back). Is there a reason you are using Ember Data instead of using a direct Ajax call to your backend? Seems like that would greatly simplify things here ...

Controller vs Request specs in Rails. How to do them properly?

So there's an argument that I'm reading about that says Controller tests should be unit tests of the controllers and Request specs should be more of an integration test that involves the router, the controller, and the response. That's the philosophy in the codebase that I'm working in. Given that, what's the best way to write both tests given that I have this controller:
class Api::WineController < ApplicationController
def show
wine = Wine.find(params[:id])
render json: { id: wine.id, varietal: wine.varietal }, status: :ok
rescue ActiveRecord::RecordNotFound
render json: { error: { message: "Wine not found") } }, status: :bad_request
end
end
So my request spec is the one that looks like a typical, integration-y controller test that most people write:
require 'rails_helper'
RSpec.describe "Wine API", type: :request do
describe '#get /api/wine' do
let!(:wine) { create(:wine) }
subject { get "/api/wine_invite_beta/wine_tokens/:id", params }
let(:params) {
{
id: wine.id
}
}
context "and the wine exists" do
it "returns back a JSON response of names" do
subject
expect(JSON.parse(response.body)).to eq("id" => wine.id, "varietal" => wine.varietal)
expect(response).to have_http_status(:ok)
end
end
context "and wine does not exist" do
it "returns back a JSON response of errors" do
subject
expect(JSON.parse(response.body)).to eq("error" => { "message"
....
end
end
end
end
So the request spec uses the http methods (:get is the one used), to hit the router which then hits the controller. This seems more like an integration test.
The controller test should do without the router and just test the class and its methods like I would test the model. Is that right? Do people agree? This is how I'm writing it:
require 'rails_helper'
RSpec.describe Api::WinesController, type: :controller do
describe "#show" do
let(:controller_instance) { described_class.new }
subject { controller_instance.show }
before do
allow(controller_instance).to receive(:params) { params }
end
let(:params) { { id: 1} }
context "and wine token exists for user" do
let!(:wine) { create(:wine) }
it "calls render with the wine token data" do
expect(controller_instance).to receive(:render).with(
json: {
id: wine.id,
varietal: wine.varietal
},
status: :ok
)
subject
end
end
Is that okay? I'm merely setting an expectation that a method is called within the controller because that seems like a command. That feels wrong though. The render method seems more like a query than a command and so perhaps I should be inspecting the state of the controller after render is called. Does anyone know how to do this?
More generally, what do people think of this approach to making controller vs request specs?

How to test that an API response has keys in RSpec

I have an endpoint that responds with an object's attributes + attributes that are added from an ActiveModelSerializer. I want to write a test that checks to see if the response has keys.
Let's hypothetically say that the object (say a tree) has these keys
expected_tree_attributes = [:height, :age, :color]
How do I write this test properly? Can I write:
subject { post :obtain_tree_info, { id: tree.id } }
response = JSON.parse(subject.body)
expected(response).to include(*expected_tree_attributes)
IS that... acceptable?
Please consider to use rspec-api-matchers gem
or airborne gem
With these you can do:
# api_matchers
response = JSON.parse(subject.body)
expect(response).to be_success
expect(response).to have_json_node(:height).with(tree.height)
expect(response).to have_json_node(:age).with(tree.age)
expect(response).to have_json_node(:color).with(tree.color)
# or
expect(response).to have_json_node(:age).with("123")
Airborne
describe 'sample spec' do
it 'should validate types' do
post '/api/v1/obtain_tree_info', {id: tree.id}
expect_json_types(height: :int, age: :int_or_null, color: :string)
end
end

How can I return a 404 JSON format in Rails 4?

I am new to Ruby. I am writing a Restful API application using Rails 4.
How can I return a 404 JSON not found string when the record is not found?
I found a number of posts but no luck, only for Rails 3.
In my controller I can caught the exception
def show
country = Country.find(params[:id])
render :json => country.to_record
rescue Exception
render :json => "404"
end
But I want a generic one to capture all the not found resources.
Use rescue_from. See http://guides.rubyonrails.org/v2.3.11/action_controller_overview.html#rescue
In this instance use something like:
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
private
def record_not_found(error)
render json: { error: error.message }, status: :not_found
end
end
Do:
def show
country = Country.find(params[:id])
render :json => country.to_record
rescue Exception
render :json => 404_json_text, :status => 404
end

Why does my Django request.method does not match POST

$.ajax({
type :'GET',
url : geturl(a),
// type: $(this).attr('method'),
dataType : 'json',
views.py:
if request.method=="POST":
if request.POST.get('monyrsubmit'):
monthform=MonthForm(request.POST)
if monthform.is_valid():
selected_month=monthform.cleaned_data["Month"]
selected_year=monthform.cleaned_data["Year"]
print selected_month
print selected_year
can i have both GET and POST requests in the type field of ajax. im using a form and only when the submit button is clicked im trying to display information based on the data submitted. if request.POST.get('monyrsubmit') does not work.
Help will be appreciated
It's very simple. You have to abstract the events.
function event_page_load() {
function ajax_request('GET')
}
function click_submit_button() {
function ajax_request('POST')
}
function ajax_request(type) {
$.ajax({
type : type,
......
......
})
}
You can also consider the follwoign general guidelines.
GET and POST should be used based on the type of the request to the server
- If you are reading the existing data(without modification) from the server, use GET
- if you are writing/modifying any data in the server, use POST
in jQuery, you can use these simple methods.
For GET requests
$.get(
url,
{param1: "value1", param2: "value2"},
function(responseText){
// todo ;
},
"html"
);
for POST requests
$.post(
url,
{param1: "value1", param2: "value2"},
function(responseText){
// todo ;
},
"html"
);
Make sure that you have disable the browser caching.
$.ajaxSetup ({
cache: false
});
In django side, you can use request.is_ajax() method to verify the ajax call and you can filter based on request.method property.
You can refer all the possible usages of AJAX with Djano at https://github.com/sivaa/django-jquery-ajax-exmaples