Get list of unique column results from database - ruby-on-rails

I've stumbled across this answer and it has helped me to generate a list of unique values exactly as I wanted, however, I don't want all of the results. Is there any way to filter the results within the select or another way to accomplish this?
I was thinking of something along the lines of this:
#results = MyModel.select("DISTINCT(columnForDistinction)", :myBoolean => false)
or
#results = MyModel.select("DISTINCT(columnForDistinction)", :someString => stringImLookingFor)
Currently, I'm not able to filter the results on the query, so I am iterating over the returned array and only listing the results that have that boolean set to false like so:
<% #results.each do |result| %>
<% if !result.myBoolean %>
#do stuff here
<% end %>
<% end %>
and
<% #results.each do |result| %>
<% if result.someString == stringImLookingFor %>
#do stuff here
<% end %>
<% end %>
Is there a better way to be doing this?

ActiveRecord query methods are chainable. You can call multiple and it will build them all into a query when you use the result. For conditions, you'll use where. Try something like:
#results = MyModel.select("DISTINCT(columnForDistinction)").where(:myBoolean => false)

Related

Rails iteration over arrays and hashes

I am trying to iterate over what I think is a hash in rails. I used deep_pluck gem to get the values of a Model including some values from the associations. Like this:
Continent.deep_pluck(:link_name, :name, 'countries' => [:link_name, :name])
this returns:
[{"link_name"=>"europe", "name"=>"europe", "countries"=>[{"link_name"=>"countryname", "name"=>"countryname"}]}]
I am trying to iterate this like this:
<% results.each do |continent| %>
<% continent.each do |link_name, name, countries| %>
<%= link_name %>
<% end %>
<% end %>
which in return this:
link_name
name
countries
I tried a lot of different ways and methods and I still can't get the desired output which is to print out the values of :link_name and :name and also another object of countries to iterate them over again for their name etc.
I'm trying to build a navigation menu which has a list of each continent with a submenu of the countries of the continent. I use pluck because I just want the names and link_names of the database.
Thank you very much!
When you iterate over a hash, you get access to the keys and values.
If you look at what's printing out, you're getting the keys of each hash. Your output might make more sense if you set the parameters to what they actually are.
<% results.each do |continent| %>
<% continent.each do |key, value| %>
<%= key %>
<% end %>
<% end %>
This should be enough to get you further along. To achieve what you want, you'll need to check each key and do something with the value based on what the key is.
Perhaps try something like:
[{"link_name"=>"europe", "name"=>"europe", "countries"=>[{"link_name"=>"countryname", "name"=>"countryname"}]}].each do |continent|
continent.each do |k,v|
case k
when 'countries'
v.each do |country|
country.each do |k,v|
puts " - #{v}"
end
end
else
puts v
end
end
end
(Naturally, you'll need to add the erb markup. And the "puts" are just for example to run this in console.)
Which will give you:
europe
europe
- countryname
- countryname
Thank you very much for your suggestions, i finally managed to make it work like this:
<% results.each do |continent| %>
<li class="has_children"><%= continent["name"] %>
<ul class="sub_menu">
<% continent["countries"].each do |country| %>
<li><%= country["name"] %>
<% end %>
</ul>
</li>
<% end %>

Can I query the current scope(s)?

My collections model has a scope like this
scope :got, -> { where(status: 'Got') }
I have a link to an index as follows
<%= user_collections_path(#user, got: true) %>
Thanks to the has_scope gem that creates an index of the user's collections where the status: is 'Got'. the path is
users/user1/collections?got=true
In that index view I want to be able to write something like
<% if status: 'Got' %>
You have these ones
<% end %>
But no matter how I write it I can't seem to query the scope that was passed in the link. Is there a standard way of doing this?
You can do as following:
<% if params[:got].to_s == 'true' %>
You have these ones
<% end %>
But this forces you to use true as value for params[:got]. Maybe this is better:
<% if params[:got].present? %>
You have these ones
<% end %>
But this will work with params like:
users/user1/collections?got=true,
users/user1/collections?got=false,
users/user1/collections?got=NOPE,
etc.
Actually, the has_scope gem provides a method current_scopes that returns a hash (key = scope, value = value given to the scope) in the corresponding views. You should be able to do like this:
<% if current_scopes[:got].present? %>
You have these ones
<% end %>

dealing with complex GET params in rails

I'm trying to pass params via GET to a form using ransack, it would normally work fine except that the params[:q] is causing a problem when I try to merge it.
controller (using ransack)
def index
#search = Record.ransack(params[:q])
#records = #search.result.page(params[:page])
end
view
<ul>
<% Genre.all.each do |genre| %>
<% category_count = #search.result.joins(:genre).where("genres.id = ?", genre.id).size %>
<% unless category_count == 0 %>
<li>
<%= link_to genre.name, params.merge(:"q[genre_name_eq]" => genre.name) %> (<%= category_count %>)
</li>
<% end %>
<% end %>
</ul>
But I keep getting duplication:
q[genre_name_eq]=Rockabilly&q[genre_name_eq]=Rockabilly
Without the q[] it manages the params correctly, overwriting the previous one.
Also tried params[:q].merge(:genre_name_eq) which causes the problem when there is no q[] and it also just doesn't work, giving me genre_name_eq= and no q[]
How else can I handle the q[] so that it replaces the value instead of duplicating it several times?
EDIT (after your edit)
params is a hash, not a simple querystring. If you want to update a nested value, you have to update the nested hash.
First ensure that params[:q] exists and is a hash (in the controller)
params[:q] ||= {}
Then only update q in the view
<% params[:q].update :genre_name_eq => genre.name %>
<%= link_to genre.name, params %>

Rails finding a value in a table

Is it possible to call the include? function on a whole table, like this?
<% #user.games.each do |g|
##latestround = g.rounds.order('created_at DESC').first
%>
<% if ##latestround.submittedpictures.isFinalPicture.include?(true) %>
<p>FinalPicture has been played!</p>
<% end %>
<% end %>
The problem i'm getting is that It only works when I put a block on submittedpictures and then loop through each record of this table. However I want to look through the whole table in one go and see if the column 'isFinalPicture' includes a value with 'false'.
Any ideas?
The following snippet works but its not the way i want it (I would get more lines if the round happens to have more 'true' FinalPictures)
<% ##latestround.submittedpictures.each do |s| %>
<% if s.isFinalPicture == true %>
<p>Final Picture has been played!</p>
<% end %>
<% end %>
You could make a scope for it like
class SubmitedPricture << ActiveRecord::Base
scope :final_pictures, where('isFinalPricture = ?', true)
end
then you could see if there is any with only one query
latestround.submittedpictures.final_pictures.any?
Also you should follow the conventions of Rails in naming your Models and everything else. Like submittedpictures should be submitted_pictures

Rails: Multiple models records list

How can I show recent added #post and #photos in one list? For example:
post - LAlala (10.10.2011)
photos - [] [] [] [] (1.1.2011)
post - Bbbdsfbs (2.12.2010)
post - Lasdasdf2 (2.10.2009)
#posts = Post.limit(20).order('created_at desc')
#photos = Photo.limit(20).order('created_at desc')
#recent_items = (#posts + #photos).sort_by(&:created_at)
<% #recent_items.each do |item| %>
<% if item.class == "Photo" %>
<%= image_tag item.url %>
<% else %>
<%= item.title %>
<% end %>
<% end %>
Alternatively, use group_by to do it like this:
#recent_items = (#posts + #photos).group_by(&:created_at)
<% #recent_items.each do |date, items| %>
Date: <%= date %>
<% items.each do |item| %>
Show information here.
<% end %>
<% end >
I would move the view logic into a helper if I were you for DRYer code.
It is much better to do this is the database.
I just say this: polymorphism + database views.
Create a database view which contains the columns you need from both Post and Photo, including the column "type" containing a the name of the model (you need it for the polymorphism). Call this view for example "list_items". Then create a model called "ListItem". Then you can use this model like any other, paginate it and whatever you need to do.
ListItem.order("created_at > ?", Date.yesterday).page(params[:page])
And don't forget to configure the polymorphic association
However, all this is much easier to accomplish with the listable gem. Check it out!

Resources