Delayed Indexing in SunSpot solr still make Delete request on record save - sunspot-rails

The delayed indexing is working fine but on record save it sends some delete request to websolr... here in the log it shows
SOLR Request (14.3ms) [ path=# parameters={data: Message 547488, headers: {"Content-Type"=>"text/xml"}, method: post, params: {:wt=>:ruby}, query: wt=ruby, path: update, uri: http://index.websolr.com/solr/index/update?wt=ruby, open_timeout: , read_timeout: } ]
SOLR Request (12.4ms) [ path=# parameters={data: Message 547488, headers: {"Content-Type"=>"text/xml"}, method: post, params: {:wt=>:ruby}, query: wt=ruby, path: update, uri: http://index.websolr.com/solr/index/update?wt=ruby, open_timeout: , read_timeout: } ]
SOLR Request (9.7ms) [ path=# parameters={data: , headers: {"Content-Type"=>"text/xml"}, method: post, params: {:wt=>:ruby}, query: wt=ruby, path: update, uri: http://index.websolr.com/solr/index/update?wt=ruby, open_timeout: , read_timeout: } ]
These are the 3 requests that has been made against single message creation.
here is my search block
searchable :if => proc { |message| !message.user_messages.blank? } do
text :message_body do
CGI.escape(self.body || "")
end
text :subject do
CGI.escape(self.subject || "")
end
text :sender_name do
user.blank? ? "" : user.full_name
end
integer :users_ids, :multiple => true do
user_messages.map{|um| um.user_id}
end
time :created_at
end handle_asynchronously :solr_index
Please look in it asap,
thanks

To queue Sunspot deletes with DelayedJob, you should also add this line:
handle_asynchronously :remove_from_index

Related

on Update, if one of my param is blank, how to delete it from database?

I not sure how to delete a param in database, when updating and the param is left blank. Below is my current code-
def update
if !ABC.exists?(:id =>params[:id])
render json: { errors: #error }, status: 500
else
#abc = ABC.find(params[:id])
if #abc.update(permitted_update_abc_params)
render json: #abc, status: 200
else
render json: #abc.errors.full_messages, status: 500
end
end
end
You can simply run
obj.update_attributes(:field_name => params[:present_params], :field_name => params[:present_params], :field_name => params[:blank_params])
this blank param will replace database field value with existing blank value.

Validating JSON response using rest client

I am trying to use rest client in ruby to parse json but I am stuck how to validate the response (extract values from the response). Also I am trying to validate the valid response code(200) response.code does not work.
Following is the JSON response and Code that uses rest client to get it:
def self.call_legacy_transactions
get_response=RestClient::Request.execute(method: :get, url: 'URL', timeout: 15)
puts(get_response.body)
json_response = JSON.parse(get_response)
//Dont know how to get the values from response hash. Please suggest
end
JSON Response:
[
{
"value": "12345678912345",
"events": [
{
"transaction_id": 205,
"package_name": "",
"event_codes": [
465,
469,
471,
474,
410,
490,
1040
]
},
{
"transaction_id": 204,
"package_name": "",
"event_codes": [
465,
469,
474,
490
]
},
{
"transaction_id": 207,
"package_name": "",
"event_codes": [
465,
469,
471,
474,
490
]
}
]
}
]
I want the event code for each transaction for each value.
If you just want a flat list of event code integers, you can use:
json_response.flat_map do |value_data|
value_data[:events].flat_map do |event_data|
event_data[:event_codes]
end
end
UPDATE based on the comment "I want to extract event codes only where transaction id is 205":
If there could only ever be one item with that transaction ID:
json_response.flat_map do |value_data|
value_data[:events].find do |event_data|
event_data[:transaction_id] == 205
end[:event_codes]
end
If there could be many items with that transaction ID:
json_response.flat_map do |value_data|
value_data[:events].select do |event_data|
event_data[:transaction_id] == 205
end.flat_map do |event_data|
event_data[:event_codes]
end
end
You can call methods on the response to see the body, the response code, etc. More info in the README
Add to your code:
def self.call_legacy_transactions(tx_id = 205)
get_response=RestClient::Request.execute(method: :get, url: 'URL', timeout: 15)
puts(get_response.body)
# check if the response was successful
if get_response.code == 200
# need to parse the body
json_response = JSON.parse(get_response.body)
# the json response is an array of json objects
# we need to iterate over them and grab the value
# in the `events` key and iterate over those and
# select just the ones with the desired transaction id and
# get the value in each of the `event_codes` keys and
# then flatten all the sub arrays into one
event_codes = json_response.flat_map do |data|
data['events'].
select { |event| event['transaction_id'] == tx_id }.
flat_map { |event| event['event_codes'] }
end
event_codes # is now a list of just the event codes
end
end
With the above you can pass the transaction id into the method to get the event codes for any transaction e.g.
call_legacy_transactions 205

returning confirmation from paypal api sinatra

We are creating a paypal express checkout for a business using sinatra. I need to be able to get something returned form the API giving me confirmation that an order payment has gone through. Using this I want to pass a "PAID' value into a database that will match up with the customer. This is the code to set up my paypal express checkout (inside of shopping_cart.erb):
<script>
paypal.Button.render({
env: 'sandbox', // sandbox | production
// PayPal Client IDs - replace with your own
// Create a PayPal app: https://developer.paypal.com/developer/applications/create
client: {
sandbox: '',
production: ''
},
// Show the buyer a 'Pay Now' button in the checkout flow
commit: true,
// payment() is called when the button is clicked
payment: function(data, actions) {
// Make a call to the REST api to create the payment
return actions.payment.create({
// curl -v -X POST "https://api.sandbox.paypal.com/v1/payments/payment" \
// -H "Content-Type:application/json" \
// -H "Authorization: Bearer <Access-Token>" \
// -d '{"intent": "sale", "payer": {"payment_method": "paypal"} },
transactions: [
{amount: { total: '0.01', currency: 'USD' }}
],
redirect_urls: {
"return_url": "http://www.paypal.com/return",
"cancel_url": "http://www.paypal.com/cancel"
}
});
},
// onAuthorize() is called when the buyer approves the payment
onAuthorize: function(data, actions) {
// Make a call to the REST api to execute the payment
return actions.payment.execute().then(function() {
window.alert('Payment Complete!');
window.location.href = "../receipt";
document.getElementbyId("paypal-button-container").innerHTML = "<input type='hidden' name='clicked' value='paid'>"
});
}
}, '#paypal-button-container');
function endClicked(){
document.getElementbyId("paypal-button-container").innerHTML = "<input type='hidden' name='clicked' value='paid'>"
}
</script>
How do I got about getting a confirmation back and then pass something to the db? Here is the portion of my `app.rb that is dealing with it:
post '/receipt' do
#title = 'Receipt'
campaign_name = params[:campaign_name]
user = session[:user]
cart = session[:cart]
puts "this is the receipt"
db.exec("UPDATE orders SET payment_status = 'paid' WHERE campaign_name = '#{campaign_name}' AND customer_name = '#{user}'")
erb :receipt, :locals => {
:cart => session[:cart],
:campaign_name => session[:campaign_name],
:user => session[:user],
:message =>"Thanks for your order, here is a receipt you can print for your records."
}
end
get '/receipt' do
#title = 'Receipt'
campaign_name = params[:campaign_name]
user = session[:user]
cart = session[:cart]
clicked = params[:clicked]
puts "this is clicked '#{clicked}'"
# if clicked != ""
# redirect '/receipt'
# end
erb :receipt,:locals => {
:cart => session[:cart],
:campaign_name => session[:campaign_name],
:clicked => clicked,
:user => session[:user],
:message =>"Thanks for your order, here is a receipt you can print for your records."
}
end

No Matching Action Clause to Process Request error on HTTPoison.patch

From an elixir genserver process I am executing the post_metdata method to send a JSON HTTP Patch request to a Phoenix endpoint (on another server). The server continues to error indicating no matching clause showing the JSON link structure is not being included in the params based to the method. The id is included but not the passed data payload. Any suggestions on what appears to be the problem?
Client code
defp post_metadata(metadata, webhook) do
case HTTPoison.patch webhook, encode(metadata), [{"content-type", "application/json"}] do
{:ok, %HTTPoison.Response{status_code: 200} = response} ->
# Logger.debug response.body
Logger.debug "Successfully extracted and posted metadata for #{webhook}"
{:error, %HTTPoison.Error{reason: reason}} ->
Logger.warn "Unable to extract and post metadata for #{webhook}"
end
end
defp encode(metadata) do
%{
"link":
%{
"title": metadata.title,
"description": metadata.description
}
}
|> Poison.encode!
end
Phoenix Controller method expected, but not being matched
def update(conn, %{"id" => id, "link" => link_params}) do
link = Repo.get!(Link, id)
changeset = Link.changeset(link, link_params)
case Repo.update(changeset) do
{:ok, link} ->
render(conn, "show.json", link: link)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(Mini.ChangesetView, "error.json", changeset: changeset)
end
end
router.ex
defmodule Mini.Router do
use Mini.Web, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
plug Plug.Logger, log: :debug
end
scope "/", Mini do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
scope "/api", Mini do
pipe_through :api
resources "/links", LinkController, except: [:new, :edit]
end
end
Error logged to the console
[debug] ** (Phoenix.ActionClauseError) bad request to Mini.LinkController.update, no matching action clause to process request
(mini) web/controllers/link_controller.ex:39: Mini.LinkController.update(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{}, before_send: [#Function<1.42492691/1 in Plug.Logger.call/2>, #Function<1.42492691/1 in Plug.Logger.call/2>, #Function<0.111727833/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>], body_params: %{}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "PATCH", owner: #PID<0.438.0>, params: %{"id" => "12"}, path_info: ["api", "links", "12"], path_params: %{}, peer: {{127, 0, 0, 1}, 55369}, port: 4000, private: %{Mini.Router => {[], %{}}, :phoenix_action => :update, :phoenix_controller => Mini.LinkController, :phoenix_endpoint => Mini.Endpoint, :phoenix_format => "json", :phoenix_layout => {Mini.LayoutView, :app}, :phoenix_pipelines => [:api], :phoenix_route => #Function<4.107513407/1 in Mini.Router.match_route/4>, :phoenix_router => Mini.Router, :phoenix_view => Mini.LinkView, :plug_session_fetch => #Function<1.61377594/1 in Plug.Session.fetch_session/1>}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"content-type", "application/json, application/json"}, {"user-agent", "hackney/1.6.6"}, {"host", "localhost:4000"}, {"content-length", "58"}], request_path: "/api/links/12", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "5bggaasurlj1oe027nvmv5aiek0hq3k8"}], scheme: :http, script_name: [], secret_key_base: "YfnqjmBhsSJMF/TmhK6qpMnJl7mS0tIYHk1tZ/dZUA6d7KOdv2g/AOJUfWo8sulb", state: :unset, status: nil}, %{"id" => "12"})
(mini) web/controllers/link_controller.ex:1: Mini.LinkController.action/2
(mini) web/controllers/link_controller.ex:1: Mini.LinkController.phoenix_controller_pipeline/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.instrument/4
(mini) lib/phoenix/router.ex:261: Mini.Router.dispatch/2
(mini) web/router.ex:1: Mini.Router.do_call/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.phoenix_pipeline/1
(mini) lib/plug/debugger.ex:123: Mini.Endpoint."call (overridable 3)"/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/billc/dev/mini/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
I've executed a request mocking the JSON data structure using Insomnia with success. I sent both requests to Httpbin and compared. The only difference I can find is the Content-type has duplicate application/json entries for the request sent by HTTPoison. But, I can find no reason or option to prevention the duplicate value. Nor any reason why Phoenix would choke on it.
For an unexplainable reason, HTTPoison is adding duplicate 'application/json' values in the content-type header. Plug is choking on having multiple content-type values. I worked around the issue by adding a semi-colon to the end of the passed in header.
case HTTPoison.patch webhook, encode(metadata), [{"content-type", "application/json;"}] do
The ending semi-colon terminates the content-type value. HTTPoison only inserts a single 'application/json' value and Plug behaves normally.
Strange.

Insert json data to existing remote server in corona

How to post data to my own server. I can fetch data from it but can't add data .Code for fetch is below:
local function networkListener( event )
if ( event.isError ) then
print( "Network error!")
else
local json=event.response
local length=string.len(json)
json=string.sub(json, 50, (length-1));
jsonTable=JSON.encode(json)
local t = jsonTable
print(jsonTable)
-- Go through the array in a loop
for key in pairs(t) do
-- Here you can do whatever you like with the values
print(t[key]["AuthorID"])
print(t[key]["AuthorName"])
--print(t[key]["returnvalue3"])
end
end
end
local remoteFeed="http://www.xtremeesolutions.com/xesapps/webservice/readauthors.php"
network.request(remoteFeed, "GET", networkListener)
--And trying code to post data is
local function postData(e)
if (e.isError)then
print("Error ");
else
print("Error ".. e.response);
end
end
local params = {
body = query
}
network.request(remoteFeed, "POST",postData,params))
Above code not giving any error but also not inserting values.Please suggest me to solve this.
I think you should use "POST" instead of "GET", see the code below:
...
local remoteFeed="http://www.xtremeesolutions.com/xesapps/webservice/readauthors.php"
network.request(remoteFeed, "POST", networkListener, params)
Maybe you should also check this link http://docs.coronalabs.com/api/library/network/request.html at section: HTTP POST with custom headers
EDITED
the loop for handle post value should be:
if ( event.isError ) then
print( "Network error!")
else
...
for key in pairs(t) do
postData = t[key]["AuthorID"] .. "=" .. t[key]["AuthorName"]
end
local params = {}
params.body = postData
local remoteFeed="http://www.xtremeesolutions.com/xesapps/webservice/readauthors.php"
network.request(remoteFeed, "POST", networkListener, params)
end
those lines should be togather in else scope.