Ruby - Difference between :variable and #variable - ruby

As a Ruby on Rails newbie, I understand that the "#" and ":" references have different meanings. I saw this post in SO, which described some of the differences.
# indicates a instance variable (e.g., #my_selection)
: indicates an alias (e.g., :my_selection)
I ran into a situation where I had a standard MVC page, similar to all of the other forms/pages in my webapp.
html.erb snippet
<%= form_for #my_selection do |f| %>
route.rb snippet
resources :my_selections
When I attempt to access this page, I get this error:
NoMethodError in selections#create
Showing C:/somedir/myapp/app/views/my_selections/index.html.erb where line #16 raised:
undefined method `my_selection_index_path' for #<#<Class:0x1197e5676>:0x25439c3b>
Line 16 is the form snippet shown above.
All of my other forms/pages in the same web app are set up in exactly the same way and are working fine. However, once I changed the erb form reference to :my_selection, this error went away and my page behaved normally.
Questions:
Is my understanding of the difference between :my_selections and #my_selections correct?
Why would switching to :my_selection resolve my original error?

Is my understanding of the difference between :my_selections and
#my_selections correct?
Nope :(
: indicates a symbol, its not an alias for anything intrinsically. It's like an immutable string, which is often used as a name to represent something.
In places where the Rails api accepts a symbol in place of an instance variable, internally it's actually doing this:
self.instance_variable_get "##{my_symbol}"
Which actually returns the value of the requested instance variable.
So the only reason that you think symbol correspond to instance variable at all, is because the code that drives the API you are using works that way. Without a framework to do that for you, there is no correlation at all.
Why would switching to :my_selection resolve my original error?
for_form(model_instance) will generate a form that submits to the create action if the model instance is unsaved, or to the update action if the model is already exiting in your DB.
No I don't know what's in #my_selection, but whatever class it is doesn't seem to be generating the routes properly.
resources :my_selections
Will generate a route you would invoke like this:
my_selections_path
How your form is generating a route for my_selection_index_path I'm not sure and it really depends on what your models are.
And when you pass a symbol instead, and there is no corresponding ivar, it uses that as the model name for route generation. Which would do the right thing by trying to invoke my_selections_path, which is directly based on the symbol you pass in.

Related

Ruby Sinatra Upload Form params Disturbed

Upon submitting a form in Sinatra, I'm coming up with the following error:
App 40327 output: 2018-06-28 02:59:17 - NoMethodError - undefined method `[]' for nil:NilClass:
App 40327 output: /Library/WebServer/Documents/blammo/routes/publish.rb:87:in `block in <class:MyApp>'
The form is a file upload form, and a single text field. Simple. The file goes through, as does the text field. They are both captured just fine.
I submit the params to a method, which is ultimately responsible for generating the error on the following line down the page:
fname = params[:s_single_file_upload][:filename]
The method in question returns fine with a boolean. I've rewritten it a couple of ways and flushed out anything that might trip something I'm
unfamiliar with.
So the params is messed up if this method mentioned above is being called. So fname can't be assigned. I expect the params to be intact
at this point in the code. Is there any destruction if the params are perused before this point? In another language, I've seen params destroyed
in one way or another for some reason, but I'm not sure about Ruby.
I'm not finding any nil:NilClass, but that's exactly what it's reporting. Here's the trigger of this method:
result = Alpha::rf_alpha_sniff(params)
And the module::method:
module Alpha
def self.rf_alpha_sniff(incoming)
qualifiers = %w(alpha bravo charlie delta echo foxtrot)
incoming.delete('captures')
incoming.delete('splat') # take out Mustermann's 'captures' and 'splat'
incoming.delete('s_single_file_upload') # non-perusal 'single_file_upload'
incoming.values.each do |item|
item = item.gsub(" ","_")
Dev::hq_log("item: #{ qualifiers.include?(item.downcase) }")
return true if qualifiers.include?(item.downcase)
end
return false
end
end
So the page progresses fine without this method. When the method is induced any way, the params seem to get screwed up, so the file is pretty much
gone.
How is this method interfering with the params so that it's unavailable later on down the script? I'm expecting it to be fully available everywhere.
Turns out, using incoming.delete was deleting items from the params hash, as it was a reference to the original, instead of using a copy.
So, I have to copy the params by using params.dup (duplicate) so they are not the same object.
Having a view of the params hash post-testing-method, showed me that objects were indeed deleted. Another one solved.

How do I call the evernote struct object to report all notes inside a notebook?

I am working through the ruby evernote-thrift API and sandbox.
I am experiencing some issues interpreting the docs; I am trying to retrieve the subject line from all the notes inside a particular notebook.
To get the name of the notebook I call
notebooks = noteStore.listNotebooks(authToken) and then run .each on notebooks. According to the docs there is a struct object called noteList but I can’t figure out how to use it.
this is the link to the docs area I am trying to leverage http://www.rubydoc.info/gems/evernote-thrift/Evernote/EDAM/NoteStore/NoteList#struct_fields-instance_method
my attempt, is as follows, but its not returning anything. unfortunately im not familiar with structs at all.
notebooks = noteStore.listNotebooks(authToken)
notebooks.each do |notebook|
next if notebook.name != 'First Notebook'
notes = notebook.noteList
noteList.each do |note|
puts note
end
end
i am getting a no method error... which makese sense because its a struct I just dont know how to leverage it...
undefined method `noteList' for <Evernote::EDAM::Type::Notebook:0x007fb2041683f8> (NoMethodError)
The generated docs for our Ruby SDK are confusing (sorry!), but I find the general docs to be much clearer: https://dev.evernote.com/doc/reference/.
As you can see in https://dev.evernote.com/doc/reference/Types.html#Struct_Notebook, the Notebook object does not have an attribute called noteList. There is a struct called NoteList, but that was what the removed NoteStore.findNotes returned.
The procedure for getting the titles/subjects of the notes in a notebook is to get the Notebook (which you have done), then pass the notebook's guid into NoteStore.findNotesMetadata (https://dev.evernote.com/doc/reference/NoteStore.html#Fn_NoteStore_findNotesMetadata). This returns a NotesMetadataList which has a notes attribute which is a list of NoteMetadata. This struct has metadata like title and GUID but not the body. If you want the full information, you would pass the GUID into NoteStore.getNote (https://dev.evernote.com/doc/reference/NoteStore.html#Fn_NoteStore_getNote).
That API is one of the least Ruby things I've ever seen. You have my condolences for trying to trudge through that :)
From the API docs, all I'm seeing that hangs off of that Evernote::EDAM::Type::Notebook class are #struct_fields and #validate, as far as instance methods go. Perhaps that struct_fields has what you're looking for?
If that doesn't lead you anywhere, I'd suggest doing using something like Pry to help you troubleshoot the error. I'd put a binding.pry statement on the second line and then explore the notebooks objects from there.

Rally API using Ruby: How do I reference the testcase method (Automated/Manual)?

I am using Ruby to work with the Rally API. I am trying to reference the testcase method. The method being Manual or Automated, but I always get an error. I am using Ruby, so I don’t know if method is a reserved word in Ruby, or what is happening. Could you please let me know how to reference the test case method?
I am able to do:
testcase.objective
testcase.priority
etc.
But I can’t do
testcase.method
I always get this error.
‘method’: wrong number of arguments (0 for 1) (ArgumentError)
Are you using rally_rest_api or rally_api?
If you are using rally_rest_api - Charles is correct. try testcase.elements[:method]
(fieldname downcased and underscored as a symbol)
If you are using rally_api - http://rubygems.org/gems/rally_api -
Getting fields can just be:
testcase["FieldName"]
Hope that helps.
You just need to capitalize the names when trying to access built-in fields (i.e. fields that are not custom). I came across this problem myself and using tc.Method instead of tc.method fixed it.
The reason this error shows up can be seen in the docs for Object#method which, as you've likely figured out by now, causes your code to call the method method instead of access the field named method.

PageObject with Ruby - set text in a text field only works in the main file

I'm automating a site that has a page with a list of options selected by a radio button. When selecting one of the radios, a text field and a select list are presented.
I created a file (test_contracting.rb) that is the one through which I execute the test (ruby test_contracting.rb) and some other classes to represent my page.
On my class ContractPage, I have the following element declaration:
checkbox(:option_sub_domain, :id => "option_sub_domain")
text_field(:domain, :id => "domain_text")
select_list(:tld, :id => "domain_tld")
I've created in the ContractPage a method that sets the configuration of the domain like this:
def configure_domain(config={})
check_option_sub_domain
domain = config[:domain]
tld = config[:tld]
end
When I call the method configure_domain from the test_contracting.rb, it selects the radio button, but it doesn't fill the field with the values. The params are getting into the method correctly. I've checked it using "puts". Even if I change the params to a general string like "bla" it doesnt work. The annoying point is that if on test_contracting.rb I call the exact same components, it works.
my_page_instance = ContractPage.new(browser)
my_page_instance.domain = "bla"
my_page_instance.tld = ".com"
What I found to work was to in the configure_domain method, implement the following:
domain_element.value = config[:domain]
tld_element.send_keys config[:locaweb_domain]
Then it worked.
The documentation for the PageObjects module that I'm using as reference can be found here: http://rubydoc.info/github/cheezy/page-object/master/PageObject/Accessors#select_list-instance_method
Do you guys have any explation on why the method auto generated by the pageobject to set the value of the object didnt work in this scope/context ?
By the way, a friend tried the same thing with Java and it failed as well.
In ruby all equals methods (methods that end with the = sign) need to have a receiver. Let me show you some code that will demonstrate why. Here is the code that sets a local variable to a value:
domain = "blah"
and here is the code that calls the domain= method:
domain = "blah"
In order for ruby to know that you are calling a method instead of setting a local variable you need to add a receiver. Simply change your method above to this and it will work:
def configure_domain(config={})
check_option_sub_domain
self.domain = config[:domain]
self.tld = config[:tld]
end
I'm pretty new to this world of Selenium and page objects but maybe one of my very recent discoveries might help you.
I found that that assignment methods for the select_list fields only worked for me once I started using "self" in front. This is what I have used to access it within my page object code. e.g., self.my_select_list="my select list value"
Another note - The send_keys workaround you mention is clever and might do the trick for a number of uses, but in my case the select list values are variable and may have several options starting with the same letter.
I hope something in here is useful to you.
UPDATE (Jan 3/12)
On diving further into the actual Ruby code for the page object I discovered that the select_list set is also using send_keys, so in actuality I still have the same limitation here as the one I noted using the send_keys workaround directly. sigh So much to learn, so little time!

SOAP::RPC::Driver formatting problems. How can I change it?

I'm dealing with a SOAP webservice call from a server that is expecting to receive method calls with the paramaters in the format of:
<urn:offeringId> 354 </urn:offeringId>
But SOAP::RPC::Driver is generating messages in the form of:
<offeringId xsi:type = "xsd:int">354</offeringId>
The server keeps erroring when it gets these messages (especially since it's expecting offeringId to be a custom type internal to itself, not an int).
Is there anyway to configure the driver to format things the way the server is expecting it. Is the server even doing SOAP? I'm having trouble finding reference to that style of formating for SOAP (I know it DOES work though, because SOAPUI works just fine with that type of message).
-Jenny
Edit: I've got at least part of it solved. the RPC::Driver (obviously) uses the RPC standard, whereas apparently the server I'm trying to talk to is doing "document". Now, when I look at RPC::Driver's API, I'm seeing a method named "add_document_method". That SOUNDS to me like it might be what I want, but I can't figure out what paramaters to give it. The examples I've seen around the net don't make much sense to me, things like:
def GetNamePair(response)
response.account.each do |x|
class << x
attr :configuration, true
end
x.configuration = Hash[*x.a.map do |y|
[y.__xmlattr[XSD::QName.new(nil, 'n')], String.new(y)]
end.flatten]
end
end
mNS = 'urn:zimbraAdmin'
drv.add_document_method('GetAllAdminAccountsRequest', mNS, [XSD::QName.new(mNS, 'GetAllAdminAccountsRequest')],
[XSD::QName.new(mNS, 'GetAllAdminAccountsResponse')] )
puts YAML.dump(GetNamePair(drv.GetAllAdminAccountsRequest([]))
All I really know is that I have a method that takes in certain parameters.... I really don't get why, if this method does what I think it does, it has to be more complicated. Isn't this just a matter of taking the exact same data and formating it differently? I'm so confused....
Okay, what I ended up doing was using SOAP:RPC:Drivers add_document_method, which requires me to give it the wsdl, namespace, etc, and then give it the attributes later as a single input hash thingy (and gives me the output in a similar format). It worked, it just wasn't as clean as add_rpc_method (which is waht add_method defaults to)
-Jenny

Resources