How to pull a specific field from a Ruby Associations CollectionProxy? - ruby

I have the following models:
class User < ApplicationRecord
has_many :hobbies, dependent: :destroy
end
class Hobby < ApplicationRecord
belongs_to :user
end
I was trying to output to my view the user and its hobbies:
<table>
<tr>
<th>User</th>
<th>Hobby</th>
</tr>
<% #users.each do |u| %>
<tr>
<td><%= u.name %></td>
<td><%= u.hobbies %></td>
</tr>
<% end %>
</table>
But I see the following:
User Hobby
Mad Max <Hobby::ActiveRecord_Associations_CollectionProxy:0x007fa2721ab910>
It looks like I am outputting the collection, but I want the actual hobby name. I have tried u.hobbies.first, u.hobbies[:hobby], etc. I've looked inside http://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html but it's abit confusing for me as a new developer. Can someone tell me how to pull from a specific field from the collection? And which resource out there is a good guide for me to reference in the future?

So this is basically an array of hobbies that gets attached to the user. so you need to iterate over each one and then ask for the attribute you want from it. Try something like this:
<table>
<tr>
<th>User</th>
<th>Hobby</th>
</tr>
<% #users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td>
<% user.hobbies.each do |hobby| %>
<%= hobby.attribute_name %>,
<% end %>
</td>
</tr>
<% end %>
</table>
If you want to get real fancy you could try doing something like this:
<% user.hobbies.each_with_index do |hobby, index| %>
<%= hobby.attribute_name %>
<%= (index == user.hobbies.length-1) ? '' : ','
<% end %>
That is using a ternary operator to basically say only put a comma if the hobby is not the last hobby

Related

How to stop at a specific range in ruby loops

i have this piece of code here that generates a link for all of my questions from a database, but right now I have 10 entries and this loop will iterate 10 times. Is there a way to stop the iteration at a range of 4?
<table>
<tr>
<th>Question</th>
<th>Button</th>
</tr>
</tr>
<% #questions.each do |q| %>
<tr>
<td><%= q.question %></td>
<td><%= link_to 'Question', show_url(q.id), method: :get %></td>
<td><%= q.id %> Button</td>
<% end %>
</tr>
</table>
Any suggestions will be appreciated!
Thanks.
Assuming you fetch #questions from a database or other external source, e.g. in a rails controller, you could limit the number of entries when fetching your data. There are multiple ways of doing that, depending on your data retrieval method.
However, if you need to limit the questions in the ERB part of your code, you could write:
<% #questions.take(4).each do |q| %>
<tr>
<td><%= q.question %></td>
<td><%= link_to 'Question', show_url(q.id), method: :get %></td>
<td><%= q.id %> Button</td>
</tr>
<% end %>
Alternatively, you could also write:
#questions[0..3]
or
#questions.first(4)
I hope you find this helpful.

Grouping records by user in Admin view

I would like to get all records with their usernames when signed in as Admin. For that my controller code is as below;
amol361s_controller.rb
def index
if current_user.admin
#amol361s = Amol361.all.search(params[:search]).order("created_at ASC")
#users = User.all.amol361s
else
#amol361s = current_user.amol361s.all.search(params[:search]).visible.order("created_at ASC")
end
respond_to do |format|
format.html
format.js
end
end
index.html.erb
<tbody id = "kola">
<% #users.each do |user| %>
<%= user.amol361s.each do |amol361| %>
<tr class="tr-<%= cycle('odd', 'even') %>" id='<%= "tr_#{amol361.id}" %>'>
<% if current_user && current_user.admin %>
<td class="col-1"><%= link_to amol361.date.try(:strftime,'%d/%m/%Y'), edit_amol361_path(amol361) %></td>
<% else %>
<td class="col-1"><%= amol361.date.try(:strftime,'%d/%m/%Y') %></td>
<% end %>
<td class="col-3"><%= span_with_possibly_red_color amol361.description %></td>
<td class="col-1"><%= number_with_precision(amol361.amount, :delimiter => ",", :precision => 2) %></td>
<td class="col-1 neg"><%= number_with_precision(amol361.discount, :delimiter => ",", :precision => 2) %></td>
<td class="col-1 neg"><%= number_with_precision(amol361.paid, :delimiter => ",", :precision => 2) %></td>
<% #balance += amol361.amount.to_f - amol361.discount.to_f - amol361.paid.to_f %>
<% color = #balance >= 0 ? "pos" : "neg" %>
<td class="col-1 <%= color %>"><%= number_with_precision(#balance.abs, :delimiter => ",", :precision => 0) %></td>
<td class="col-1"><%= amol361.delndel %></td>
<td class="col-1"><%= amol361.remark %></td>
<% if current_user && current_user.admin %>
<td class="col-1"><%= link_to "Hide", hide_amol361_path(amol361), method: :put, remote: true, style: "color:#bb7272;" %>
<%= link_to amol361, method: :delete, data: { confirm: "Are you sure?" }, :class => 'delete_item' do %>
<i class="fa fa-trash" ></i>
<% end %>
</td>
<% end %>
</tr>
<% end %>
<% end %>
</tbody>
Right now I am getting the error as undefined method amol361s' for # User::ActiveRecord_Relation:0x00007f5dec19d088.
So, I am trying to get the records followed by usernames, similar to how we gather records based on month.
Any suggestions are most welcome.
Thank you in advance.
From what I understand, you can simply eager load user records if the current user is admin, like this:
#amol361s = Amol361.includes(:user).search(params[:search]).order("created_at ASC")
If you do this, it will be effective to fetch the user data simply by calling association on each member of this relation, like this:
# example:
#amol361s.first.user.username # or whatever the name of username column is
I'm not sure I understood your question correctly though, cause it's a little bit unclear to me.

How do I create a table to display all the instances of my Ruby class using ERB?

My table has the following columns:
<tr>
<th>Number</th>
<th>User</th>
<th>Password</th>
<th>UID</th>
<th>GID</th>
<th>GCOS</th>
<th>Home Directory</th>
<th>Login Shell</th>
</tr>
I have class Student, which looks like this:
class Student
attr_accessor :user_name, :password, :uid, :gid,
:gcos_field, :directory, :shell
attr_reader :count
def initialize(data)
#user_name,#password,#uid,#gid,#gcos_field,#directory,#shell = data
##count = defined?(##count) ? ##count += 1 : 1
end
end
There are about thirty instances of the class under the array map:
#students = datalines.map { |line| Student.new(line.chomp.split(":")) }
A sample element from datalines array is this:
dputnam:x:4185:208:Douglas Vernon Putnam:/users/dputnam:/bin/bash
I haven't been able to get the ##count to function properly either.
My failed attempt at producing a table made all the student names (of my Ruby class incidentally) display horizontally rather than vertically:
<% #students.each do |parameters| %>
<td><%= parameters.user_name %></td>
<% end %>
Any help would be appreciated!
Here's a link to the output if it helps: http://hills.ccsf.edu/~wly3/cs132a/lab4.cgi
Okay the ERB template (I think this is what it is) since it was requested:
<h1>CS132A Lab 4</h1>
<br>
<br>
<table>
<tr>
<th>Number</th>
<th>User</th>
<th>Password</th>
<th>UID</th>
<th>GID</th>
<th>GCOS</th>
<th>Home Directory</th>
<th>Login Shell</th>
</tr>
<tr>
<% #students.each do |parameters| %>
<td><%= parameters.user_name %></td>
<% end %>
</tr>
</table>
<% finish = Time.now %>
<h2>Elapsed time in seconds:<%= (finish.to_f - start.to_f).to_s %></h2>
You have to generate a new <tr> for each student:
<% #students.each do |parameters| %>
<tr>
<td><%= parameters.user_name %></td>
</tr>
<% end %>

Creating a counter for a very large hash (rails)

So I'm trying to parse out some information from Jira's rest API using this gem: https://github.com/sumoheavy/jira-ruby
I am creating a reporting app that will count the number of times a specific 'assignee' resolves an issue in a specific project.
The hash would look like this...
[#<JIRA::Resource::Issue:329487 #attrs={'key'=>'value','key'=>'value', "fields"=> {project=>{'key'=>'value'}, assignee=>{'key'=>'value'}}
I specifically need to get the value of the assignee, and the value of the project, then somehow get them in a table that would list out each assignee, and how many completed issues they have in each project.
The issues that are showing up in this are only completed issues due to the query that I'm using, so don't worry about that, just need to parse this out and count it using some method in a model.
I can currently make a nice parsed table (doesn't get me the info I need) by using this in the view...
`<table>
<thead>
<th>Count</th>
<th>Issue Key</th>
<th>Summary</th>
<th>Time Estimate</th>
<th>Reporter</th>
<th>Assignee</th>
</thead>
<% #issues.each_with_index do |issue, index| %>
<tr>
<td><%= index + 1 %> </td>
<td><%= issue.key %> </td>
<td><%= issue.fields['summary'] %> </td>
<td><%= issue.fields['aggregatetimeestimate'] %> </td>
<td><%= issue.fields['reporter'].values[4] %> </td>
<% if issue.fields['assignee'].present? %>
<td><%= issue.fields['assignee'].values[4] %></td>
<% else %>
<td>N/A</td>
<% end %>
</tr>
<% end %>
</table>`
What I would rather see... Is a table that has the different assignees as the rows, and the different projects as the columns, then the number of issues that have that certain assignee per project, then a grand total on the right. So I need to iterate through all of the assignees, combine all of the assignees that are the same, and tally the count per project in the columns.
I would prefer not to use activerecord, as I'm not saving to a database. The database is the information being retrieved through the API, so it is constantly changing.
Remember that the projects hash, and the assignee hash are hashes of their own, and each one is several levels deep in the entire issues hash. {Issues hash => { fields hash=>{project hash}{assignee hash}}}
Thanks for any help!
Try this:
# Controller
# {Assignee => {Project => Issues closed} }
#assignee_hash = Hash.new { |hash, key| hash[key] = Hash.new(0) }
#projects = Array.new
#issues.each do |issue|
# I'm not familiar with the structure of the assignee/project
# hashes here (and 'key'=>'value' isn't too descriptive),
# but these next 2 lines should be modified to access whatever
# value you want to identify the assignee and project by
assignee = issue.fields['assignee'].??
project = issue.fields['project'].??
#projects.push project unless projects.include? project
#assignee_hash[assignee][project] += 1
end
#View
<table>
<thead>
<th>Assignee</th>
<% #projects.each do |project| %>
<th><%= project %></th>
<% end %>
<th>Total</th>
</thead>
<% #assignee_hash.each do |assignee, project_hash| %>
<tr>
<td><%= assignee %></td>
<% #projects.each do |project| %>
<td><%= project_hash[project] %></td>
<% end %>
<td><%= project_hash.values.reduce(:+) %></td>
</tr>
<% end %>
</table>

How can I render partial in show.html.erb

I have these two models in my Ruby on Rails application - Artist and Song. They are associated as follows:
class Artist < ActiveRecord::Base
has_many :songs
attr_accessible :artist_name
and
class Song < ActiveRecord::Base
belongs_to :artist
attr_accessible :title, :track_URL, :artist_id
I have this code in views/artist/show.html.erb:
<%= render 'artist_song' %>
<table>
<% #artist.songs.each do |song| %>
<tr>
<td><%= song.title %></td>
</tr>
<% end %>
</table>
The partial Im trying to render(_artist_song.html.erb) in the same view looks like this:
<table>
<% #artist = Artist.all %>
<% #artist.each do |artist| %>
<tr>
<td><%= link_to artist.artist_name, artist %></td>
</tr>
<% end %>
</table>
The way it is suppose to work is when I click on an artist shown trough the partial, the code below the partial has to show me all the songs that belongs to the particular artist.
Both the partial and the code in the table tag are working individually. But when I put them together, it looks like there is a conflict between them and the server is showing me this No Method Error:
NoMethodError in Artists#show
Showing C:/Sites/OML/app/views/artists/show.html.erb where line #9 raised:
undefined method `songs' for #<Array:0x5fe1418>
Extracted source (around line #9):
6:
7:
8: <table>
9: <% #artist.songs.each do |song| %>
10: <tr>
11: <td><%= song.title %></td>
12: </tr>
Rails.root: C:/Sites/OML
Application Trace | Framework Trace | Full Trace
app/views/artists/show.html.erb:9:in `_app_views_artists_show_html_erb__950110288_54062208'
app/controllers/artists_controller.rb:21:in `show'
I couldn`t find a solution. Any help will be appreciated.
Thank you.
You are not using a partial. You need to render the partial inside the artist loop:
show.html.erb
<table>
<% #artists = Artist.all %>
<% #artists.each do |artist| %>
<tr>
<td><%= link_to artist.artist_name, artist %></td>
</tr>
<%= render :partial => 'artist_song', :artist => artist %>
<% end %>
</table>
This way, you are passing the current artist object to inside the partial, so there you can do:
artist_song.html.erb
<% artist.songs.each do |song| %>
<tr>
<td><%= song.title %></td>
</tr>
<% end %>

Resources