Create an object from within a script Ruby - ruby

I am attemping to create an object from a class. But the objects will be created when they are needed.. Code below a bit hard to explain
incoming_message = #message sent though inter webs
class Repeater
def initialize(username, ip)
#repeat incoming message to back to ip
end
end
incoming_message = Repeater.new(user, ip)
Now I can't do that Becuase incoming_message is not a constant.
How would I get around this?
EDIT:
To clear things up a bit. I do need to use this class to create multiple objects with diffrent names. The repeater is for a chat server where an incoming message from 1 user is taken in then sent back out all of the clients connected. Each new client that connects would have a object created with that specific IP address so that messages from others can be send to the client.
It would take in messages from the other users by everyone sending to the server on the same port read the message then write to clients what it received...
I hope this helped sorry for all the confusion :)

If you want to maintain some kind of global class-level state, you should define a class-level accessor on Repeater that you can assign your repeating message to.
class Repeater
class << self
attr_accessor :incoming_message
end
def initialize(username, ip)
# repeat Repeater.incoming_message to back to ip
end
end
Repeater.incoming_message = "what"
Repeater.new(user, ip)

You need to use some parsing + serialization . Can they wire an already serialized/marshalled string?
1) convert the ruby code to yaml or json
2) use the json or yaml load method like myobj = YAML.load(new_yaml_string)
or
save it in another file called input and do a
require 'input'
create object of repeater

Related

Is there a way to force disconnect an absinthe graphql subscription from the server side?

The Phoenix app I’m working on creates subscriptions to the changes on a document as long as that document is “public”. If someone changes their document to “private”, though, I don’t want those subscriptions to continue receiving updates.
I know how to prevent new subscriptions from being created on the private document, but I’m not sure how to disable pre-existing ones from the server side?
You need to assign an ID to every socket that corresponds to a particular user. Then you can do this:
MyAppWeb.Endpoint.broadcast(socket_id, "disconnect", %{})
To assign the ID to the socket, find the module where you do this:
use Absinthe.Phoenix.Socket,
schema: MyAppWeb.Schema
It is probably in lib/my_app_web/channels/user_socket.ex.
In that "socket" module, you write your ID callbacks like this:
#impl true
def id(%{
assigns: %{
absinthe: %{
opts: [
context: %{current_user: current_user}
]
}
}
}),
do: socket_id_for_user(current_user)
def id(_socket), do: nil
def socket_id_for_user(%{id: id}), do: "user_socket:#{id}"
Now you just have to make sure this current_user assign is on your socket.
First, go to your router and put this line in any pipelines that need it (usually just the :api pipeline, sometimes the :browser pipeline):
plug :fetch_current_user
In your router (or in an imported module, whichever you prefer), write this function:
def fetch_current_user(conn, _opts) do
# I don't know how you do auth so get your user your own way.
# For me, it usually involves finding their session token in the DB.
user = get_user_from_conn(conn)
context = if is_nil(user), do: %{}, else: %{current_user: user}
conn
|> Absinthe.Plug.assign_context(context)
end
You may want to do other stuff in this function.
If you use phx_gen_auth you are probably putting the user_token in private assigns, for example.
The main problem you have now is that if you are sending your log-out mutation over this socket, you will have closed it before you can send a response. Very fun problem.
As discussed here:https://elixirforum.com/t/is-there-a-way-to-force-disconnect-an-absinthe-graphql-subscription-from-the-server-side/41042
my approach does not let you terminate particular descriptions. What I have described is a way of terminating the entire socket. With this approach, a client would have to create a new "unauthenticated" socket if it needs that.

How to use the variable in one action to another action

In the ruby controller, I have two methods in the same controller.
class NotificationsController < ApplicationController
def first
variable_one = xxxx
end
def second
// do something
end
end
I want to use the variable one in the method first, and use it in the method two. I tried to assign the variable one to a session hash. session[:variable_one] = variable_one, and access it in the method two. But it turns out the session[:variable_one] in the method two is nil. These two methods don't have the corresponding views, so I cannot add a link_to and pass parameters. The method one cannot be set as before_action as well.
Could you please have some suggestions on this problem? Thanks so much.
The issue that session is stored via cookie, and therefore it is specific to one device. So, you will have one session between the rails app and your frontend, and another session betweeen the rails app and Twilio (probably the Twilio session will reset between each request). Basically, they're totally separate contexts.
Possibly you could figure out how to pass the information along via Twilio - see https://www.twilio.com/docs/voice/how-share-information-between-your-applications - but as a general-purpose workaround, you could just store the column on the database.
First, make a migration to add the column:
add_column :users, :my_variable, :string
Set this value in the first endpoint:
def first
current_user.update my_variable: "xxxx"
end
Then read it from the second:
def second
# first you would need to load the user, then you can read the value:
my_variable = current_user.my_variable
# you could set the db value to nil here if you wanted
current_user.update my_varible: nil
end

rails persist objects over requests in development mode

I am trying to interact with Matlab.Application.Single win32ole objects in my rails application. The problem I am running into is that while I am developing my application, each separate request reloads my win32ole objects so I loose the connection to my matlab orignal instances and new instances are made. Is there a way to persist live objects between requests in rails? or is there a way to reconnect to my Matlab.Application.Single instances?
In production mode I use module variables to store my connection between requests, but in development mode Module variables are reloaded every request.
here is a snippet of my code
require 'win32ole'
module Calculator
#engine2 = nil
#engine3 = nil
def self.engine2
if #engine2.nil?
#engine2 = WIN32OLE.new("Matlab.Application.Single")
#engine2.execute("run('setup_path.m')")
end
#engine2
end
def self.engine3
if #engine3.nil?
#engine3 = WIN32OLE.new("Matlab.Application.Single")
#engine3.execute("run('setup_path.m')")
end
#engine3
end
def self.load_CT_image(file)
Calculator.engine2.execute("spm_image('Init','#{file}')")
end
def self.load_MR_image(file)
Calculator.engine3.execute("spm_image('Init','#{file}')")
end
end
I am then able to use my code in my controllers like this:
Calculator.load_CT_image('Post_Incident_CT.hdr')
Calculator.load_MR_image('Post_Incident_MRI.hdr')
You can keep an app-wide object in a constant that won't be reset for every request. Add this to a new file in config/initializers/:
ENGINE_2 = WIN32OLE.new("Matlab.Application.Single")
You might also need to include the .execute("run('setup_path.m')") line here as well (I'm not familiar with WIN32OLE). You can then assign that object to your instance variables in your Calculator module (just replace the WIN32OLE.new("Matlab.Application.Single") call with ENGINE_2, or simply refer to them directly.
I know this is beyond the scope of your question, but you have a lot of duplicated code here, and you might want to think about creating a class or module to manage your Matlab instances -- spinning up new ones as needed, and shutting down old ones that are no longer in use.

Subclass Rack::Throttle

i am reading about Rack::Throttle and i want to change the default client identifier from an IP to somethng else. The documentation says it can be done
The rate-limiting counters stored and maintained by Rack::Throttle are
keyed to unique HTTP clients.
By default, HTTP clients are uniquely identified by their IP address
as returned by Rack::Request#ip. If you wish to instead use a more
granular, application-specific identifier such as a session key or a
user account name, you need only subclass a throttling strategy
implementation and override the #client_identifier method.
I have no clue where to add that in, here is my current subclass for another method. Does anybody know how to do this? https://github.com/datagraph/rack-throttle
module Rack
module Throttle
class DailyRequests < Daily
def allowed?(request)
## Insert rules
super request
end
end
class HourlyRequests < Hourly
def allowed?(request)
## Insert rules
super request
end
end
class RequestInterval < Interval
def allowed?(request)
## Insert rules
super request
end
end
end
end
You should subclass one of the existing rack-throttle classes (probably either Rack::Throttle::Interval or Rack::Throttle::TimeWindow, whichever one more closely aligns with your needs) and override the #client_identifier method.
#client_identifier is passed one argument, request, which is a Rack::Request instance containing information passed in the incoming HTTP request and can be used to get information such as HTTP headers, cookies, path, and possibly other info depending on your app. The default implementation looks like this:
# #param [Rack::Request] request
# #return [String]
def client_identifier(request)
request.ip.to_s
end
Here's an example of subclassing Rack::Throttle::Interval to match requests on a query parameter such as ?user_id=<id>:
class UserThrottle < Rack::Throttle::Interval
def client_identifier(request)
request['user_id']
end
end
which you could use in a Rack application with:
use UserThrottle, :min => 100
Notice you can still pass options like :min to the Rack use statement, since it is just subclassing the existing throttle classes. And adopting this in a Rails app would just involve calling use in your application.rb file (see Rails on Rack).

Accessing SOAP Service with soap4r not able to access contents of returned objects

So I need to access this service from my rails app. I'm using soap4r to read the WSDL and dynamically generate methods for accessing the service.
From what I've read, I should be able to chain methods to access the nested XML nodes, but I can't get it to work. I tried using the wsdl2ruby command and read through the generated code. From what I can tell, the soap library is not generating these accessor methods. I'm pretty new to ruby, so I don't know if I'm just missing something?
I know when I inspect the element, I can see the data I want. I just can't get to it.
For instance if I use the following code:
require "soap/wsdlDriver"
wsdl = "http://frontdoor.ctn5.org/CablecastWS/CablecastWS.asmx?WSDL"
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
response = driver.getChannels('nill')
puts response.inspect
I get the following output:
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}binding
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}operation
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}body
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}address
#<SOAP::Mapping::Object:0x80b96394 {http://www.trms.com/CablecastWS/}GetChannelsResult=#<SOAP::Mapping::Object:0x80b96178 {http://www.trms.com/CablecastWS/}Channel=[#<SOAP::Mapping::Object:0x80b95f5c {http://www.trms.com/CablecastWS/}ChannelID="1" {http://www.trms.com/CablecastWS/}Name="CTN 5">, #<SOAP::Mapping::Object:0x80b9519c {http://www.trms.com/CablecastWS/}ChannelID="2" {http://www.trms.com/CablecastWS/}Name="PPAC 2">, #<SOAP::Mapping::Object:0x80b94620 {http://www.trms.com/CablecastWS/}ChannelID="14" {http://www.trms.com/CablecastWS/}Name="Test Channel">]>>
So the data is definitely there!
Here is the code generated by wsdl2ruby for the method being used above:
# {http://www.trms.com/CablecastWS/}GetChannels
class GetChannels
def initialize
end
end
# {http://www.trms.com/CablecastWS/}GetChannelsResponse
# getChannelsResult - ArrayOfChannel
class GetChannelsResponse
attr_accessor :getChannelsResult
def initialize(getChannelsResult = nil)
#getChannelsResult = getChannelsResult
end
end
Sorry for the long post, I figured the more info the more likely someone can point me in the right direction.
Thanks
-ray
Answer
require "soap/wsdlDriver"
wsdl = "http://frontdoor.ctn5.org/CablecastWS/CablecastWS.asmx?WSDL"
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
response = driver.getChannels('nill')
for item in response.getChannelsResult.channel
puts item.name
puts item.channelID
end
How I got the Answer
You can figure out the methods of response via
response.methods
This will get you a long list of methods that are hard to sort through, so I like to subtract out the generic methods. Ruby lets you subtract arrays.
response.methods - Object.new.methods
Using this technique, I found the getChannelsResult method for response. I repeated the process
resonse.getChannelsResult.methods - Object.new.methods
I found the channel method for its result. Again!
response.getChannelsResult.channel.methods - Object.new.methods
This returned a bunch of methods including: sort, min, max etc. So I guessed Array. A simple confirmation was in order
response.getChannelsResult.channel.class
Sure enough it returned Array. To make life simple, I just worked with the first item of the array to get its methods
response.getChannelsResult.channel.first.methods - Object.new.methods
Whoalla, I found two more methods "name" and "channelID"

Resources