Recive JS object and fetch data from database - ruby-on-rails

I am using Angular in frontend and I am trying to send object such as:
obj = {
"foo" : "1",
"bar" : 2,
"baz" : 3
}
And when Rails recives this object, it should send back data from database depending on these parameters. This is my current method to create API:
def index
#tickets = Ticket.select(
'id',
'departure_date',
'departure_country',
'departure_country_tag'
)
render status:200, json: { tickets: #tickets}
end
However this fetches all data from database. I only want to fetch data that matches parameters from the object.
Any suggestion on how to do this properly?

Select allows you to specify the attributes to be returned. You need to add a clause to that query with the values from the front end.
#tickets = Ticket.select(
'id',
'departure_date',
'departure_country',
'departure_country_tag'
).where(foo: obj["foo"], bar: obj["bar"], baz: obj["baz"])
If you look in the console you'll see how the data is being passed and you can amend the active record query accordingly.

Related

How to save value of JSON data to db in rails?

I need to store json data to database, data being fetched from 3rd party api.
sample of json:
[{ "name"=>"test", "number"=>"1234", "email"=>"test#t.com"},
{ "name"=>"user", "number"=>"5678", "email"=>"yser#t.com"}]
Model contains: username, number_phone, y_email
I want to store name in username and number in number_phone.
Fetching the data:
rdb = RestdbApi.new
body = rdb.call
Updated
Need store all data json not first element only
Data json change continuously need save continuously
As per the description shared if I am assuming it right, you need to fetch values from json and save it in the respective columns in database.
For the same, suppose you have a json(let's name it as result_json), as mentioned in the post:
rdb = RestdbApi.new
body = rdb.call # [{ "name"=>"test", "number"=>"1234", "email"=>"test#t.com"}]
result_json = JSON.parse(body)
Now suppose you have a user class which is mapped to the db for saving respective values, then
user = User.new
user.username = result_json[0]["name"]
user.number_phone = result_json[0]["number"]
user.save # note that this line will map the records in the User instance to the database.
I'd do something like this
rest_db_api = RestdbApi.new
user_records_from_api = JSON.parse(rest_db_api.call)
(I will assume that user_records_from_api will now contain an array of hashes, as follows:
[{ "name"=>"test", "number"=>"1234", "email"=>"test#t.com"},{ "name"=>"user", "number"=>"5678", "email"=>"yser#t.com"}]
you can then just iterate over this hash and create a record for each (I am assuming that your model is called User)
user_records_from_api.map(&:with_indifferent_access).each do |attribues|
User.create!(
username: attributes[:name],
number_phone: attributes[:number],
y_email: attributes[:email]
)
end
note: the with_indifferent_access method that I used is just a handy thing provided by the rails framework that allows you to have a hash with string keys, and access them using symbols (or vice-versa) - ActionController::Parameters (in rails) uses this
If you already have everything setup to get your response you can do something like this:
response = [{ "name"=>"test", "number"=>"1234", "email"=>"test#t.com"}]
YourModel.create(
username: response[0]["name"],
number_phone: response[0]["number"],
y_email: response[0]["email"]
)
The above shows you how to access an index for the response that you displayed, then creating your object with the response attributes. If you are expecting to have multiple in the response, you should use a loop and do something similar:
response = [{ "name"=>"test", "number"=>"1234", "email"=>"test#t.com"}, { "name"=>"test", "number"=>"1234", "email"=>"test#t.com"}]
response.each_with_index do |_, i|
YourModel.create(
username: response[i]["name"],
number_phone: response[i]["number"],
y_email: response[i]["email"]
)
end
Hope this helps!
You can use .find_or_create_by, to not duplicate the data. LINK
rdb = RestdbApi.new
body = rdb.call
body.each do |data|
# YourModel: make sure to change to yr own model name
YourModel.find_or_create_by(email: data["y_email"])(
username: data["name"],
number_phone: data["number"],
y_email: data["email"]
)
end

Convert field from integer to string in one rails Active Record relation before sending json

In my Rails 4 app, I actually send an active record relation in JSON with:
[...]
wine['varietals'] = record.varietals
#wines << wine
format.json { render :json => { :success => "OK", :items => #wines } }
[...]
wine['varietals'] is an array of AR relations. My problem is the varietal model contains a field named grape_id that is an integer. I need to send it in string for my WS. I don't want to make a custom conversion to JSON just for this field.
How to force this field to be string before the automatic JSON conversion ? If possible I don't want to make an array of hashes and keep the AR style with dot: model.field
wine['varietals'].each do |varietal|
varietal.grape_id.to_s
end
Of course this doesn't work.
All Rails models have an as_json method that gets called when rednering the model to JSON. You can override this method within your models to set up custom JSON formatting. In your case, you may want to add something like this to your Wine model:
def as_json(opts = {})
json = super(opts)
json["grape_id"] = self.grape_id.to_s
json
end
The method gives you the default model JSON when you call the super method and set it to the json variable, then stringifies grape_id and sets it in the JSON, and finally returns the updated JSON.
Now, any time a controller returns a JSON version of single Wine model, or an association of multiple Wine models, the JSON will be formatted through this updated method and the grape_id will be stringified every time.

accessing multiple values from hash ruby on rails

This code snippet
room = Room.find(roomId)
returns a single column from room table, the returned value contains multiple attributes, like id, name, description, duration.
I want when coding
render json: room
to return only duration and name.
Do i have to write something like that
render json: room[:duration, :name]
query that will only give you the attributes that you want :
room = Room.select(:id, :duration, :name).find(room_id)
You can use the only option of as_json to include only certain attributes.
render json: room.as_json(:only => [:duration, :name])
You're slightly incorrect when you say Room.find(roomId) returns a "single column from the room table". It actually returns a single row.
Anyway, there are a few ways you can do this.
A good starting point is to use the .attributes method on a model to convert it to a Hash.
So for example say you have a user with a name, email, and id columns in the database. You can call user.attributes to get
{ "name" => "max", "email" => "max#max.com", "id" => 5 }.
you can select just the name and email with
user.select { |k,v| k.in?("name", "email") } and then call to_json on the result.
To avoid having to write custom to_json code for each controller response, you can overwrite .attributes in the model. Say my User table has a password column that I never want to expose in my API:
class User
def attributes
super.reject { |k,v| v.in?("password") }
end
end
Then, if you need to return a list of users as JSON:
render json: { users: #users.map(&:attributes) }.to_json, status: 200
The answer by Pavan will work as well, by the way.
Another approach is to use jbuilder and create json "views" for your records.

Rails activerecord returning wrong results

I am developing a simple rails app and I have a custom method that returns the last created column details
def getid
#b_id = params[:bid]
#log_id = Log.where("bid = ?",#b_id).last.to_json
respond_to do |format|
format.html{render :text => #log_id}
format.json{render :json => #log_id}
end
end
The column runs the following query in the backend
Log Load (0.2ms) SELECT `logs`.* FROM `logs` WHERE (bid = 'B01') ORDER BY `logs`.`logid` DESC LIMIT 1
The corresponding column values are id:3, logid:20002
The json returned is {u'id' : u'20002, u'logid' : u'20002'}
My questions:
Why is rails adding u to every JSON element?
Why is id returned as 20002 instead of 3? (id is auto increment and is a unique key, logid is primary key)
EDIT:
I found out that the character u is being added on the python side, as they are unicode strings and got rid of it as shown here
You don't need to call to_json on the object in this line
#log_id = Log.where("bid = ?",#b_id).last.to_json
Just the original object is okay.
#log_id = Log.where("bid = ?",#b_id).last
Because when you call render json: #obj there will be an action to convert the obj to json. No need duplication.

Read a JSON document and create a new one in Rails

How can I read everything inside a JSON document and create another one with new names?
I can't find something that will help me create a new JSON file in an easy way.
Edit:
I am retrieving a ton of data in JSON format from a MongoDB database (as an array [{"xxx": "zz"}, ... ]). What I need is to cycle trough each document, each field and create a new JSON document using those fields.
thanks
Here's the gist of what you want:
#keys = {
"old" => "new",
"foo" => "bar"
}
def rename_key(pair)
old_key = pair.keys.first
{ #keys[old_key] => pair[old_key] }
end
pairs = ActiveSupport::JSON.decode(json)
pairs.map! { |pair| rename_key(pair) }
new_json = pairs.to_json
Obviously, you'd want to turn this into a class or two. Note that I made the assumption that all data from Mongo was in the form of simple key => value pairs, based on your description.

Resources