RubyOnRails - Sorting members by last name - ruby-on-rails

I have a lot of members in database and I want them sort in Rails by last_name, but the trick is that last name contain croatian letters like (Č,Ć,Š,Đ,Ž).
Some of last_names are for example: Antić, Čekić, Živad, Đurak, Perić...
I used ffi-locale gem but i failed to sort it. So any help and advice is good!

If your database has a correct configuration, this should work:
Member.sort(last_name: :asc).all
If you want to sort the members in your application, after fetching them from the database, you could use sort function (it works fine with utf strings):
members.sort_by!(&:last_name)

Related

postgres unaccent function vs RoR transliterate

In our RoR project we use postgres unaccent function to retrieve unaccent version of one of our models name attribute. The name attribute can contain any accented characters from various languages. We then save it as unaccent_name attribute. I don't like this solution because we need to be sure to have installed and accessible postgres extension UNACCENT (when testing, moving/cleaning database, and so on).
In RoR there is ActiveSupport::Inflector.transliterate method, which should do something very similar.
I've found that it mostly translates accented characters the same way, but there is also some difference:
same result:
SELECT unaccent('ľščťžý') AS unaccent_name;
=> "lsctzy"
ActiveSupport::Inflector.transliterate('ľščťžý')
=> "lsctzy"
different result:
SELECT unaccent('ß') AS unaccent_name;
=> "S"
ActiveSupport::Inflector.transliterate('ß')
=> "ss"
I know both of these methods can accept dictionaries with custom letter replacements, but I'm only interested in their general/default usage.
Is the main purpose of transliterate method same as postgres unaccent function? Can we use it as a replacement?
Very old post but I am working through a problem similar to the OP. We want to be able to search for a name and transliterate to give better results. However, with our versions of Postgres and rails the character transliterates the same to 'ss'.
Just wanted to share my findings in case it may be useful to others who stumble across this post.
In rails 5.2:
irb(main):001:0> ActiveSupport::Inflector.transliterate('ß')
=> "ss"
In postgres 9.6 I get:
db-test=# SELECT unaccent('ß') AS unaccent_name;
unaccent_name
---------------
ss
(1 row)

Parse hash for value from a table

I am writing a AWS-Federation proxy in Rails. This means I grab for some groups using net-ldap on our local ActiveDirectory and want to compare those to a list and look for matches. My NetLDAP-searchresult is this hash:
[#<Net::LDAP::Entry:0x000000048cfdd0 #myhash={:dn=>["CN=Username,OU=Support,OU=mycompany ,OU=Organisation,DC=mycompany,DC=com"], :memberof=>["CN=My AWS Groupname,CN=Receiver,CN=Users,DC=mycompany,DC=com"]}>]
Now I want to parse this hash and look for matches in a local "groups" table. It looks like that:
Name AWS-Role
My AWS-Groupname Some Group
AWS-Othergroup Some Other-Group
I have a group-model.
What is a best practices approach? I've never done something like this before. Would I use a Regex here? Do I loop the groups through all tables? What's the rails way to do this?
edited for more information
I'm going to assume a few things here, since I don't know where you get the LDAP search results from, but assuming your hash looks like this:
EDIT:
based on the additional information:
// Example
require 'net-ldap'
entry = Net::LDAP::Entry.new
entry.dn = ["CN=Username,OU=Support,OU=mycompany ,OU=Organisation,DC=mycompany,DC=com"]
entry[:memberof] =["CN=My AWS Groupname,CN=Receiver,CN=Users,DC=mycompany,DC=com"]
name = entry.memberof.first.split(',').first.gsub('CN=', '')
And assuming you have a model called Group that is mapped to this "groups" table, you can do something like this:
Group.where(name: name).any?
If you find any results, it means you have a match in the table.
But this completely depends on the table structure and hash. To properly answer your question, I'd need to see what Objects you have in Rails, and what the structure of your Hash looks like.
EDIT:
Updated my answer based on the received feedback. Use code at own risk.

AcitveRecord where method that matches just one record

Program.where(name: "xxyyzz123") will return a collection, even if there's just one record that matches which forces me to do ugly things like:
puts Program.where(name: "xxyyzz123").first.age
or
puts Program.where(name: "xxyyzz123")[0].age
When I know for sure only one record will match, is there a shorter way to grab a property from that one record?
ActiveRecord's dynamic attribute-based finders (find_by_x) allow you to select the first record that matches in your database. For example:
Program.find_by_name('xxyyzz123')
will return the first record with name = 'xxyyzz123'
Note that these finders are 'mildly deprecated' in Rails 4. Using
Program.find_by(name: 'xxyyzz123")
achieves the same thing and may make it easier when needing to update to the next version of Rails if they ever remove the former's functionality.
See ActiveRecord::Base in the API for more.
Yes, you will have to access that with Program.where(name: "xxyyzz123").first.age, however, in Rails 3, it is usually recommended to do that type of query with: Program.find_by_name('xxyyzz123').age.
Rails 4 deprecates the above syntax and recommends you to use the following syntax for that:
Program.find_by(name: 'xxyyzz123')
If you have multiple conditions, then simply : Program.find_by(name: 'xxyyzz123', lang: 'ruby')
Behind the scene, it does the same tomfoolery - where clause and returns first object.

Rails: Getting column value from query

Seems like it should be able to look at a simple tutorial or find an aswer with a quick google, but I can't...
codes = PartnerCode.find_by_sql "SELECT * from partner_codes where product = 'SPANMEX' and isused = 'false' limit 1"
I want the column named code, I want just the value. Tried everything what that seems logical. Driving me nuts because everything I find shows an example without referencing the actual values returned
So what is the object returned? Array, hash, ActiveRecord? Thanks in advance.
For Rails 4+ (and a bit earlier I think), use pluck:
Partner.where(conditions).pluck :code
> ["code1", "code2", "code3"]
map is inefficient as it will select all columns first and also won't be able to optimise the query.
You need this one
Partner.where( conditions ).map(&:code)
is shorthand for
Partner.where( conditions ).map{|p| p.code}
PS
if you are often run into such case you will like this gem valium by ernie
it gives you pretty way to get values without instantiating activerecord object like
Partner.where( conditions ).value_of :code
UPDATED:
if you need access some attribute and after that update record
save instance first in some variable:
instance=Partner.where( conditions ).first
then you may access attributes like instance.code and update some attribute
instance.update_attribute || instance.update_attributes
check documentation at api.rubyonrails.org for details

Sanitizing data at active record

I want to sanitize the data coming from my form in ActiveRecord. Especially the apostrophe before its actually included into the SQL query. I want it to be something raghu'\s if raghu's is been inputed. I have already tried using:
sanitize_sql_array
sanitize_sql_for_assignment
sanitize_sql_for_conditions
sanitize_sql_hash_for_assignment
sanitize_sql_hash_for_conditions
But none of these seem to escape the apostrophe there by failing my SQL query.
Rails will handle a lot of the santizing for you if you use the following format for performing finds. It'll run the necessary sub methods to ensure that nothing potentially destructive is inserted into the database. Not sure about the single inverted comma, but it's worth a shot.
Model.find(:all, :condition => ["text_value = ?", params[:form_input])
You might want to have a look at this thread - Strip & Sanitize BEFORE saving data from the Ruby Forum - I haven't tried any of the solutions mentioned but it might get you going in the right direction

Resources