Getting count of residents in each country - ruby-on-rails

Say I have a Users table, and each user has a country_id (the list of countries is stored in another table).
I want to display a list of each country and how many members it has, ie:
Canada: 16
Romania: 12
USA: 9
I was using some raw SQL, but the move to postgres was messy, so I'd like to use a cleaner implementation. Is there a nice 'railsy' way to go about getting said list?

This should return a hash with country_id => count pairs:
#users_by_country = User.group(:country_id).count
#=> { 1 => 104, 2 => 63, ... }
The generated SQL query looks like this:
SELECT COUNT(*) AS count_all, country_id AS country_id FROM `users` GROUP BY country_id
And in your view:
<% #countries.each do |country| %>
<%= country.name %>: <%= #users_by_country[country.id] %>
<% end>

though you have not provided any detail . so its hard to answer exaclty, but may be this will help
User.group(:country_id).count

If you have a Countries model and you want to do it a little differently so that it is more human readable you could use .map.
Countries.map{|o| { Country: o.name, members: o.members.count } }
Obviously you need to have the associations. If countries is just a field on User then this will not work.
BR

Related

How to get only the unique values from a select drop down rails

I am trying just to display unique values in the year. This is what I tried so far
= select_tag("year", options_for_select(Car.all.uniq.map{|c|[c.year, c.year]}))
I do know that uniq is for an array. The other thought was to do a validation for uniqueness but the client doesn't want that.
Here you can use select field to get unique dropdown list, check the below code for help:
<%= f.select :year, options_for_select(Car.all.map {|p| [ p.year ]}.uniq, "Select Year"),:prompt => "Select Year",:required => true %>
You are using uniq on Car model. You should map from the collection all the years, then remove duplicates:
= select_tag("year", options_for_select(Car.all.map(&:year).uniq))

Simple Drop Down List from Array in Rails

This seems like it should be in Rails A1, but I can't find it any where. I have a bunch of locations stored in a Location table, made up of text fields City, County, Country etc. (This should have all been normalised out in my opinion, but there you go...).
A user can search by Location, and they enter into the separate search fields. At the moment, I'd like the Country such box to be a drop down list of countries. I currently get the list of countries in the db as follows:
#countries = Location.find(:all, :select=>"DISTINCT country")
The search box is currently just a text field:
<%= f.text_field :country,{:placeholder => "Country",:size=>20 } %>
But I'd like that to be a drop down box of the countries that are already in the #countries variable. It will just pass the country as a string. I'm a complete Newbie to Rails and even the basics are flumaxing me...Help!
If name is the actual name of the county in your country model:
<%= f.select(:country, #countries.map(&:name), {:include_blank => 'Select a Country'}) %>
You could do differently, having the value of the field different from the value displayed. Documentation lives here.
FYI, I usually use a very convenient gem named Carmen to handle country lists etc...

How to store countries as integers in a database in ruby on rails

What I'm trying to do:
I'm trying to find out if there is a quick way to get country_select to store integers representing the countries instead of storing the country names/strings themselves. I'm using the country select gem.
Possible solution:
One way I'm thinking this can be done is if I install the gem as a plugin and edit the countries array to have arrays within the main array with integers and a string e.g. COUNTRIES = [["United Kingdom", 1],["United States", 2]]
This way in my form there will be values representing the strings. Then I can have a country_id column in my profiles table where users selected countries id will be stored. I will have a separate table "countries" that will have the countries stored in it and I'll use the country_id of the profiles table to reference the correct country in the countries table.
Doing it this way would mean I would still get the good features of the gem/plugin such as having priority countries at the top of the select list. Something I don't know how to do on my own.
It would take long but it could work. If I chose this solution where would I put the plugin? vendors folder in my apps directory right?
But if there is a quicker way to do this I'd like to do it that way.
A bigger picture:
Ok I have a search form where a user can browse the sites users filtering out results by:
text typed location
gender
sexuality
marital status
country
I'm using thinking sphinx and when filtering attributes it seems that the attributes need to be represented integers because everything works but the country.
I'm using the country select gem and it seems to only store strings and not an integer representing the string.
I would like to have it store integers instead.
Here are some contants I use in my search forms:
module ApplicationHelper
GENDER = [["Select", nil],["Male", 1],["Female", 2]]
ETHNICITY = [["Select", nil],['Black', 1 ],['White / Caucasian', 2 ],['European', 3 ],['Asian', 4 ],
['Indian', 5 ],['Middle Eastern', 6 ],['Native American', 7 ],['Hispanic', 8 ],
['Mixed Race', 9 ],['Other Ethnicity', 10 ]]
MARITAL_STATUS = [[' Select', nil],['Single', 1 ],['Dating', 2 ],['In relationship', 3 ],['Married', 4 ],
['Living Together', 5 ],['Divorced', 6 ],['Separated', 7 ],['Widowed', 8 ]]
SEXUAL_PREFERENCE = [[' Select', nil],['Straight', 1 ],['Gay', 2 ],['Bi-sexual', 3 ]]
end
The search/browse form:
<%= form_tag browsers_path, :method => 'get' do %>
<p>
Location: <%= text_field_tag :location, params[:location] %>
<br />
Country: <%= country_select :country, [ "United Kingdom", "France", "Germany" ] %>
<br />
Gender: <%= select_tag :gender, options_for_select(ApplicationHelper::GENDER, params[:gender]) %>
<br />
Ethnicity: <%= select_tag :ethnicity, options_for_select(ApplicationHelper::ETHNICITY, params[:ethnicity]) %>
<br />
Marital status: <%= select_tag :marital_status, options_for_select(ApplicationHelper::MARITAL_STATUS, params[:marital_status]) %>
<br />
Sexual preference: <%= select_tag :sexual_preference, options_for_select(ApplicationHelper::SEXUAL_PREFERENCE, params[:sexual_preference]) %>
<br />
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
as you can see each array has a string and an integer. If you check out the array from the country_select gem there are just strings.
I'd appreciate an explanation of the best possible way to do what I'm trying to do and a clear example if possible.
I hope this post made sense.
Kind regards
I ended up recreating the country list from wikipedia with name of country and iso code as value. Much more straight forward and I got to store countries as their iso code and as integers making it possible to use the attribute with thinking sphinx.
Create the constant like you have for the other filters. Then use a virtual attribute to translate and set the values so that you can store the int version and not the string.
EDIT:
Maybe I do not understand what we are talking about exactly but if you are trying to store the value in a model somewhere you can do something like this:
def country_int(country_s)
country = COUNTRY[country_s]
end
def country_int
COUNTRY.key(country)
end

Rails collection_select modify output

In one of the views (erb) I have the following code
collection_select(:wp_article, :wp_site_id, WpSite.find_by_sql(["SELECT wp_sites.* FROM wp_sites, users_wp_sites, users WHERE users_wp_sites.user_id = users.id and users_wp_sites.wp_site_id = wp_sites.id and username= ?", session[:cur_username]]), :id, :name,
{:prompt => true})
This lists the site names that are accessible by the current user (cur_username) in a drop down list, for example
Google.com
Facebook.com
Twitter.com
Now I need to display the number of times that the user has accessed these sites in the same drop down list, like this:
Google.com (32)
Facebook.com (68)
Twitter.com (21)
How can I modify the query to include the count together with the site name?
(I know how to get the count in a subquery within the same query posted above, but do not know how to pass name of site (:name) and count (the new count I will get in the subquery) to the drop down list as one complete string.)
Managed to solve it in this way:
<%= collection_select(:wp_article, :wp_site_id, WpSite.find_by_sql(["SELECT wp_sites.id, CONCAT(wp_sites.name, ' (', (select count(*) from wp_articles where wp_articles.wp_site_id = wp_sites.id and wp_articles.author = users.username and published = 1), ')') name FROM wp_sites, users_wp_sites, users WHERE users_wp_sites.user_id = users.id and users_wp_sites.wp_site_id = wp_sites.id and username= ?", session[:cur_username]]), :id, :name, {:prompt => true}) %>
In the main SQL query I am using CONCAT (it is a MySQL backend) to append the count to the name and keeping the attribute name "name" (so that it is referenced by symbol :name).

alphabetical pagination in rails

I'm searching a gem for Rails for alphabetical pagination. I wish I could have a list of first letters found in the result (I mean, if there is no row beginning with 'a', I don't want the 'a' to be display on the pagination links). Is this kind of gem already exists?
Thanks in advance!
This wouldn't be too hard to create at all, for example if you had a find, maybe like:
#all_words = Word.select("words.word")
…which returned a result a result set such as a list of words like this:
["alphabet", "boy", "day", "donkey", "ruby", "rails", "iPad"]
…the you could do this:
#all_words.collect {|word| word[0,1]}.uniq.sort
which would return:
["a", "b", "d", "r", "i"]
The .collect {|word| word[0,1]} stores the first letter of each word into a new array whilst uniq filters out the unique letters and sort sorts these alphabetically.
Simply assign this to a variable and you can use it in your view like so:
<ul>
<% #first_letters.each do |letter| %>
<%= content_tag :li, link_to(letter, words_pagination_url(letter), :title => "Pagination by letter: #{letter}") %>
<% end %>
</ul>
Your controller action could then decide what to do with the param from the pagination if one is passed in:
def index
if params[:letter]
#words = Word.by_letter(params[:letter])
else
#words = Word.all
end
end
And then the scope in your model would look something like:
scope :by_letter,
lambda { |letter| {
:conditions => ["words.word LIKE ?", "#{letter}%"]
}}
Your routes require something like:
match "words(/:letter)" => "words#index", :as => words_pagination
I haven't tested this all the way through but it should set you on the right path.
To get a dynamic select from the appropriate table, you can use a dynamic SQL finder.
In this example, we select from a table named 'albums', and fabricate a column 'name' to hold the values. These will be returned in the 'Album' model object. Change any of these names to suit your needs.
Album.find_by_sql("SELECT DISTINCT SUBSTR(name,1,1) AS 'name' FROM albums ORDER BY 1")
Note that you can't use the Album model objects for anything except querying the 'name' field. This is because we've given this object a lobotomy by only populating the 'name' field - there's not even a valid 'id' field associated!
I've created an alphabetical pagination gem here:
https://github.com/lingz/alphabetical_paginate
For anyone still having issues in this domain.

Resources