Following were my query to get list of countries along with cities:
#countries_cities = Product.joins(:user).where("country is not null and country <> ''").where("city is not null and city <> ''").where(:users => {:merchant_status => 1}).group(:country, :city).select("country,city").as_json
The output result were as follow:
Object[city:"Bangkok",country:"Thailand"],Object[city:"Phuket",country:"Thailand"],Object[city:"Malaysia",country:"Kuala Lumpur"],Object[city:"Malaysia",country:"Penang"],Object[city:"Shanghai",country:"China"],Object[city:"Beijing",country:"China"]
cchs = #countries_cities.group_by{|cc| cc["country"]}
#search_location_country = cchs
And the view is:
<ul id="color-dropdown-menu" class="dropdown-menu dropdown-menu-right" role="menu">
<% #search_location_country.each do |country, cities| %>
<li class="input" style="background:#ECECEC; "><%= country.upcase %></li>
<% cities.each do |city| %>
<li class="input"><%= city["city"].titleize %></li>
<% end %>
<% end %>
</ul>
Now the Drop down result follow this pattern:
Thailand
-Bangkok
-Phuket
Malaysia
-Kuala Lumpur
-Penang
China
-Beijing
-Shanghai
How can I ensure that Malaysia will always place at the top of the drop down lists? Thanks!!
How about:
#countries_cities = Product.joins(:user)
.where.not(country: [nil, ''])
.where(users: {merchant_status: 1})
.group(:country, :city)
.order("country!= 'Malaysia'")
.select(:country, :city)
.as_json
In Postgres, false is sorted before true (see this answer here: Custom ORDER BY Explanation)
You can customize you query like this:
#countries_cities = Product.joins(:user)
.where.not(country: [nil, ''])
.where(:users => {:merchant_status => 1})
.group(:country, :city)
.order("ORDER BY
CASE WHEN country = 'Malaysia' THEN 1
ELSE 2
END ASC")
.select(:country, :city)
.as_json
So we set the order of Malaysia = 2, and others = 1 to ensure the result with Malaysia will be on the top.
Related
I have an array of objects, where I have the following fields: title, name e url
My data:
#array = [
{ id: 1, title: '123', name: 123 },
{ id: 2, title: '123', name: 321 },
{ id: 3, title: '1234', name: 123 },
]
I need to group my data by title and then make the map with the names
<%= #array.map do |x| %>
<div class='col-md-12'>
<h3><%= x.title %></h3>
<div class="row">
<%= #array.filter do |y| %>
<div class="col-4">
<% if y.title === x.title %>
<p><%= t.name %></p>
<% end %>
</div>
<% end.join.html_safe %>
</div>
</div>
<% end.join.html_safe %>
The return is:
title = '123'
name = '123'
name = '321'
title = '123'
name = '123'
name = '321'
title = '123'
name = '123'
That is, my array comes duplicated ... how to proceed?
Remembering that I am inside the rails view
You're getting duplicate entries since you're mapping over all the elements and filtering the array for every element inside the block.
You can use Enumerable#group_by to group the array elements by title. You can then iterate over the groups and display the title and names of each group. Note that I'm using item[:name] to access the values from the hash since your question mentions an array of hashes. You should update it to item.name (and other places using hash access) if you're working with objects instead.
#groups = #array.group_by {|i| i[:title] }
<% #groups.each do |title, items| %>
<h3><%= title %></h3>
<% items.each do |item| %>
<p><%= item[:name] %></p>
<% end %>
<% end %>
I'd like to create a todo list looking for any cell that matches today's date on either agreement, start or due date.
<% #project.where("project_date_agreement + project_date_start + project_date_due > ?", Date.today).each do |tasks_today| %>
<ul>
<li>Item Due Today</li>
</ul>
<% end %>
Any help getting me in right direction would be appreciated.
You want to use OR conditions in your where clause. Properly speaking this would be in your controller.
#projects = Project.where('date_agreement = ? OR date_start = ? or date_due = ?', Date.today, Date.today, Date.today)
In your Project Model you might want to create a field that say's what's due...
def due_because
due_array = []
due_array << 'Agreement date' if date_agreemnt == Date.today
due_array << 'Start date' if date_start == Date.today
due_array << 'Due date' if date_due == Date.today'
due_array.join(', ')
end
Then in your view you would iterate over the #projects
<ul>
<li>Items Due Today</li>
<% #projects.each do |project| %>
<li><%=project.name%> <%=project.due_because%></li>
<% end %>
</ul>
if you asking one row and different column, how about if you combine with table
<% #tasks = #projects.where("date_agreement = ? AND date_start = ? AND date_due = ?",Date.today ,Date.today, Date.today) %>
<table>
<tr>
<ul>
<% #tasks.each do |task| %>
<td>
<li><%= task.check_box :item_due %></li>
</td>
<% end %>
</ul>
</tr>
</table>
How can I list unique country followed by related cities? Following were my product table:
name country city
p1 US New York
p2 US Boston
p3 US Chicago
k1 UK London
k2 UK Liverpool
Controller:
#countries = Product.joins(:user).distinct.where("country is not null and country <> ''").where(:users => {:merchant_status => 1}).pluck(:country)
#cities = Product.joins(:user).distinct.where("city is not null and city <> ''").where(:users => {:merchant_status => 1}).pluck(:city)
#countries.map! {|country| country.split.map(&:capitalize).join(' ')}
#search_location_country = #countries
And in my View:
<ul id="color-dropdown-menu" class="dropdown-menu dropdown-menu-right" role="menu">
<% #search_location_country.each do |country| %>
<li class="input"><%= country %></li>
<% end %>
</ul>
How can I sort the end result for drop down like this:
US
- New York
- Boston
- Chicago
UK
- London
- Liverpool
Thanks!!
EDIT
To be display something like this:
Hey you can try this way using group it gives you all distinct records
#countries_cities = Product.joins(:user).where("country is not null and country <> ''").where("city is not null and city <> ''").where(:users => {:merchant_status => 1}).group(:country, :city).select("country,city").as_json
It will give you output like
[{:country => "US", :city => "New York"}..]
If you want to again group it by country then used like
cchs = #countries_cities.group_by{|cc| cc["country"]}
Convert above multidimensional array to hash using
#country_cities_hash = = Hash[*cchs]
In your view file as
<% #country_cities_hash.each do |country, cities| %>
<li class="input"><%= country %></li>
<% cities.each do |city| %>
<li class="input"><%= "#{city}(#{country})" %></li>
<% end %>
<% end %>
Not sure I do understand the question but... I guess you have a collection of Product, looking like this :
produts = [
<Product #name="p1", #country="US" #city="New York">,
<Product #name="p1", #country="US" #city="Boston">,
<Product #name="k2", #country="FR" #city="Paris">,
...
]
In that case, to index the city names by country :
#cities_by_coutry = products.inject({}) do |index, product|
index[product.country] ||= []
index[product.country] << product.city
index
end
Which result to :
{"US"=>["New York", "Boston"], "FR"=>["Paris"]}
Then you can iterate :
#cities_by_coutry.each do |country, cities|
cities.each do |city|
puts "City: #{city} is in country {country}"
end
end
I am attempting to perform a series of requests that will organize the results in a given date span in a way where each location will live on the top level, and contain an another array with each set of results. Here is what I have so far:
locations = Location.all
#requests = []
locations.each do |location|
request = PurchaseRequest.where('created_at >= ? AND created_at <= ? AND location_id = ?', params[:start_date], params[:end_date], location.id).order(:location_id)
#requests.push(location => request)
end
My ideal (non-working) implementation in the view would look something like:
<ul>
<% #requests.each do |location| %>
<li>location[0].name</li>
<ul>
<% location[1].each do |request| %>
<li>request.name</li>
<% end %>
</ul>
<% end %>
</ul>
Try something like this:
#requests = {}
Location.all.each do |location|
#requests[location.name] = PurchaseRequest.where('created_at >= ? AND created_at <= ? AND location_id = ?', params[:start_date], params[:end_date], location.id).order(:location_id)
end
and:
<ul>
<% #requests.each do |location_name, request_list| %>
<li><%= location_name %></li>
<ul>
<% request_list.each do |request| %>
<li><%= request.name %></li>
<% end %>
</ul>
<% end %>
</ul>
#requests becomes a hash with the key being the location name and the value being the purchase requests.
i have a single search field that is querying three different columns from two different tables: "companies" and "industries" from a positions table and "schools" from an educations table. it is successfully returning all users that meet ALL fields entered into the search field (using select_tag). this is from my view:
<%= form_tag(search_path, :method => :get, :id => "people_search") do %>
<div class="row-fluid">
<div class="span4">
<table>
<tr>
<td>
<div class="search-table" style="padding-left:55px">
<%= select_tag "all", options_for_select((#visible_companies + #visible_industries + #visible_schools).uniq, params[:all]), { :placeholder => "Search by companies, industries and schools...", :multiple => true, :js => "if (evt.keyCode == 13) {form.submit();}" } %>
</div>
</td>
<td>
<%= submit_tag "Add", id: "send-button", style:"width:175px;" %>
</td>
</tr>
</table>
</div>
<% end %>
</div>
and controller:
#visible_positions = Position.where{ is_visible.eq('true') }
#visible_educations = Education.where{ is_visible.eq('true') }
#visible_companies = #visible_positions.order("LOWER(company)").map(&:company).uniq
#visible_industries = #visible_positions.order("LOWER(industry)").map(&:industry).uniq
#visible_schools = #visible_educations.order("LOWER(school)").map(&:school).uniq
#c = #visible_positions.where{company.in(my{params[:all]})}.map(&:user_id)
#i = #visible_positions.where{industry.in(my{params[:all]})}.map(&:user_id)
#s = #visible_educations.where{school.in(my{params[:all]})}.map(&:user_id)
#C = #visible_positions.where{company.in(my{params[:all]})}.map(&:company)
#I = #visible_positions.where{industry.in(my{params[:all]})}.map(&:industry)
#S = #visible_educations.where{school.in(my{params[:all]})}.map(&:school)
#blacklist = []
#cis = #c + #i + #s
#experiences = ([#C,#I,#S].reject(&:empty?).reduce(:&))
#cis.uniq.each do |user_id|
unless #C.empty?
#C.uniq.each do |company|
unless Position.find_all_by_company(company).map(&:user_id).include?(user_id) || Position.find_all_by_industry(company).map(&:user_id).include?(user_id) || Education.find_all_by_school(company).map(&:user_id).include?(user_id)
#blacklist << user_id
end
end
end
unless #I.empty?
#I.uniq.each do |industry|
unless Position.find_all_by_industry(industry).map(&:user_id).include?(user_id) || Position.find_all_by_company(industry).map(&:user_id).include?(user_id) || Education.find_all_by_school(industry).map(&:user_id).include?(user_id)
#blacklist << user_id
end
end
end
unless #S.empty?
#S.each do |school|
unless Education.find_all_by_school(school).map(&:user_id).include?(user_id) || Position.find_all_by_company(school).map(&:user_id).include?(user_id) || Position.find_all_by_industry(school).map(&:user_id).include?(user_id)
#blacklist << user_id
end
end
end
end
unless #c.empty? && #i.empty? && #s.empty?
#users = User.find(#cis - #blacklist)
end
the search looks like this (notice the single field), with a sample query included (notice the AND filter...i'm the only user in the database that fits all search terms ['dartmouth college' for school, 'world health organization' for company, 'internet' for industry]):
i realize this is not an efficient query and am thinking of ways to speed it up, but could use some ideas at this point.
happy turkey day :)
Based on your description rather then on understanding your code I figured out something like this
User.joins(:positions, :educations).where("lower(positions.company) like lower(?) and lower(positions.industry) like lower(?) and lower(educations.school) like lower(?) and positions.is_visible and educations.is_visible", "%#{company}%", "%#{industry}%", "%#{school}%")
or if there is only one company or industry in column
User.joins(:positions, :educations).where("(lower(positions.company) = lower(?) or lower(positions.industry) = lower(?)) and lower(educations.school) = lower(?) and positions.is_visible and educations.is_visible", company,industry, school)
But to put many industries, companies, schools as params will be more complicated
and create indexes
create index positions_lower_company on positions (lower(company));
create index positions_lower_industry on positions (lower(industry));
create index educations_lower_school on educations (lower(school));
I hope it will help somehow.