How to select distinct name from associated columns in rails - ruby-on-rails

I am working on a netflix clone project in ruby on rails and I need to get distinct genre name from an associated column in rails. That means, from the first table I have the 'genre_id' and from the second I have the 'name' of the genre. So how can I get this 'name'?
Movie Table
Title | Genre
xxxx | 1
aaaa | 1
bbbb | 1
cccc | 1
zzzz | 2
dddd | 2
eeee | 2
gggg | 2
Genre Table
id | name
1 | Action
2 | Romance
In Model
#action = Movie.where(genre_id: 1)
Try
<%= #action.select(:genre_id).distinct %>
Result
#<Movie::ActiveRecord_Relation:0x00007fb908040470>
Expected
Action
PS: These return error
<% #action.first.genre_id.name %>
<% #action.select(:genre_id).first.name %>
<% #action..select(:genre_id).distinct.as_json %> --> returns [{"genre_id"=>1, "id"=>nil}]
<% #action.first.genre_id %> --> returns 1

Because I can not comment yet, I will answer. It's an old question, for Rails 5+ you should use the following:
#action.distinct.pluck(:genre_id)
It will return an array of unique genre_id's.

I'm assuming you only have the title from the movie table or genre_id (according to the example). You would have to look up the genre table to get the 'Action' string returned.
action = Genre.where(id: 1)
If you have to make a link from the movie to genre table, that will go something like this:
movies = Movie.includes(:genre)
movies.first.genre.name # this will return the action string
# or, pick a specific movie and look up its genre
movies.where(:title => 'xyz').first.genre.name

Related

Getting the winner of a match - the rails way?

In my (League) view I want to list all the matches and mark the match as played, the winning team or the match as a tie.
To know if it is a tie or who the winner is, I have to check the score of each opponent. Where do I do these calculations? view helper?, model scope?
My idea is to have three functions that check per match when i list the matches:
match.played? -> true / false
match.tie? -> true / false
match.winner? -> team_id with the highest score.
Database (postgresql)
Matches
id | league_id | date
---+-----------+----------
1 | 1 | 2016-03-21 21:00:00
2 | 1 | 2016-03-22 09:00:00
...
Opponents
(score is null if not played)
id | match_id | team_id | score
---+----------+---------+--------
1 | 1 | 1 | 0
2 | 1 | 2 | 1
3 | 2 | 3 | 1
4 | 2 | 4 | 1
4 | 3 | 1 |
4 | 3 | 2 |
....
You're definitely on the right path. I would have the methods you suggested on my Match model with one exception:
match.winner #=> returns the Team object of the winner (or nil).
I would then have a view helper that called these methods to determine how to render them. I.e., Has it been played? Was it a tie? Who won.
Your questions scope is a little broad for a definitive answer ;)
Ask 5 developers and you will get 12 different answers.
That said, here is what I would do:
Your idea to implement those instance methods is a good starting point, although I personally do not like "?" methods that do not return a boolean value, in my oppinion it should just be #winner and should return the team instance, not the id (I take it there is a "Team" model). You might want to think about a complementary #loser method.
Your view could look something like this:
<table>
<% #matches.each_with_index do |match, i| %>
<tr>
<td class="match number">
<%= i + 1 %>
</td>
<td class="team-1">
<%= match.team_1 %>
</td>
<td class="team-2">
<%= match.team_2 %>
</td>
<td class="winner">
<% if match.played? %>
<!-- this would be a view helper since you have to consider
the tie situation and we do not want that much logic
in the view. It would return a string with either the
teams name or "tie". -->
<%= winner_of_match match %>
<% else %>
N/A
<% end %>
</td>
<!-- etc... -->
</tr>
<% end %>
</table>
This is just very basic to give you an idea to build on. For example you might want to get rid of the if match.played and do it in your view helper (return "not yet played" or something).

Find matching values of 2 columns in Ruby on Rails

I am reading a CSV file with RoR and printing out an HTML table but need to mark when the values of 2 separate columns match with another row.
The CSV looks like
name | value1 | value2| value3
bob | 2 | 3 | foo
jim | 4 | 5 | bar
tim | 2 | 7 | foo
I want to find when VALUE1 and VALUE3 match the values of VALUE1 and VALUE3 of another row in this CSV file (in this case: "2" & "foo" match on bob and tim)
The result would be something like:
name | value1 | value2| value3 | duplicate
bob | 2 | 3 | foo | Y
jim | 4 | 5 | bar | N
tim | 2 | 7 | foo | Y
I'm printing the table out
<% file.each do |row| %>
<tr>
<% row.each do |k, v| %>
<td><% v %></td>
<% end %>
</tr>
<% end %>
What I'd like to do is flag the table row when I find the matching columns.
Another version of the answer above, in plain ruby rather than ERB, so it's easier to test
I wanted to show my small ruby program to show how I did this. It's not as easy to read in the ERB version and this can be copied and pasted into IRB or piped into a file.
puts '<head></head>'
puts '<body>'
puts '<table>'
puts '<tr><th>#</th><th>col1</th><th>col2</th><th>col3</th><th>col4</th><th>Matching Previous Rows:</th></tr>'
file = [%w(Bob foo 32 3), %w(Joe zip 4 foo), %w(Joe baz 4 foo), %w(Steve foo 44 3), %w(Bob baz 32 foo), %w(Mary baz 4 wow), %w(Lisa 34 wow 2), %w(Art 45 foo E),%w(Bob foo 32 3)]
output_file = []
file.each do |row|
row.unshift 0x00FFFF #make first value the background color of 0xFFFFFF
row.push '' #add a column for matches
output_file.each_with_index do |prev_row,i| # look for current row values in previous entries
if prev_row[2] == row[2] and prev_row[4] == row[4]
if prev_row[0] == 0x00FFFF
prev_row[0] = rand(0xFFFF0)
row[0] = prev_row[0]
else
row[0] = prev_row[0]
end
row[-1] += "#{(i + 1)}, "
end
end
output_file << row #add the new row to the look-back array
end
output_file.each_with_index do |output_row,i|
print "<tr bgcolor=##{output_row[0].to_s(16).upcase}F >"
output_row.shift
print "<td>#{i + 1}</td>"
output_row.each do |v| #why the k? you don't use it here.
print '<td>' + "#{v}" + ' </td>'
end
puts '</tr>'
end
puts '</table>'
puts '</body>'
I am reminded of a certain XKCD comic about determining if a photo was taken in a National Park,
And if the photo is of a bird... LOL
So you need a bit more complex data structure to do comparison of each row with all previous rows.
OK, final edit: I added code to only set a new color if this is the first time a set of values repeats, that way if it repeats again it will get the same color. Also added code that appends columns showing what rows also match.
<% output_file = [] %>
<% color_offset = 26214 %>
<% file.each do |row| %>
<% row.unshift 0x00FFFF # add last 4 digits of bgcolor as first item in each row %>
<% row.push '' #add a column at the end for row match numbers
<% output_file.each_with_index do |prev_row,i| # look for current row values in previous entries %>
<% if prev_row[2] == row[2] and prev_row[4] == row[4] %>
<% if prev_row[0] == 0x00FFFF %>
<% prev_row[0] -= color_offset %>
<% row[0] = prev_row[0] %>
<% else %>
<% row[0] = prev_row[0] %>
<% end %>
<% color_offset -= 52 %>
<% row[-1] += "#{(i + 1)}, " %>
<% end %>
<% end %>
<% output_file << row # add the new row to the look-back array %>
<% end %>
<% output_file.each do |output_row| %>
<tr bgcolor=#FF<% output_row[0].to_s(16).upcase %> >
<% output_row.shift %>
<% output_row.each do |v| # why the k? you don't use it here. %>
<td> <% v %> </td>
<% end %>
</tr>
<% end %>
So you take each row, loop through the array of rows previously checked, if it matches change both their first items to a matching 4 digit color in hex (G and B, R is added at the end), then copy the new row into the array of rows previously checked.
This breaks if a row matches more than once, as it will only give the same color to the new match and the one previous. BUT I added a final column that tells you which row each one matched previously. So if it is highlighted you can jump back to that row.
There are other ways to do the highlighting, maybe copy the new color forward, that way more than two of the exact same row would be the same color.

slice each day ROR [duplicate]

This question already has answers here:
How do I group by day instead of date?
(6 answers)
Closed 8 years ago.
Im creating a time line with some columns from a table.
At the moment is the time line just display each column ordered by the "created_at" field.
But i want slice it for each day like this:
TODAY
content -|
|
|- content
|
content -|
|
YESTERDAY
|
|- content
|
content -|
At the moment am i using this code
<ul>
<% #timeline.each do |timeline| %>
<li>
<%= timeline.title %>
</li>
<% end %>
</ul>
I want to do something like the "each_slice(5)" function.
Hope anybody can tell me how to do this.
Thanks in advance.
You can group your array with ruby group_by:
#timeline.group_by { |el| el.created_at.to_date.to_s(:db) }
Note: I assume that #timeline already sorted.
Probably, this method will be reusable, so better place it in models like:
def self.to_grouped_by_day
group_by { |el| el.created_at.to_date.to_s(:db) }
end
And than call it in the controller.

Ruby each do loop 'n' number of times

Hi I'm having trouble with the below loop in a .erb view
<% my_list.each do | list | %>
.. loop stuff.....
<% end %.
This works fine for looping through my list, but I only want to loop through the first 4 items in 'my_list' and not the whole list. I tried some things like:
<% my_list.each do | product | 3.times %>
but didn't seem to work as I think my ruby knowledge is limited to say the least!
Use Array#take like this:
<% my_list.take(4).each do | product | %>
Take first 4 element from my_list Array#first:
<% my_list.first(4).each do | product | %>
use Array#each_slice for slice your array
<% my_list.each_slice(4) do | products | %>
<% products.each do | product | %>
It is apparent that you want to iterate through your list in groups of four (you really should amend your question, because this is an important piece of information). It is also apparent you are using Rails. Fortunately Rails has in_groups_of built into ActiveSupport:
<% my_list.in_groups_of(4) do |products| %>
<% products.each do | product | %>
One advantage of this approach (over alternatives such as each_slice) is that in_groups_of will pad the end to make sure you always get four groups. It will pad with nil by default, but you can specify the padding yourself:
<% my_list.in_groups_of(4, " ") do |products| %>
If you pass false as the pad, it will not pad at all and behaves just like each_slice.
<% my_list[0..3].each do | list | %>

Grouping Sunspot Models to get sorting/count on View

#search = Sunspot.search(Event, Person, Organization) do
keywords params[:q]
order_by(:score)
end
Based on the search results I'd like to create a list of Models with counts for each model.
Events (12)
People (5)
Organizations (3)
Is there a way to do this type of grouping in Sunspot?
<% #search.each_hit_with_result do |hit, result| -%>
<%= result.class %> <!- Gives me Model, but repeated -->
<% end %>
There is probably a smarter way, but one possible way is to get array of the classes like this
classes = #search.results.map(&:class) # this will give array of returned classes
then do as suggested in this link
h = Hash.new(0)
classes.each { | v | h.store(v, h[v]+1) }
# h = { 3=>3, 2=>1, 1=>1, 4=>1 }
hope that helps

Resources