Reading a JSON object in Ruby on Rails - ruby

I'm a Ruby on Rails beginner and I'm trying to convert a static website I've made into Rails app where I can store customers and quote data. I'm trying to do this as a RESTful API where my site sends a JSON object containing the customer's information. I check to see if the email in the JSON object matches any of the emails I have in my database and if it does I send back the id of that customer. If not then I create a new customer and send back that id. The problem I'm having is that no matter how I write it, my rails app is not reading the JSON data, so if I have nothing in my database it creates a customer with all null attributes and when I run it again it goes "Oh, I have customer with a null email" and returns that customer.
{
"fname": "William",
"lname": "Shakespeare",
"email": "wshakespeare#test.com",
"bname": "MyCompany",
"primary": "555-555-5555",
"secondary": ""
}
Here's an example of my JSON object.
Here's how my controller is looking:
class CustomersController < ApplicationController
skip_before_action :verify_authenticity_token
wrap_parameters format: [:json, :xml, :url_encoded_form, :multipart_form]
def create
#query = Customer.where(:email === params[:email])
if #query.empty? == true
redirect_to action: "new", status: 301
else
#theid = #query.first.id
render json: {status: 'SUCCESS', message: 'Existing customer', theid:#theid}
end
end
def new
Customer.create(fname: params[:fname], lname: params[:lname], email: params[:email], bname: params[:bname], primary: params[:primary], secondary: params[:secondary])
render json: {status: 'SUCCESS', message: 'New customer', theid: Customer.last.id}
end
Any help would be greatly appreciated. Thanks.

Related

Speed up Ruby class to avoid requests to JIRA and Slack API

My, pure Ruby, class pull out user names from Jira API to convert it into email address and pass these email addresses to another class based on which Slack ID is extracted.
module Request
class GetUser
def call
setup_email
end
private
def setup_email
devops_email = dev_role['actors'].map { |user| "#{user['name']}#example.com" }
devops_email.each do |email|
::Slack::GetUserId.new(email: email).call
end
end
def dev_role
HTTParty.get('https://company_name.atlassian.net/rest/api/3/project/1234/role/1234',
basic_auth: { username: 'user', password: 'pass' },
headers: { 'content-type' => 'application/json' })
end
end
end
Because above class will be called every day (AWS Lambda schedule), I want to speed up the class. What should I use to achieve that? Should I use some database (Dynamodb probably?) to save user data (userID and user email) and make a query to check if the data (e.g. user name) has changed?
Or maybe should I change some implementation and leave these requests without saving data to the database?

ActiveModel serializer ignores root key when posts or post is empty or nil

I am using active model serializer V0.10.0 with Rails 5 api only application. During implementation I noticed the AMS is completely ignoring the root key when the posts/post is empty or nil respectively. This behavior actually breaks my mobile app as it always expects root key data in all response.
So what I want to achieve here is no matter what I always want data as root element of my Rails app response for all requests.
Response for SHOW API when the post is empty
SHOW render json: #post, root: 'data'
Expected
{
"data": {}
}
Actual
null
Response for INDEX API when the posts are empty
INDEX render json: #posts, root: 'data'
Expected
{
"data": []
}
Actual
{
"posts": []
}
class ApplicationSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
ActiveModelSerializers.config.adapter = :json
def host
Rails.application.secrets.dig(:host_url)
end
end
class PostSerializer < ApplicationSerializer
attributes :id
has_many :comments
end

How to get id from post route in Sinatra

I have a factory that is creating a student. All of the required fields are being filled in and created in the factory. When I post a new student, I am never getting that student, just the one created in the factory? How Can I get the id of the new student from the POST?
students.rb
FactoryGirl.define do
factory :student do
sequence(:id)
sequence(:first_name){|n| "Tom"}
sequence(:last_name) {|n| "Dick"}
sequence(:password) {|n| "test"}
sequence(:email){ |n| "person#{n}#example.com" }
school
end
end
student_spec.rb
require File.dirname(__FILE__) + '/spec_helper'
describe 'admin' do
before :all do
#student=FactoryGirl.create(:student)
end
it 'should save student information' do
params={
post:{
first_name: 'Abraham',
last_name: 'Lincoln',
address: '1400 Pennsylvania Ave.',
city: 'Washington',
state: 'D.C.',
zip: '11111',
email: 'alincoln#whitehouse.gov',
password: 'I cant tell a lie',
major: 'Law',
level: 'Graduate',
employment: 'President',
participation: 'Yes',
participation_research: 'No',
what_doing_now: 'Watching a Play',
ethnicity: 'White',
eth_other: 'none',
education_level: 'Doctorate',
hometown: 'Springfield, IL',
twitter_handle: '#TheRealAbe',
facebook_url: 'therealabe',
prior_education: 'None',
prior_AS: 'None',
prior_BS: 'None',
prior_MS: 'None',
prior_Other: 'None',
awards_honors: 'Ended Civil War',
scholarships: 'Full',
other_inbre_funding: 'yes',
deleted: 'false'
}
}
post '/admin/students/add/', params, {'rack.session'=>{student_id:#student.id, admin_authorized:true}}
updated_student = Student.get(#student.id)
expect(updated_student.first_name).to eql('Abraham')
#expect(updated_student.last_name).to eql('Dick')
#expect(updated_student.address).to eql('1400 Pennsylvania Ave.')
end
end
I can't know for certain without seeing the route, but it seems to me that you are calling POST twice, once in the route, and once within the params hash. However, without seeing your routes, I can't be sure if that's an issue.
Another thought comes from reading your spec. Are you attempting to create a new student(POST) or are you attempting to edit the student? If you are attempting to edit an existing student, this should probably be referring to a separate route, PUT or a PATCH by RESTful conventions. As was mentioned above, a POST route does not need an id, precisely because it is creating a new student, which is where it will create the id, and the id is set by the database, not manually.
a reference to the above: http://guides.rubyonrails.org/v2.3.11/routing.html
I hope this at least points in the right direction. :D

How to fetch a document by its ID in elasticsearch rails

I see in the elasticsearch docs you can fetch a document by its ID. Is there any equivalent in elasticsearch rails? I'm feeding by API with "as_indexed_json" and it's a somewhat expensive query, I'd like to return ths JSON straight out of elasticsearch in my API.
You can fetch a particular document from a given index by id with the get method on Elasticsearch::Transport::Client. The get method expects a single hash argument with keys for the index you want to fetch from and the id of the document you want to fetch.
So, all together you need 3 things:
A client object
The name of the index
The id of the document (i.e. your model id)
client = YourModel.__elasticsearch__.client
document = client.get({ index: YourModel.index_name, id: id_to_find })
Here how you can accomplish it.
This is from controller action and works well for me.
def show
client = Elasticsearch::Client.new host:'127.0.0.1:9200', log: true
response = client.search index: 'example', body: {query: { match: {_id: params[:id]} } }
#example = response['hits']['hits'][0]['_source']
respond_to do |format|
format.html # show.html.erb
format.js # show.js.erb
format.json { render json: #example }
end
#records = Example.search(#example['name']).per(12).results
end

Api errors customization for Rails 3 like Github api v3

I am adding an API on a Rails3 app and its pretty going good.
But I saw the following Github api v3 at http://developer.github.com/v3/
HTTP/1.1 422 Unprocessable Entity
Content-Length: 149
{
"message": "Validation Failed",
"errors": [
{
"resource": "Issue",
"field": "title",
"code": "missing_field"
}
]
}
I liked the error messages structure. But couldn't get it to reproduce.
How can I make my apis to make the response like it?
You could quite easily achieve that error format by adding an ActionController::Responder for your JSON format. See http://api.rubyonrails.org/classes/ActionController/Responder.html for the (extremely vague) documentation on this class, but in a nutshell, you need to override the to_json method.
In the example below I'm calling a private method in an ActionController:Responder which will construct the json response, including the customised error response of your choice; all you have to do is fill in the gaps, really:
def to_json
json, status = response_data
render :json => json, :status => status
end
def response_data
status = options[:status] || 200
message = options[:notice] || ''
data = options[:data] || []
if data.blank? && !resource.blank?
if has_errors?
# Do whatever you need to your response to make this happen.
# You'll generally just want to munge resource.errors here into the format you want.
else
# Do something here for other types of responses.
end
end
hash_for_json = { :data => data, :message => message }
[hash_for_json, status]
end

Resources