Ruby soap4r build headers - ruby-on-rails

Again with the soap.
I am trying to build a header using soap4r that is supposed to look like this
<SOAP-ENV:Header>
<ns1:UserAuthentication
SOAP-ENV:mustUnderstand="1"
SOAP-ENV:actor="http://api.affiliatewindow.com">
<ns1:iId>*****</ns1:iId>
<ns1:sPassword>*****</ns1:sPassword>
<ns1:sType>affiliate</ ns1:sType>
</ns1:UserAuthentication>
<ns1:getQuota SOAP-ENV:mustUnderstand="1" SOAP-
ENV:actor="http://api.affiliatewindow.com">true</ns1:getQuota>
</SOAP-ENV:Header>
What I have done is created a header derv. class
AffHeader < SOAP::Header::SimpleHandler
Created a UserAuthentification element.
def initialize
#element = XSD::QName.new(nil, "UserAuthentification")
super(#element)
end
And return a hash
def on_simple_outbound
self.mustunderstand = 1
{ "iId" => ID, "sPassword" => PASSWORD, "sType" => "affiliate" }
end
How can I make my header look like I want further. How do I add the actor for example.
I am going to keep searching on this, any Help is very appreciated.
Thank you

In SOAP4R, the target_actor attribute is read only but you can add a new method like:
def target_actor= (uri)
#target_actor = uri
end
and in your on_simple_outbound method, you can call target_actor with your uri like so:
def on_simple_outbound
self.mustunderstand = 1
self.target_actor = "http://api.affiliatewindow.com"
{ "iId" => ID, "sPassword" => PASSWORD, "sType" => "affiliate" }
end
E.g.
irb(main):003:0> h = AffHeader.new
=> #<AffHeader:0x3409ef0 #target_actor=nil, #encodingstyle=nil,
#element=#<XSD::QName:0x1a04f5a {}UserAuthentification>,
#mustunderstand=false, #elename=#<XSD::QName:0x1a04f5a {}UserAuthentification>>
irb(main):006:0> h.on_simple_outbound
=> {"sType"=>"affiliate", "sPassword"=>"secret", "iId"=>"johndoe"}
irb(main):007:0> h
=> #<AffHeader:0x3409ef0 #target_actor="http://api.affiliatewindow.com",
#encodingstyle=nil,
#element=#<XSD::QName:0x1a04f5a {}UserAuthentification>,
#mustunderstand=1, #elename=#<XSD::QName:0x1a04f5a
{}UserAuthentification>>

Related

HTTParty Google maps directions between origin and destination.

My goal: http://maps.googleapis.com/maps/api/directions/json?origin=montreal&destination=toronto&sensor=false
My class:
class GoogleMap
include HTTParty
base_uri 'http://maps.googleapis.com'
attr_accessor :origin, :destination
def initialize(service, page)
#options = { query: {origin: origin, destination: destination} }
end
def directions
self.class.get("/maps/api/directions/json", #options)
end
end
Currently when I run this on the console:
irb(main):001:0> g = GoogleMap.new("montreal", "toronto")
=> #<GoogleMap:0x007fcaeeb88538 #options={:query=>{:origin=>nil, :destination=>nil}}>
irb(main):002:0> g.directions
=> #<HTTParty::Response:0x7fcaeeb60b00 parsed_response={"error_message"=>"Invalid request. Missing the 'origin' parameter.", "routes"=>[]...
Problem is: {:query=>{:origin=>nil, :destination=>nil}} origin and destination are nil.
I would like to know how I would achieve:
irb(main):001:0> g = GoogleMap.new("montreal", "toronto")
=> #<GoogleMap:0x007fcaeeb88538 #options={:query=>{:origin=>montreal, :destination=>toronto}}
And then when I run:
g.directions I get output of http://maps.googleapis.com/maps/api/directions/json?origin=montreal&destination=toronto&sensor=false
Thank you in advance.
I think you might want to change your
def initialize(service, page)
to
def initialize(origin, destination)
Or you can do g.origin = "montreal" and g.destination = "toronto" before you call g.directions

How to retrieve reference to AWS::S3::MultipartUpload with ruby

I have a rails app and in a controller action I am able to create a multipart upload like so:
def create
s3 = AWS::S3.new
bucket = s3.buckets["my_bucket"]
key = "some_new_file_name.ext"
obj = bucket.objects[key]
mpu = obj.multipart_upload
render json: {
:id => mpu.id
}
end
so now the client has the multipart upload id and she can upload parts to aws with her browser. I wish to create another action which will assemble the parts once they are done uploading. Something like:
def assemble
s3 = AWS::S3.new
bucket = s3.buckets["my_bucket"]
key = params['key']
bucket.objects[key].multipart_upload.complete
render json: { :status => "all good" }
end
This isn't working though. How do I retrieve a reference to the multipartUpload object or create a new one with the key or id so that I can call the "complete" method on it? Any insight is appreciated
I found this method in the documentation for the Client class and got it to work as follows:
client = AWS::S3::Client.new
# reassemble partsList
partsList = []
params[:partsList].each do |key, pair|
partsList.push pair
end
options = {
:bucket_name => 'my_bucket',
:key => params[:key],
:upload_id => params[:upload_id],
:parts => partsList
}
client.complete_multipart_upload(options)

Put Action in Lib to reduce line controllers and organize code Rails

I have a mode to put my code of controller in lib/ to reduce the code of the controller, I don't know if this works with my instance variables. I need some pass the action of controller to a lib/, to make a sample call require or include in action, some to organize my code more.
The action is:
def calculate_ship
pacote = Correios::Frete::Pacote.new
#products = buy_cart.line_items
#products.each do |p|
p.product.length = 16 if !p.product.length
p.product.weight = 0.3 if !p.product.weight
p.product.width = 11 if !p.product.width
p.product.height = 6 if !p.product.height
#item = Correios::Frete::PacoteItem.new :peso => p.product.weight, :comprimento => p.product.length, :largura => p.product.width, :altura => p.product.height
while p.quantity > 0
pacote.add_item(#item)
p.quantity -= 1
end
end
frete = Correios::Frete::Calculador.new :cep_origem => "95520-000",
:cep_destino => params[:cep],
:encomenda => pacote
servicos = frete.calcular :sedex, :pac
#pac = servicos[:pac].valor
#sedex = servicos[:sedex].valor
flash[:error] = servicos[:sedex].msg_erro
end
How to move this into lib/? I'm not accustomed to programing seriously with lib/, etc.
Instead, how about moving your logic into model & private methods. something like this?
Controller
def calculate_ship
Model.products = buy_cart.line_items
Model.set_defaults
#products = Model.items
servicos = calc_costs
#pac = servicos[:pac].valor
#sedex = servicos[:sedex].valor
flash[:error] = servicos[:sedex].msg_erro
end
private
def calc_costs
frete = Correios::Frete::Calculador.new :cep_origem => "95520-000",
:cep_destino => params[:cep],
:encomenda => pacote
frete.calcular :sedex, :pac
end
Model
attr_accessor :pacote, :products
def initialize
pacote = Correios::Frete::Pacote.new
end
def self.set_defaults
products.each do |p|
p.product.length = 16 if p.product.length.empty?
p.product.weight = 0.3 if p.product.weight.empty?
p.product.width = 11 if p.product.width.empty?
p.product.height = 6 if p.product.height.empty?
end
end
def self.items
products.each do |p|
#item = Correios::Frete::PacoteItem.new :peso => p.product.weight, :comprimento => p.product.length, :largura => p.product.width, :altura => p.product.height
while p.quantity > 0
pacote.add_item(#item)
p.quantity -= 1
end
end
end
PS: I didn't understand the code logic on what its actually doing as the complete code was not given & also the language looks like English but its not English. so, This is pseudo-code might have some errors but I hope this would give you atleast an idea on how you can move code from controller into the model/private methods. controllers actions should only be used to instantiate instance variables & call methods on objects. Remember, fat models & skinny controllers!.
Hope it helps
[edit]
F.A.Q
Q1. the Model in you code in controller can be someone Model? i talk this because this action is in my Cart controller, seems that the model should not be product?
Ans: I am not sure I fully understand what you mean by the Model in you code in controller can be someone Model? Are you asking that where this model code should do? Its actually simple, if this mode code is related to Cart, put it in Cart's model & if its related Product, put it in Product's Model.
Q2. this attr_accessor :pacote, :productsis for the pacote valid in all my app ? and the products to be able to pick up the product model Product?
Ans: attr_accessor :pacote, :productsis declares getter/setters. Please see What is attr_accessor in Ruby?

Using result of `JSON.decode` in Rails

So I have an action in my controller that does a get_response to an API:
def memeapi
require "net/http"
require "uri"
#meme = Meme.new(params[:meme])
url = "http://version1.api.memegenerator.net/Instance_Create?username=apigen&password=SECRET&languageCode=en&generatorID=#{#meme.memeid}&imageID=#{#meme.imgid}&text0=#{#meme.text0}&text1=#{#meme.text1}"
resp = Net::HTTP.get_response(URI.parse(url))
data = resp.body
# I want to convert it to the Rails data structure - a hash
result = ActiveSupport::JSON.decode(data)
end
Ok but now I want to get back the information, use it to create another object, but I cant even format the information I am getting, can anyone tell me what I am doing wrong, what am I missing?
I want to be able to access the information from the get_response...
Thank you.
This is the JSON structure
{"success":true,"result":{"generatorID":45,"displayName":"Insanity Wolf","urlName":"Insanity-Wolf","totalVotesScore":0,"imageUrl":"/cache/images/400x/0/0/20.jpg","instanceID":13226270,"text0":"push","text1":null,"instanceImageUrl":"/cache/instances/400x/12/12916/13226270.jpg","instanceUrl":"http://memegenerator.net/instance/13226270"}}
I dont want to save all the fields btw...
result will look something like this after JSON.decode in your code.
{
'success' => true,
'result' => {
"generatorID" => 45,
"displayName" => "Insanity Wolf",
"urlName" => "Insanity-Wolf",
"totalVotesScore" => 0,
"imageUrl" => "/cache/images/400x/0/0/20.jpg",
"instanceID" => 13226270,
"text0" => "push",
"text1" => nil,
"instanceImageUrl" => "/cache/instances/400x/12/12916/13226270.jpg",
"instanceUrl" => "http://memegenerator.net/instance/13226270"
}
}
You have a nested hash (hash as part of a hash) here, which you can access like this:
image_url = result['result']['imageUrl'] # => "/cache/images/400x/0/0/20.jpg"
What you actually want to do with this information, I cannot guess. Maybe you want to update the Meme object you created?
#meme.url = image_url

Using a method while looping through an array in ruby

I am using ruby-aaws to return Amazon Products and I want to enter them into my DB. I have created a model Amazonproduct and I have created a method get_amazon_data to return an array with all the product information. When i define the specific element in the array ( e.g. to_a[0] ) and then use ruby-aaws item_attributes method, it returns the name I am searching for and saves it to my DB. I am trying to iterate through the array and still have the item_attributes method work. When i don't define the element, i get this error: undefined method `item_attributes' for #Array:0x7f012cae2d68
Here is the code in my controller.
def create
#arr = Amazonproduct.get_amazon_data( :r ).to_a
#arr.each { |name|
#amazonproduct = Amazonproduct.new(params[:amazonproducts])
#amazonproduct.name = #arr.item_attributes.title.to_s
}
EDIT: Code in my model to see if that helps:
class Amazonproduct < ActiveRecord::Base
def self.get_amazon_data(r)
resp = Amazon::AWS.item_search('GourmetFood', { 'Keywords' => 'Coffee Maker' })
items = resp.item_search_response.items.item
end
end
Thanks for any help/advice.
I'm not familiar with the Amazon API, but I do observe that #arr is an array. Arrays do not usually have methods like item_attributes, so you probably lost track of which object was which somewhere in the coding process. It happens ;)
Try moving that .item_attributes call onto the object that supports that method. Maybe amazonproduct.get_amazon_data(:r), before its being turned into an array with to_a, has that method?
It's not quite clear to me what your classes are doing but to use #each, you can do something like
hash = {}
[['name', 'Macbook'], ['price', 1000]].each do |sub_array|
hash[sub_array[0]] = sub_array[1]
end
which gives you a hash like
{ 'name' => 'Macbook', 'price' => 1000 }
This hash may be easier to work with
#product = Product.new
#product.name = hash[:name]
....
EDIT
Try
def create
#arr = Amazonproduct.get_amazon_data( :r ).to_a
#arr.each do |aws_object|
#amazonproduct = Amazonproduct.new(params[:amazonproducts])
#amazonproduct.name = aws_object.item_attributes.title.to_s
end
end

Resources