Using gsub to clean string and then truncate - ruby-on-rails

I need to remove some characters from a string (computer mac address + junk...) and truncate to leave the first 18 characters.
Currently, I have the following in my model:
def popular_locations
popular_locations = Radacct.group(calledstationid).order('calledstationid desc').count
end
That outputs a list and their count but the format needs adjustment for a search I'll do.
I tried adding this:
clean_mac_address = :calledstationid.gsub(/[^0-9a-z]/i, '')
But I get an error undefined method `gsub' for :calledstationid:Symbol
-- EDIT --
Initially the calledstationid is stored in db (radacct model) with the following format:
00-18-0A-21-44-7B:Home Office
This is basically a mac address plus an SSID name.
I need to strip out the dashes and SSID because we have another model (locations) which has a list of mac addresses in this format:
00:18:0A:21:44:7B
locations and radacct are unrelated (radacct is a model where all sessions are dumped into). Eventually what I need to do is do a count of all sessions and group by calledstationid (as seen above). Then we'll query the locations table and work out the location name. I should be left with something like this:
location_name session_count
School 2
Home 12
Office 89

I'm not sure how you put the errant : in there when the model definition doesn't have it:
clean_mac_address = calledstationid.gsub(/[^0-9a-z]/i, '')
What you probably mean to do is clean up that variable before passing it in:
def popular_locations
# Clean up calledstationid
calledstationid.gsub!(/[^0-9a-z]/i, '')
# Find it and return
Radacct.group(calledstationid).order('calledstationid desc').count
end

I think that popular_location is object of ActiveSupport::OrderedHash class with calledstationid as keys.
So if I understood you right, try something like
result = Radacct.group(calledstationid).order('calledstationid desc').count
result.each do |key, value|
puts key.gsub(/[^0-9a-z]/i, '') # formatted key
puts value # count
end
I think there is also sql-way to did it. You should select substring from calledstationid and then group by it.
Check this article http://www.ke-cai.net/2009/06/mysql-group-by-substring.html

Related

How to create a hash for all records created by a user?

In our Rails app, the user (or we on his behalf) load some data or even insert it manually using a crud.
After this step the user must validate all the configuration (the data) and "accept and agree" that it's all correct.
On a given day, the application will execute some tasks according the configuration.
Today, we already have a "freeze" flag, where we can prevent changes in the data, so the user cannot mess the things up...
But we also would like to do something like hash the data and say something like "your config is frozen and the hash is 34FE00...".
This would give the user a certain that the system is running with the configuration he approved.
How can we do that? There are 7 or 8 tables. The total of records created would be around 2k or 3k.
How to hash the data to detect changes after the approval? How would you do that?
I'm thinking about doing a find_by_user in each table, loop all records and use some fields (or all) to build a string and hash it at the end of the current loop.
After loop all tables, I would have 8 hash strings and would concatenate and hash them in a final hash.
How does it looks like? Any ideas?
Here's a possible implementation. Just define object as an Array of all the stuff you'd like to hash :
require 'digest/md5'
def validation_hash(object, len = 16)
Digest::MD5.hexdigest(object.to_json)[0,len]
end
puts validation_hash([Actor.first,Movie.first(5)])
# => 94eba93c0a8e92f8
# After changing a single character in the first Actors's biography :
# => 35f342d915d6be4e

Rails Import CSV Error: invalid byte sequence in UTF-8

I'm getting the error invalid byte sequence in UTF-8 when trying to import a CSV file in my Rails application. Everything was working fine until I added a gsub method to compare one of the CSV columns to a field in my database.
When I import a CSV file, I want to check whether the address for each row is included in an array of different addresses for a specific client. I have a client model with an alt_addresses property which contains a few different possible formats for the client's address.
I then have a citation model (if you're familiar with local SEO you'll know this term). The citation model doesn't have an address field, but it has a nap_correct? field (NAP stands for "Name", "Address", "Phone Number"). If the name, address, and phone number for a CSV row is equivalent to what I have in the database for that client, the nap_correct? field for that citation gets set to "correct".
Here's what the import method looks like in my citation model:
def self.import(file, client_id)
#client = Client.find(client_id)
CSV.foreach(file.path, headers: true) do |row|
#row = row.to_hash
#citation = Citation.new
if #row["Address"]
if #client.alt_addresses.include?(#row["Address"].to_s.downcase.gsub(/\W+/, '')) && self.phone == #row["Phone Number"].gsub(/[^0-9]/, '')
#citation.nap_correct = true
end
end
#citation.name = #row["Domain"]
#citation.listing_url = #row["Citation Link"]
#citation.save
end
end
And then here's what the alt_addresses property looks like in my client model:
def alt_addresses
address = self.address.downcase.gsub(/\W+/, '')
address_with_zip = (self.address + self.zip_code).downcase.gsub(/\W+/, '')
return [address, address_with_zip]
end
I'm using gsub to reformat the address column in the CSV as well as the field in my client database table so I can compare the two values. This is where the problem comes in. As soon as I added the gsub method I started getting the invalid byte-sequence error.
I'm using Ruby 2.1.3. I've noticed a lot of the similar errors I find searching Stack Overflow are related to an older version of Ruby.
Specify the encoding with encoding option:
CSV.foreach(file.path, headers: true, encoding: 'iso-8859-1:utf-8') do |row|
# your code here
end
One way I've figured out to get around this is to "Save As" on open office or libre office and then click "Edit Filter Settings", then make sure the character set is UTF-8 and save. Bottom line, use some external tool to convert the characters to utf-8 compatible characters before loading it into ruby. This issue can be a true f-ing labyrinth within ruby alone
A unix tool called iconv can apparently do this sort of thing. https://superuser.com/questions/588048/is-there-any-tools-which-can-convert-any-strings-to-utf-8-encoded-values-in-linu

InvalidTextRepresentation: ERROR: invalid input syntax for integer: "all"

I know "all" isn't an integer
I took this method of the official documentation postgres + rails (I can't link it now but might later if needed)
def list
#a = a.find(:all)
end
so I thought it would list every "a" in "a" table, but didn't. Instead that error was thrown. Isn't this the way rails+gres works? Help a newbie please, thank you vm
find accepts an integer and finds the record with the given int ID.
If you want to retrieve all records, use:
def list
#a = A.all
end
Assuming that A is a model

How to get table column value?

I write follow code to get one record from the table webeehs:
webeehs_result = Webeeh.find(:all, :conditions=>["webeeh_project_id=#{project_id}"])
Then I want to get one column value from this record, how could I do?
For example, the column name is webeeh_date.
first of all, never EVER write code like that. Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. If you must do conditions, then do it like this:
:conditions => ["webeeh_project_id = ?", project_id]
if you have a Project model, you should rename the webeeh_project_id column from your Webeeh model into project_id and have an association in your Project model like has_many :webeehs
Then, you won't need to call that find anymore, just do a p = Project.find(id) and then p.webeehs will return the webeehs you need.
the result will be an array which you can iterate through. And to get your webeeh.webeeh_date member, just call it like this:
result.each do |webeeh|
date = webeeh.webeeh_date
end
webeehs_result = Webeeh.findwebeeh_dates
is enough to get all columnn values.
For a different method and performance issues check the following: http://www.stopdropandrew.com/2010/01/28/finding-ids-fast-with-active-record.html
webeeh_result will usually be an array of results for the database.
You can iterate throughit using
webeehs_result.each do |webeeh|
# use "webeeh.webeeh_date" to access the column_name or do whatever you want with it.
end

case insensitive search in rails - an example from Beginning Rails

Could some on help me to turn the following search into case - insensitive?
Here is the piece of code for earching "title" field in event module:
# Add each field to the conditions array
searchable_fields.each_pair do |field, value|
conditions << "#{field} LIKE ?"
values << "%#{value}%"
end
Here is the data I have entered:
Concert
■Posted by: bancova
■2010-03-14
■boston
test
the "Concert" is the title of this event.
now, when I entered "concert" (small c), I cannot get the event.
however, when I entered "Concert", or "oncert", or "cert"...I can get it.
Could some some friend explain the code and teach me how to make it case insensive?
thanks.
I'm unfamiliar with the tutorial you're using but it looks like it's a database problem, not a Ruby/Rails problem. The problem is that your database is case sensitive so 'Concert' matches because that's what's in the DB, but 'concert' doesn't because it's not an actual match with 'Concert'.
Anyway, the actual solution will depend on your database and how it's configured but lets assume it's MySQL, then your solution would look like this
searchable_fields.each_pair do |field, value|
conditions << "#{field} LIKE LOWER(?)"
values << "%#{value.downcase}%"
end
value.downcase will change the input string to all lowercase and the LOWER sql function will do the same on the database side. They should now match. IF you're using SqlLite or Postgres you'll need to look up their lowercase functions but the rest will still be the same.

Resources