As @Camway notes above, this is easy to do using the correct Rails methodology for JOINING, SELECT, and GROUPing. For example, suppose I have users and regions, a user can have areas from 0 to many, and a region can have users from 0 to many.
Here is my Model Region :
class Region < ActiveRecord::Base
Here is my user model:
class User < ActiveRecord::Base
There is, of course, a table regions_users , with integer fields region_id and user_id.
To get a general-purpose GROUP_CONCAT job that pulls the codes of all the regions to which each user is attached, I just need to add a class method like this to the User model:
class User < ActiveRecord::Base # attributes: id (integer), email (string) has_and_belongs_to_many :regions class << self def regions_listing joins(:regions) .select("DISTINCT users.email, GROUP_CONCAT(DISTINCT regions.region_code ORDER BY regions.region_code) AS regions_list") .group("users.email") .order("users.email") end end end
So, with just this code code, everything pulls all users sorted by email.
ruby > User.regions_listing => [#<User email: " joe@blow.com ">,#<User email: " sally@mae.com ">,#<User email: " billy@bob.com ">,#<User email: " jane@doe.com ">,#<User email: " big@ed.com ">]
Each of these returned objects has an attribute of the #regions_list attribute, which will provide you with a group list of codes for the regions attached to this user through the regions_users table.
This can be seen with a simple #map call:
ruby > User.regions_listing.map { |u| [u.email, u.regions_list] } => [[" joe@blow.com ", "0,1,2,3,4,5"], [" sally@mae.com ", "1,2,5"], [" billy@bob.com ", "0,4"], [" jane@doe.com ", "3"], [" big@ed.com ", "2,3,4,5"]]
Note that since this uses the appropriate AR support AR methods, this is a chain . That is, you can add β. Region_listingβ at the end of the entire AR request to the user model, and it will provide you with a group method / data for any user objects selected by your request up.
In this way:
ruby > User.where("users.email like 'b%'").regions_listing.map { |u| [u.email, u.regions_list] } => [[" billy@bob.com ", "0,4"], [" big@ed.com ", "2,3,4,5"]]
And you can also get data in your manufactured #regions_list field using HAVING, for example, to find all users connected to both region 0 and region 4:
ruby > User.regions_listing.having("regions_list LIKE '%0%4%'").map { |u| [u.email, u.regions_list] } => [[" joe@blow.com ", "0,1,2,3,4,5"], [" billy@bob.com ", "0,4"]]