How to create dynamic id in elastic search client in Rails? - ruby-on-rails

I am trying to post data elk server using elastic search client.I need to pass dynamic id.Below the code I am using
require 'elasticsearch'
module PostDataToElasticsearchConcern
extend ActiveSupport::Concern
included do
helper_method :post_executions_to_elasticsearch
end
def post_executions_to_elasticsearch(username,mac_address,parametername)
json = {
"mac_address" => mac_address.to_s,
"parameter_name" => parametername.to_s,
"user_name" => username.to_s,
"time" => Time.now.utc.iso8601
}
postdata=json.to_s.gsub!("=>",":")
puts "JSON----------------------------"+postdata.to_s
client = Elasticsearch::Client.new url:"My Server:9200"
response = client.index(index: 'testingapp', body: json, id: '1')
end
end
Now I have passed id as 1. But id needs to be created dynamically.how to create dynamic id?.
Thanks

I am able to create dynamic id with below code.
response = client.index(index: 'testingapp', body: json)
Removing id will created dynamic id.

Related

Rails how to save data upon creation with an external API?

In my app for bike_rental_shops, I'm making it possible for these shops to manage their bike rentals.
Context
Bike rental companies also offer their bikes on website of external parties, therefore I'm connecting my Rails application with these external websites. I'm currently handling this in my controller when a user goes to the index page. Before loading the index page an API call is made to the external rental website and new bike rentals should be saved in the database.
Question
How to save only new rentals and not all rentals linked to a certain external rental website?
Current consideration
The only thing I can come up with is adding a database column with {external_website}_rental_id for a specific external website, so I can match them. However, this would mean that I need to add a seperate rental_id for every external rental website.
Code
rentals_controller.rb
def index
shop = Shop.find(params[:id])
request_rental_api
#bikes = shop.bikes
end
private
def request_rental_api
# set variables
base_url = "https://www.rentalwebsite.com"
url = "/rest/api/rentals"
token = 'TOKEN'
# init connection object
connection = Faraday.new(:url => base_url) do |c|
c.use Faraday::Request::UrlEncoded
c.use Faraday::Response::Logger
c.use FaradayMiddleware::FollowRedirects
c.adapter Faraday::Adapter::NetHttp
end
# send request
response = connection.get url do |request|
request.headers["Authorization"] = token
request.headers["Accept"] = "application/json"
end
bookings = JSON.parse(response.body['results'])
# check if rental is unique, and if so save it.
# Rental.create(????)
end
JSON output API
{
"next": null,
"previous": null,
"results": [
{
"activation_requested": false,
"id": 21664,
"slug": "rental-test"
#more information....
}
}]
you can create 2 columns
provider_rental_id id returned in response JSON
provider name of provider, to which request was made
Then to only create new records
rental_ids = bookings['results'].map { |r| r['id'] }
return if rental_ids.none?
existing_rental_ids = Rental.where(provider_rental_id: rental_ids, provider: 'Name of Provider').pluck(:provider_rental_id)
new_rental_ids = rental_ids - existing_rental_ids
new_rental_ids.each do |rental_id|
Rental.create(
provider: 'Name of Provider',
provider_rental_id: rental_id,
...
or if you are using rails 6 you can check upsert_all
Note: It does not instantiate any models nor does it trigger Active Record callbacks or validations.
Additionally try to move this into a background cronjob

How to update a couchdb document with Ruby

I have a Rails application with MYSQL backend. Upon saving data in MYSQL, it pushes some data to Couchdb using curl commands. However, I am unable to update that very same document. I dont know how query from couchdb and use _rev id to update. Here is how am creating and pushing a couchdb document.
require 'net/http'
require 'uri'
require 'json'
def push_to_couchdb
url = URI.parse("http://127.0.0.1:5984/m5fcash/100")
request = Net::HTTP::Put.new(url)
request.body = JSON.dump({
"fname" => "fname",
"lanme" => "lname",
"type" => "demo",
"facility" => "spectre"
})
req_options = {
use_ssl: url.scheme == "https",
}
response = Net::HTTP.start(url.hostname, url.port, req_options) do |http|
http.request(request)
end
end
This is how am trying to query the document and extract its _rev id
def get_couch_doc
uri = URI.parse("http://127.0.0.1:5984/m5fcash/100")
response = Net::HTTP.get_response(uri)
raise response.inspect
end
I expect raise response.inspect to gove a couchdb document from which I will exctract a _rev id. But all I get is #. How can I query a document in Ruby using curl??
It's not entirely clear to me from your code what you're trying to do, so I'll try to explain in general terms.
In order to read a specific document revsion, you need to use the rev=... query parameter. This is probably not what you want. In your get_couch_doc you can't have a request body. It looks like you're trying to fetch a document based on specific data in the body -- for this you need to create a secondary index, known as a view in CouchDB.
If you want to be able to query based on the lanme (maybe that should be lname?) field, you'd make a view where the map could look something like
function(doc) {
if (doc.lname) {
emit(doc.lname, null);
}
}
If you want to update a document, you need to do a PUT database/doc_id with the rev=.... query parameter on the URL.
CouchDB docs for the document API, and for views.

How to Consume SOAP with Savon in Rails app

I need to communicate to a service called ifthenpay via Soap using Savon on a Rails app that i'm working on.
The service generates payment references so users could pay on home banking or in cash machines.
The app needs to communicate to the service to see if the payment was made or not.
I'm using Savon and this is what i have so far in the checkout model(don't know if this is the right place to put the above code):
def self.check_status!
client = Savon.client(
wsdl: "http://www.ifthensoftware.com/IfmbWS/IfmbWS.asmx?WSDL",
endpoint: "http://localhost:3000",
namespaces: {"xmlns:ift"=>"https://www.ifthensoftware.com/"}
)
begin
response = client.call(:get_payments, message: check_status_hash)
rescue Savon::SOAPFault => error
#...
end
end
def self.check_status_hash
{
"ift:get_payments" => {
"ift:chavebackoffice" => { "ift:chavebackoffice" => "0000-0000-0000-0000" },
"ift:entidade" => {"ift:entidade" => "11202"},
"ift:subidentidade" => {"ift:subidentidade" => "202"},
"ift:dtHrInicio" => {"ift:dtHrInicio" => ""},
"ift:dtHrFim" => {"ift:dtHrFim" => ""},
"ift:referencia" => {"ift:referencia" => ""},
"ift:valor" => {"ift:valor" => ""}
}
}
end
I've an admin page where i need to list all the payments that have been made, so i can manage what was selled.
You can see the service operations here
What do i need to put in the controller and in the view for this to work?
I really appreciate your help, because i'm struggling with this for a long time.
From my point of view, and pardon me because I'm not very experienced with the use of savon, you are slightly overkilling this.
To start with, you are providing the client with a WSDL url, so what is the use of attaching a doubtfully necessary endpoint?
A namespace is, to my understanding, necessary, once again, in case there is no standard WSDl interface.
I would go, to start off, I would simply go for:
#client = Savon.client(wsdl: "http://www.ifthensoftware.com/IfmbWS/IfmbWS.asmx?WSDL")
Watch the #client instead of client. We need to assign the client to a variable that will be reachable throughout the entire process (request, process, response).
Next, you will need to prepare your request. Parsing the above url, there is a banch of methods. You are providing in your example getPayments request.
I will not use this space to tell you how to construct the hash, but the hash should look something like this:
request_hash = {
chavebackoffice: "0000-0000-0000-0000",
entidade: "11202",
subidentidade: "202",
dtHrInicio: "",
dtHrFim: "",
referencia: "",
valor: ""
}
To make the call to the api, you should simply do this:
#response = #client.call(:get_payments) do
message request_hash
end
And then, parse the #response. You will probably need to turn it to a hash first. Maybe something like this:
#data = #response.to_hash[:get_payments_response][:get_payments_result][:ifmb]
I hope this will help you enough. It should be more than enough.
Putting all up: Controller code, adapt to your need
before_action :set_client, only: [:get_payments, :other_actions_perhaps]
def get_payments
# params[:whatever] in case you post to #whatever object
# params without [:whatever] if you are using "GET" method
request_hash = {
chavebackoffice: params[:whatever][:chavebackoffice],
entidade: params[:whatever][:entidade],
subidentidade: params[:whatever][:subidentidade],
dtHrInicio: params[:whatever][:dtHrInicio],
dtHrFim: params[:whatever][:dtHrFim],
referencia: params[:whatever][:referencia],
valor: params[:whatever][:valor]
}
response = #client.call(:get_payments) do
message request_hash
end
# use this #data in your view
#data = response.to_hash[:get_payments_response][:get_payments_result][:ifmb]
end
def set_client
#client = Savon.client(wsdl: "http://www.ifthensoftware.com/IfmbWS/IfmbWS.asmx?WSDL")
end

How to retrieve a specific mailchip list by name

I'm very new to both rails and mailchip. I'm able to retrieve all my lists inside my controller with the below code
class EmailsController < ApplicationController
def new
#email = Email.new
#gbList = Gibbon::API.lists.list
puts "#gbList", #gbList
end
end
I can see all my lists in my console. What I'm trying to do is retrieve one of those lists via the name attribute. For example my list is called "My eList"
I tried doing:
#eList = Gibbon::API.lists.list(:list_name => "My eList");
But this still returns an array of all my lists.
Pass the list_name key-value pair as a member of the filters hash. See the Gibbon documentation on Fetching Lists for more info:
#eList = Gibbon::API.lists.list({:filters => {:list_name => 'My eList'}})

Is there a way to set the default namespace with Savon::Model?

Savon is stubborn in generating SOAP envelopes from WSDL's. It does it improperly and I see no way to fix it. It also takes the liberty of inserting the wsdl: namespace on everything for whatever reason.
The request I am building uses the tns: namespace. I'd love to be able to use Savon::Model, but right now I have to do:
client.request :tns, :function_name do
soap.body = { params }
end
Instead of something like:
super(params)
Making the request block in every function is tedious, and I have to define the function name every time instead of Savon automatically calling the correct function like what would happen in the ideal case. Right now my functions are looking like
def foo
client.request :tns, :foo do
...
end
Having to say "foo" twice seems ridiculous. Is there a way to set the default namespace for every request in a class that extends Savon::Model?
client = Savon.client do
wsdl "blah blah"
element_form_default :qualified
namespace_identifier :tem
env_namespace :soapenv
end
I am not sure if I understand your questions. I assume you are asking how to set the default namespace and wrap the request body in a function, so you don't need to write the request body every time. This code works for me, but I removed some irrelevant parts
class ExampleWS
EXAMPLE_WS_DEFAULT_NAMESPACE = "urn:example:request:1.0.0"
......
def getStockPrice( locale, stockId )
response = $client.request :get_stock_price do
soap.input = [
"ns1:getStockPrice",
{
"xmlns:ns1" => EXAMPLE_WS_DEFAULT_NAMESPACE #set default namespace here
}
]
soap.body = {
"locale" => locale,
"stockId" => stockId
}
end
end
......
end
......
# call the function
getStockPrice("en_US", 123 )
This works for me. It uses Savon 2, though:
class Soapservice
extend Savon::Model
client wsdl: "http://example.com?wsdl", env_namespace: :tns,
operations :get_resource, :put_resource
def :get_resource(id)
super(message: { id: id })
end
end
service = Soapservice.new
response = service.get_resource(1) #overwriting get_resource
# or
response = service.put_resource(message: { username: "luke", secret: "secret" })
(My example builds on the one from the official savon homepage)

Resources