Nested each do loops printing unexpectedly in Ruby - ruby-on-rails

I have two arrays containing strings. I'm trying to iterate through both arrays with nested .each do loops to see if any elements in the first array have a substring of any of the elements in the second array. I'm using .include? within the nested loops to check this. I want the result to be the string printed the number of times it matches an element in partials.
This is the method that isn't working
def orphanCheck(partials, partials1, duplicatesArray)
partials1.each do |i|
partials.each do |j|
if i.include?(j)
duplicatesArray.push(i)
end
end
end
end
I'm using this as a helper method to define partials and partials1
def manipulate(monthEmails, todayEmails, partials, partials1)
monthEmails.each do |i|
email = EmailAddress.new(i.to_s)
partials.push(email.host_name.to_s)
end
todayEmails.each do |j|
todaySignup = j.to_s.slice(11, 100)
partials1.push(todaySignup)
end
end
And then I'm calling the two with the following
manipulate(allUnique, todayEmails, partials, partials1)
orphanCheck(partials, partials1, duplicatesArray)
#puts duplicatesArray
duplicatesArray is printing some strings that shouldn't be matches and it's printing some strings more times than I want. For example, gmail.com isn't in partials at all but me#gmail.com, which is in partials1 once, is being pushed to duplicatesArray three times. If yahoo.com is in partials three times, then I would want me#yahoo.com (from partials1) to be pushed to duplicatesArray three times, for example.

To be sure you could be doing:
partials1.each do |i|
i_ups=i.split('#')[-1]
partials.each do |j|
if i_ups===j
duplicatesArray.push(i)
break
end
end
end
If I understood correctly (partials is only the host part of the email provider and partials1 is the full email address)

A better solution that should give you a correct duplicatesArray would be:
partials1.each do |email_address|
email_host = email_address.split("#").last
duplicatesArray.push(email_address) if partials.include?(email_host)
end

Related

Comparing two arrays and not getting expected output in rails console

I have the following controller action that builds two arrays.
current_event = Event.find(params[:event_id])
campaign_titles = Relationship::CampaignTitleRelationship.where(campaign_id: current_event.campaign_id)
campaign_title_ids = Array.new
campaign_titles.each do |title|
campaign_title_ids << [title.title_id]
end
event_title_ids = Array.new
params[:title_ids].each do |title|
event_title_ids << [title]
end
The two arrays output like this
[["6556"], ["9359"], ["11319"], ["12952"], ["14389"], ["14955"], ["16823"]]
[[6556], [9359], [11319], [12952], [14389], [14955], [16823]]
I'm trying to compare these two arrays using the - symbol, but am only getting an output of each id, instead of what I expect (nothing) since both arrays contain the same items.
I can see that the first array has quotations around each key inside the bracket. The second does not. How do I compare these two arrays?
Just add params as integers to your array
params[:title_ids].each do |title|
event_title_ids << [title.to_i]
end

Looping through passed parameters in Capybara

I would like to create a Capybara method for reading the contents of a table, that takes a variable number of parameters and iterates through the parameters.
Here is the method I have:
Then /^I should see a table record with "(.*?)", "(.*?)", "(.*?)"$/ do |invisible, name, address, phone|
rows = page.all(".table-bordered tr")
expect(rows.any? { |record| record.has_content? name }).to be_true
rows.each do |record|
if record.has_content? name
expect(record.has_content? address).to be_true
expect(record.has_content? phone).to be_true
end
end
end
I'm using the same CSS table structure to create tables with much larger numbers of columns elsewhere in the program. So whether the table has 3 columns or 12, I'd like to be able to use the same method so I don't write awkward code.
How can I assign a variable number of parameters and loop through each parameter in Capybara?
def assert_my_table(name, *row_data)
# It will be much faster than looping through all rows
row = page.find(:xpath, "//*[#class='table-bordered']//tr[./td='#{name}']")
# retrive row contents only once (again, it will be faster than retrieving it again for each of the columns you want to assert)
row_text = row.text
row_data.each do |text|
expect(row_text).to include(text)
end
end
assert_my_table(name, address, phone)

Rails Case or Helper

I have a number of codes which all have different meanings e.g. "cancelled", "confirmed" etc and I store the code in the database. I want to make use of the word forms in a number of different places around my Rails app and wanted to know what people recommend for this to keep things as efficient as possible.
I have considered a case statement in my views but it will be repeated and I want to avoid logic in my views too. So I thought maybe a helper but should it be a case statement within the helper?
This is what I have so far in my relevant helper file:
def status_word(status)
case status
when 1
puts "Cancelled"
when 2
puts "Confirmed"
end
end
and I call it in my view as follows:
<%= status_word(1) %>
but nothing is outputted in my view. Can/should I use "put" here or is there a better way?
Your using puts incorrectly. It's for writing to standard output, not for returning a value from a method. You want return, or just let the value fall off the end of the method:
def status_word(status)
case status
when 1 then "Cancelled"
when 2 then "Confirmed"
end
end
With puts before each string, you're actually returning the return value of puts, which is nil:
irb(main):001:0> puts "what"
what
=> nil

Should I symbolize keys?

1) I am grabbing some records for the DB in HAML to display, and the attributes method on each row returns a hash. The hash's keys are strings. Should I turn those keys into symbols? I am not sure the call to symbolize_keys is worth it. I.e.,
%td #{app['comment']}
or
%td #{app[:comment]
2) I am trying to symbolize the array of hashes I return, but it is not working:
rows = Comment.all(:order => 'created DESC')
result = rows.each_with_object([]) do |row, comments|
comments << row.attributes.symbolize_keys
end
Is it not actually pushing the symbolized hash into the comments array? I also tried symbolize_keys!, and that did not help. What am I doing wrong?
Since you're using Rails, you have access to HashWithIndifferentAccess so you can bypass your "strings or symbols" issue quite easily by allow both:
h = HashWithIndifferentAccess.new(some_model.attributes)
puts h['id'] # Gives you some_model.id
puts h[:id] # Also gives you some_model.id
Your each_with_object approach:
result = rows.each_with_object([]) do |row, comments|
comments << row.attributes.symbolize_keys
end
should work fine so I think your problem with that lies elsewhere.
Do you have a reason for using ActiveRecord::Base#attributes[your_attribute] instead of ActiveRecord::Base#your_attribute directly? You didn't mention a reason.
ActiveRecord::Base automatically sets up accessors for your database fields:
object = Model.new
object.your_column = "foo" # Writer
object.your_column # Reader
You should be able to use the reader in your views instead of accessing the value through ActiveRecord::Base#attributes.
Update:
I'm not sure if this is what confuses you.
Comment.find(:all) already retrieves all columns values for those rows in your database and stores them in your Comment objects (which we assign to #comments below). The values are already stored in your Comment objects, so you may already use them in your views as you please.
In your controller, if you have:
def index
#comments = Commend.find(:all) # Fetch columns and rows.
end
you can do this in your HAML view:
- #comments.each do |comment| # Iterate through array of Comment objects
%tr
%td= comment.comment # Use value for "comment" column.
you can add hook, which symbolizes keys after model load:
class YourModel < ApplicationRecord
after_initialize do |rec|
attributes["some_json_field"].symbolize_keys! if attributes.key? "some_json_field"
end
end

Rails association access

I wish I described this better, but it's the best I know how. I have two classes Cars and Colors. Each can have many of each other through a association class CarColors. The association is set up correctly I'm positive of this but I can't seem to get this to work:
#carlist = Cars.includes(:Colors).all
#carlist.colors
ERROR
#carlist[0].colors
WORKS
My question is how can I iterate over the #carlist without declaring a index as in the successful example? Below is a few things I have tried which also fail:
#carlist.each do |c|
c.colors
end
#carlist.each_with_index do |c,i|
c[i].colors
end
Your first example fails because Car.includes(:colors).all returns an array of cars, not a single car, so the following will fail, because #colors is not defined for the array
#cars = Car.includes(:colors).all
#cars.colors #=> NoMethodError, color is not defined for Array
The following will work, because the iterator will have an instance of car
#cars.each do |car|
puts car.colors # => Will print an array of color objects
end
each_with_index will work as well, but it is a bit different, as the first object
is the same as the each loop car object, the second object is the index
#cars.each_with_index do |car, index|
puts car.colors # => Will print an array of color objects
puts #cars[index].colors # => Will print an array of color objects
puts car == #cars[index] # => will print true
end

Resources