Finding only the new rows added to a table - ruby

I have the following code which is supposed to get me only the new events added to the table from the last time i checked the table.
events=#browser.table( :id =>'table_events').tbody.rows
....
some code
....
events_new=#browser.table( :id =>'table_events').tbody.rows
events=events_new - events # not working !!
Im getting the fallowing error :
undefined method `-' for #<Watir::TableRowCollection:0x007fccb9ba2358> (NoMethodError)
I understand that the "-" predicate is wrong of course, but is there a method that does what i need or do i need to go over all the TableRowCollection and find the new rows manually?

You could try converting the TableRowCollection to an array, which does support subtraction:
events = events_new.to_a - events.to_a
That will work provided the elements have a useful == method defined - and it looks like they do.
Correction: actually, because array subtraction is implemented using a hash table for efficiency (view source here if you're curious), it is not the TableRow#== method that is important but the TableRow#hash method. Fortunately, it looks like Watir implements that as well.

Related

Can a method return an object and a value?

I'm learning Adobes Premiere Pro API (ExtendScript).
In the documentation, is says that the method for a Sequence Object called Sequence.createSubsequence() "Returns 0 if successful".
However in the example code, they assign the method to a variable, does this not suggest the method actually returns an Object rather than an integer (in this case it's a Sequence object)?
New to coding so trying to understanding if there's something fundamental I don't get here, or whether this is in fact an error.
var newSeq = activeSequence.createSubsequence(ignoreMapping);
newSeq.name = "myseqname";
It looks like that documentation is wrong. If I run the code in the debug console it does indeed return a Sequence object.
app.project.activeSequence.createSubsequence(true)
→ [object Sequence]

ActiveStorage::Attachment find resource by blob_id

I have the following model
class Document
has_many_attached :previews
...
end
And I'm trying to find single elements there.
The problem is if I do:
#document.previews.find_by(blob_id: 22)
I get this error: undefined method `find_by' for #<ActiveStorage::Attached::Many>
So I'm kind of forced to loop through enumerable:
#document.previews.find { |p| p.blob_id == 22 }
Is there any other (better/prettier) way to do this?
#ntonnelier I have a similar model, and with Rails 7.0.3 your first example works fine for me:
#document.previews.find_by(blob_id: 22)
Another couple of options that work are:
#document.previews.where(blob_id: 22)
#document.previews.blobs.find_by_id(22)
You should be able to access the blobs for a particular record via the blobs method, which gets you an ActiveRecord collection, and you can use find on that one.
Something like #document.previews.blobs.find(22) might work in your particular case.

How should I merge hash while using 'first_or_create'

I have this hash, which is built dynamically:
additional_values = {"grouping_id"=>1}
I want to merge it with this record object after creation via first_or_create:
result = model.where(name: 'test').first_or_create do |record|
# I'm trying to merge any record attributes that exist in my hash:
record.attributes.merge(additional_values)
# This works, but it sucks:
# record.grouping_id = data['grouping_id'] if model.name == 'Grouping'
end
#Not working:
#result.attributes>>{"id"=>1, "name"=>"Test", "grouping_id"=>nil}
I understand that if the record already exists (returned via 'first'), it won't be updated...although that would be a nice option and any recommendations on that are welcome, but the table was just dropped and recreated, so that's not the issue.
What am I missing?
I also tried using to_sym, resulting with:
additional_values = {:grouping_id=>1}
...just in case there was some weirdness I didn't know about...didn't make a difference
The problem is Hash#merge returns a new hash and then you aren't doing anything with that hash, you're just throwing it away. I would also suggest sticking to using the ActiveRecord methods for updating attributes, instead of trying to manipulate the underlying hash, such as using assign_attributes or, if you want to save the record update. Though, you may find the create_with, which can be used with find_or_create_by, useful here:
model.create_with(additional_values).find_or_create_by(name: 'test')
I can't find any documentation that I like (if at all) for first_or_create in recent rails versions, but if you like that more than find_or_create_by, then if we look at the Rails 3 documentation for first_or_create, you should be able to do with out the create_with:
model.where(name: 'test').first_or_create(additional_attributes)

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!

haml collection and nil --> strftime

I have a Post object I am rendering in a partial, where one element is
= post.created_at
I want to format the time so I've tried variations of strftime in the partial and as a model hook.
= post.created_at.strftime('etc etc')
&
= post.formatted_time
These work fine when there is something to render, but when there isn't a set of posts, there is an error rendering the page:
undefined method `strftime' for nil:NilClass
only the first works when there are no posts, and creates 1 empty post div on the page.
I need to do something either in the model or template to catch when it is empty and render nothing, which seems basic but I've not yet struck the right search terms to find something I understand to implement.
I'm posting this so someone might help me to think through what I've got so far. Basically I need to format time, which I can do but catch when there is nothing to format.
In Rails you can always use try, which will run the method only if created_at is not nil:
= post.created_at.try(:strftime, 'etc etc')
http://apidock.com/rails/Object/try

Resources