Rails displaying table data dynamically - ruby-on-rails

Models
class Smoothval < ActiveRecord::Base
has_many :smoothings
has_many :steps
end
class Step < ActiveRecord::Base
belongs_to :usdzar
belongs_to :smoothing
belongs_to :smoothval
default_scope lambda {
order(id: :desc)
}
end
class Usdzar < ActiveRecord::Base
has_many :smoothings
has_many :steps
end
The index view that I am trying to achieve:
<table><thead>
<tr>
<th>Smoothing1</th>
<th>Smoothing2</th>
</tr></thead>
<tbody>
<tr>
<td>"finalsmprice","stepnum"</td>
<td>"finalsmprice","stepnum"</td>
</tr>
</tbody>
</table
So all the fsmprices and the stepnums for every smoothval from the steps table
My index.html.erb looks like this:
<h1>Listing Steps</h1>
<table class="table table-striped table-bordered table-condensed">
<thead>
<% Step.all.includes(:smoothval).group_by(&:smoothval_id).each do |smoothval_id, steps| %>
<tr>
<th>
Smoothing: <%= smoothval_id %>
</th>
</tr>
</thead>
<tbody>
<% steps.each do |step| %>
<tr>
<td>
(<%= step.fsmprice %>): <%= step.stepnum %>
</td>
<% end %>
</tr> </tbody>
<% end %>
</table>
The table is very long and obviously displays all headings and data after one another. I have tried to create a postgres pivot table but that failed using tablefunc so back trying to do it in rails
In my controller I can get the smoothvals (the table headings) into an array as follows, the array looks like [1, 5]:
sv = Smoothval.where('id IN (SELECT DISTINCT(steps.smoothval_id) FROM steps)')
#assigned = sv.pluck(:id)
How can I get the above table layout
Thanks

This was too difficult and came accross a post that said its best to create a pivot table
HOWEVER thats not so easy in Postgres, the issue with the tablefunc extension is that it doesnt dynamically assign the columns, so they need to be statically assigned. So I went this route for now and tested the function https://github.com/hnsl/colpivot
I stuck with the basics and did this but will need to think more about refactoring the solution.
SELECT c_crosstab('Select * from steps', 'ct_view', 'id', 'smoothval_id', 'stepnum', 'first');
SELECT *
FROM crosstab(
'SELECT usdzar_id, smoothval_id, stepnum
FROM steps
ORDER BY 1,2 ASC') -- needs to be "ORDER BY 1,2" here
AS ct ("SV" int, "Smooth1" int, "Smooth2" int, "Smooth3" int);
Hope this helps somoene else

Related

How can I display values from relationship on column array?

I have 2 tables (users and meetings).
I'm trying to displaying the name of the user on table index view
users
|id| |name|
1 DEMO 1
2 DEMO 2
3 DEMO 3
meetings
|id| |user_id|
1 ["1", "2"]
2 ["2"]
3 ["2", "3"]
The Controller /app/controllers/meetings_controller.erb
def index
#meetings = Meeting.all
end
Models
#meeting.rb
class Meeting < ApplicationRecord
belongs_to :users
end
#user.rb
class User < ApplicationRecord
has_many :meetings
end
The View /app/views/meetings/index.html.erb
<table>
<thead>
<tr>
<td>id</td>
<td>User Names</td>
</tr>
</thead>
<tbody>
<% #meetings.each do |meeting| %>
<tr>
<td><%= meeting.id %></td>
<td><%= meeting.user_id %></td>
</tr>
<% end %>
</tbody>
</table>
I'm trying to display the user_id on array relationship and i tried this code:
I got the following error using the following code
undefined method `each' for "[\"1\", \"2\"]":String
<% meeting.user_id do |array|%>
<%= array.user.name %>
<% end %>
I got the following error using the following code
undefined method `each' for "[\"1\", \"2\"]":String
<% meeting.user_id do |array|%>
<%= array %>
<% end %>
I cannot display the value relationship because of column array.
Can you please help me with this issue?
Thanks in advance.
While there is nothing wrong with your approach, one comes to understand that the path of least resistance (= least pain) is to follow "The Rails Way".
So instead of answering your question, let me suggest that the relationship between your models should be:
# user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :meetings
end
# meeting.rb
class Meeting < ActiveRecord::Base
has_and_belongs_to_many :users
end
# you will also need to create a join table with a migration:
def change
create_join_table :meetings, :users
end
Then the view will include:
<% #meetings.each do |meeting| %>
<tr>
<td><%= meeting.id %></td>
<td><%= meeting.users.map(&:name).join(', ') %></td>
</tr>
<% end %>
I assume that you have a has_many relation between Meeting and User. That means that meeting.users will return the list of the users for the current meeting.
The following will return a comma-separated string with the names.
<table>
<thead>
<tr>
<td>id</td>
<td>User Names</td>
</tr>
</thead>
<tbody>
<% #meetings.each do |meeting| %>
<tr>
<td><%= meeting.id %></td>
<td><%= meeting.users.map(&:name).join(', ') %></td>
</tr>
<% end %>
</tbody>
</table>

Trying to display records from chained models on Rails 5.2

Following on from this question
class CoffeeRoast < ApplicationRecord
has_many :coffee_blends
has_many :coffee_beans, through: :coffee_blends
has_one :country, through: :coffee_beans
end
class CoffeeBean < ApplicationRecord
has_many :coffee_blends
has_many :coffee_roasts, through: :coffee_blends
belongs_to :country
end
class Country < ApplicationRecord
has_many :coffee_beans
end
class CoffeeBlend < ApplicationRecord
belongs_to :coffee_bean
belongs_to :coffee_roast
end
I am able to show the related coffee_beans on the coffee_roasts show page, and also the country, however, I can not work out how to display them correctly.
My current code is attempting to show the bean and its related country on the same row on the table, however the top is blank and the two countries are both in the second row.
coffee_roasts/show.html.erb
<h1 class="display-3"><%= #coffee_roast.name %></h1>
<p>
by <h2 class="display-6"><%= #coffee_roast.roaster.roaster_name %></h2>
</p>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Bean</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<% #coffee_roast.coffee_blends.each do |blend| %>
<tr>
<th><%= blend.coffee_bean.name %>
<% end %></th>
<th><%= #coffee_roast.coffee_beans.map {|cb| cb.country.country_name }.join(', ') %></th>
</tr>
</tbody>
</table>
Bean | Country
El Martillo |
Finca La Cumbre | El Salvador, Guatemala
El Salvador show be in-line with the El Martillo bean.
My approach feels quite wrong here, but I'm pretty new to working with multiple levels of models so still learning.
How can I get the beans associated country to display alongside the bean?
This was actually a lot simpler than I thought. I've found the below works perfectly. No need to map an array.
<tbody>
<% #coffee_roast.coffee_blends.each do |blend| %>
<tr>
<td><%= blend.coffee_bean.name %></td>
<td><%= blend.coffee_bean.country.country_name %></td> #this bit was the original concern.
<td><%= blend.coffee_bean.variety %></td>
<td><%= blend.coffee_bean.process %></td>
<% end %>
</tr>
</tbody>
<tbody>
<% #coffee_roast.coffee_blends.each do |blend| %>
<tr>
<td><%= blend.coffee_bean.name %></td>
<td><%= #coffee_roast.coffee_beans.map {|cb| cb.country.country_name }.join(', ') %></td>
</tr>
<% end %>
</tbody>
try and see if this works?

Sorting an index through an associated table?

I have an index that displays all of the current "dprojects" created. I'm working on being able to click the table headers to sort the data by that parameter. I have this all working except for one column. This column displays our customers by the number we've assigned them. For example, "Customer A" is "008". The "dprojects" table has a column for customer ID, and the "schools" table has columns for both the ID and the actual name of the customer.
Because it is a "dprojects" index, the table is sorting by the ID associated with the customer, and not the customer's name. How can I get it to sort alphabetically by name? Here's my code:
view: (dname is the customer name within the school model)
<table>
<thead>
<tr style="border-bottom: 2px solid black;">
<th> <%= sortable "scode", "School" %></th>
</tr>
</thead>
<tbody>
<% #dprojects.where.not(status: "Completed").each do |dproject| %>
<tr>
<td width="20%" class="dotted"><%= dproject.school.dname[0,25] + "..." %></td>
</tr>
<% end %>
</tbody>
</table>
model:
class Dproject < ActiveRecord::Base
belongs_to :school, foreign_key: 'scode'
end
controller:
def index
#dprojects = Dproject.order(params[:sort])
respond_with(#dprojects)
end
helper:
module DprojectsHelper
def sortable(column, title = nil)
title ||= column.titleize
link_to title, :sort => column
end
end
I thought I would be able to modify the view with the line:
<th> <%= sortable "dproject.school.dname", "School" %></th>
but that doesn't work. What am I missing? Thanks for any assistance!
I suppose it is because there is no such column (dproject.school.dname) in #dprojects. You need to join the tables in order to access also the columns of the model School.
I was tested the sorting on a model Book Author, where Book belongs_to :author, pretty similar to your. For the sorting to work I did like what follows:
In controller there is a join table, note the aliases (AS):
sort_by = params[:sort] || 'author_name'
#books = Book.joins(:author).select('books.name AS book_name, authors.name AS author_name').order(sort_by)
I used sort_by to avoid ambiguous column name, as for me there is name column in both models.
Then in view:
<p>id | <%= sortable 'book_name', 'Book' %> | <%= sortable 'author_name', 'Author' %></p>
<% #books.each do |book| %>
<p><%= book.book_name %> | <%= book.author_name %> </p>
<% end %>

What is the correct associations for join tables in Ruby on Rails?

So I have a recipes app that I'm working on and I can't understand why I'm not getting something to display. I'm using Recipe as a join table and for simplicity I only included it along with three other tables. For purposes of the app the only thing I'm wanting to display is the name associated on each model.
I have the following models:
Vegetable
Protein
Starch
Recipe
Recipe is acting as the join table and has:
belongs_to :vegetable
belongs_to :protein
belongs_to :starch
accepts_nested_attributes_for :vegetable, :protein, :starch
Each of the other model has:
has_one :recipe
So my thought for the view was a simple iteration
<table>
<thead>
<tr>
<th> Vegetable Name </th>
<th> Protein Name </th>
</tr>
</thead>
<% #recipes.each do |recipes| %>
<tr>
<td> <%= recipe.vegetable.name %> <td>
<td> <%= recipe.protein.name %> <td>
</tr>
Yet nothing is coming up beyond the headers. I've done various things with the iteration like changing recipes to recipe, passing recipe as an argument at the end of each column. I've made sure that my Recipe controller has the following:
def recipe_params
params.require(:recipe).permit(:vegetable_id, :protein_id, :starch_id)
end
Am I wrong in my associations and that's why it's not presenting anything?
I think it is a typo. Use this:
<% #recipes.each do |**recipe**| %>
<tr>
<td><%= recipe.vegetable.name %><td>
<td><%= recipe.protein.name %><td>
</tr>
<%end%>

Retrieve info from last record of association

I have a model Lead which has a has_many Relationship with Activity.
I want to display a list of all leads on the leads index page, including a count of all activities and the timestamp of the latest activity of each lead.
The model looks like this:
class Lead < ActiveRecord::Base
has_many :activities, -> { order("activitytimestamp DESC") }, dependent: :destroy
class Activity < ActiveRecord::Base
belongs_to :lead
The view looks like this:
<table>
<thead>
<tr>
<th>Activity | last</th>
...
</tr>
</thead>
<tbody>
<% #leads.each do |lead| %>
<tr>
<td><%= lead.activities.size %> | <%= lead.activities.last %></td>
...
</tr>
<% end %>
</tbody>
</table>
Obviously lead.activities.last doesn't work.
What do I need to do to display the timestamp of the latest lead.activities Record?
You're so close!
General configuration of a general attribute of the most recent record related to a specific record is:
specific_record.related_records.last.general_attribute
or, in your case, I believe:
lead.activities.last.timestamp_field
The issue with
leads.activities.last
is that it returns the object, not the information in the field of that object, which is what you're looking for.

Resources