I have the following JSON stored in my database under an column called event (using the json column type).
{
"captable":{
"id":28,
"version":1,
"name":"CapTable",
"company_id":22,
"created_at":"2018-10-31T18:56:03.965Z",
"updated_at":"2018-10-31T18:57:30.626Z",
"total_stocks_in_company":"400.0"
},
"event":{
"status_locked":null,
"id":51,
"price_per_share":"1000.0",
"total_company_stocks_after_event":"400.0",
"name":"2nd event ",
"date":"2018-10-31",
"currency":"SEK",
"valuation":"400000.0",
"created_at":"2018-10-31T18:57:17.282Z",
"updated_at":"2018-10-31T18:57:30.676Z",
"captable_id":28,
"company_id":22,
"snapshot":"{\"captable\":{\"id\":28,\"total_stocks_in_company\":\"400.0\",\"version\":1,\"name\":\"CapTable\",\"company_id\":22,\"created_at\":\"2018-10-31T18:56:03.965Z\",\"updated_at\":\"2018-10-31T18:57:30.626Z\"},\"event\":{\"status_locked\":null,\"id\":51,\"price_per_share\":\"1000.0\",\"total_company_stocks_after_event\":\"400.0\",\"name\":\"2nd event \",\"date\":\"2018-10-31\",\"currency\":\"SEK\",\"valuation\":\"400000.0\",\"created_at\":\"2018-10-31T18:57:17.282Z\",\"updated_at\":\"2018-10-31T18:57:30.665Z\",\"captable_id\":28,\"company_id\":22,\"snapshot\":null},\"shareholders\":[{\"id\":52,\"shareholder\":\"Peter\",\"name\":\"Peter\",\"number_of_stocks\":\"100.0\",\"company_id\":22,\"created_at\":\"2018-10-31T18:55:42.730Z\",\"updated_at\":\"2018-10-31T18:57:30.637Z\",\"ownership_percentage\":\"0.25\",\"email\":\"\",\"telephone\":\"\"},{\"id\":53,\"shareholder\":\"Jane\",\"name\":\"Jane\",\"number_of_stocks\":\"100.0\",\"company_id\":22,\"created_at\":\"2018-10-31T18:55:49.490Z\",\"updated_at\":\"2018-10-31T18:57:30.644Z\",\"ownership_percentage\":\"0.25\",\"email\":\"\",\"telephone\":\"\"},{\"id\":54,\"shareholder\":\"Sally\",\"name\":\"Sally \",\"number_of_stocks\":\"200.0\",\"company_id\":22,\"created_at\":\"2018-10-31T18:55:56.192Z\",\"updated_at\":\"2018-10-31T18:57:30.651Z\",\"ownership_percentage\":\"0.5\",\"email\":\"\",\"telephone\":\"\"}]}"
},
"shareholders":[
{
"id":52,
"shareholder":"Peter",
"name":"Peter",
"number_of_stocks":"50.0",
"company_id":22,
"created_at":"2018-10-31T18:55:42.730Z",
"updated_at":"2018-10-31T18:58:31.406Z",
"ownership_percentage":"0.125",
"email":"",
"telephone":""
},
{
"id":53,
"shareholder":"Jane",
"name":"Jane",
"number_of_stocks":"150.0",
"company_id":22,
"created_at":"2018-10-31T18:55:49.490Z",
"updated_at":"2018-10-31T18:58:31.410Z",
"ownership_percentage":"0.375",
"email":"",
"telephone":""
},
{
"id":54,
"shareholder":"Sally",
"name":"Sally ",
"number_of_stocks":"200.0",
"company_id":22,
"created_at":"2018-10-31T18:55:56.192Z",
"updated_at":"2018-10-31T18:57:30.651Z",
"ownership_percentage":"0.5",
"email":"",
"telephone":""
}
]
}
I can successfully render the JSON to my view using
<%= #event.snapshot %>
However, what I'd like to do now is fill a table in my view using the json column as the data source, but I'm having trouble figuring out where to put the logic, whether ot have it in the view of have a separate method in either the controller or model.
What I'd love to do is have a table that looks like this: (pseudocode)
<table class="table">
<tr>
<th>Shareholder</th>
<th>Name</th>
<th>Number of Shares</th>
<th>Ownership %</th>
</tr>
<%= #event.snapshot["shareholders"].each do |shareholder| %>
<tr>
<td><%= shareholder.shareholder %></td>
<td><%= shareholder.name %></td>
<td><%= shareholder.number_of_stocks %></td>
<td><%= shareholder.ownership_percentage %></td>
</tr>
<%= end %>
</table>
Can someone help point me in the right direction when it comes to filling a table using a json object instead of simply values from the database?
To clarify: how should I best access the shareholders when iterating through the JSON (i.e. <%= #event.snapshot["shareholders"].each do |shareholder| %> ) in order to create a new table row for each of them?
If you have a Shareholder model with the necessary attributes you can use the JSON to populate objects and then do pretty much what you did above. Note: the first line of the loop now creates a new object for each shareholder entry.
You'll need to parse the JSON first.
<% snapshot_json = JSON.parse(#event.snapshot) %>
<% snapshot_json["shareholders"].each do |shareholder_hash| %>
<% shareholder = Shareholder.new(shareholder_hash) %>
<tr>
<td><%= shareholder.shareholder %></td>
<td><%= shareholder.name %></td>
<td><%= shareholder.number_of_stocks %></td>
<td><%= shareholder.ownership_percentage %></td>
</tr>
<%= end %>
If you don't want to create a new class/model you can just use the hash form of the JSON directly ...
<% snapshot_json = JSON.parse(#event.snapshot) %>
<% snapshot_json["shareholders"].each do |shareholder| %>
<tr>
<td><%= shareholder["shareholder"] %></td>
<td><%= shareholder["name"] %></td>
<td><%= shareholder["number_of_stocks"] %></td>
<td><%= shareholder["ownership_percentage"] %></td>
</tr>
<%= end %>
I think this is simple but I'm just not getting it. I need to join 3 tables and have rails return values from all 3. I have done a join but rails only returns values from 1 table. I think I just don't know the syntax
Here is my controller method
#previous_results = Test.joins(:run, :detail).where("runs.name = ? AND tests.name = ?", #run.name, #test.name).last(1000)
That does do a join here is the sql from it
SELECT `tests`.* FROM `tests` INNER JOIN `runs` ON `runs`.`id` = `tests`.`run_id` INNER JOIN `details` ON `details`.`test_id` = `tests`.`id`
WHERE (runs.name = 'SNMSubscriberSpecificTemplatesFeedsTest' AND tests.name = 'testSitePrefixFalseForNTINSequentialList') ORDER BY `tests`.`id` DESC LIMIT 1000
all I need to do is return values from the details table also. I want 2 column values from details essentially instead of doing test .* I was test.id, test.name, detail.text, detail.message as my return
Int active record how do I tell it to not just return test table data but also include columns in details
This query in SQL does what I want I need to know how to active record it
SELECT `tests`.*, `details`.`detail_text`, `details`.`detail_error`
FROM `tests`
INNER JOIN `runs` ON `runs`.`id` = `tests`.`run_id`
INNER JOIN `details` ON `tests`.`id` = `details`.`id`
WHERE (runs.name = 'SNMSubscriberSpecificTemplatesFeedsTest' AND tests.name = 'testSitePrefixFalseForNTINSequentialList')
ORDER BY `tests`.`id` DESC LIMIT 1000
#tests = Test
.select('tests.*', 'details.detail_text', 'details.detail_error')
.joins(:run, :detail)
.where(
runs: { name: 'SNMSubscriberSpecificTemplatesFeedsTest' },
tests: { name: 'testSitePrefixFalseForNTINSequentialList' }
)
.limit(1000)
.order(id: :desc)
your views would look like:
<table>
<tr>
<th>Test ID</th>
<th>Test Detail's Detail Text</th>
<th>Test Detail's Detail Error</th>
</tr>
<% #tests.each do |test| %>
<tr>
<td><%= test.id %></td>
<td><%= test.detail_text %></td>
<td><%= test.detail_error %></td>
</tr>
<% end %>
</table>
Recommendation:
do not use select() explicitly to fetch the "associated values", but instead access them directly through the objects, like below
#tests = Test
.joins(:run, :detail).includes(:detail)
.where(
runs: { name: 'SNMSubscriberSpecificTemplatesFeedsTest' },
tests: { name: 'testSitePrefixFalseForNTINSequentialList' }
)
.limit(1000)
.order(id: :desc)
your views would look something like:
<table>
<tr>
<th>Test ID</th>
<th>Test Detail's Detail Text</th>
<th>Test Detail's Detail Error</th>
</tr>
<% #tests.each do |test| %>
<tr>
<td><%= test.id %></td>
<td><%= test.detail.detail_text %></td>
<td><%= test.detail.detal_error %></td>
</tr>
<% end %>
</table>
been teaching myself how to build a simple ruby/rails site. trying now to figure out the caveats for data manipulation. group is working, how do i "sum" all the columns?
index.html.erb
<table>
<tr>
<th>Site</th>
<th><7days</th>
<th>>7days</th>
<th>>30days</th>
<th>>90days</th>
<th>>180days</th>
<th>>365days</th>
</tr>
<tr>
<% #gdcomets.each do |dcomet| %>
<td><%= dcomet.site %></td>
<td><%= #sum1 %></td>
<td><%= #sum2 %></td>
<td><%= #sum3 %></td>
<td><%= #sum4 %></td>
<td><%= #sum5 %></td>
<td><%= #sum6 %></td>
</tr>
<% end %>
</table>
dcomets_controller
class DcometsController < ApplicationController
# GET /dcomets
# GET /dcomets.json
def index
#dcomets = Dcomet.all
#gdcomets = Dcomet.group(:site)
#sum1 = #gdcomets.map(&:ls7day).sum
#sum2 = #gdcomets.map(&:gt7day).sum
#sum3 = #gdcomets.map(&:gt30day).sum
#sum4 = #gdcomets.map(&:gt90day).sum
#sum5 = #gdcomets.map(&:gt180day).sum
#sum6 = #gdcomets.map(&:gt365day).sum
respond_to do |format|
format.html # index.html.erb
format.json { render json: #gdcomets }
end
end
end
#sum = #gdcomets.map(&:data).sum
:data being the name of the column you want to sum.
You'll get better performance letting SQL do the donkey work of summing everything:
Dcomet.group(:site).sum(:data)
Where :data is the name of column you want to sum. That will return a hash with the keys being the site values, and the values the corresponding sum for that site
I'm trying to submit multiple entries into the database from an array. So, I create multiple new entries and store them in an array. In the view, I have a form of checkboxes for the user to check which ones he/she wants to add to the database. Upon clicking submit, I would like to add each of these forms to the database all in on shot. Here is the code:
Controller:
class EventsBoysController < ApplicationController
def new
#season = find_season
#meet = find_meet(#season)
#athletes_boys = current_coach.athletes.where(boy: true)
#events_boys = []
#athletes_boys.each do |athlete|
#events_boys << #meet.events_boys.new(:athlete_id => athlete.id)
end
#events = ["400 IH", "100", "1600", "400", "110 HH", "800", "3200", "200"]
end
def create
debugger
#season = find_season
#meet = find_meet(#season)
#events_boys = #meet.events_boys.create(events_boy_permit)
# debugger
if #events_boys.save
redirect_to #events_boys, notice: 'Season was successfully created.'
else
render action: "new"
end
end
private
def find_season
Season.find(params[:season_id])
end
def find_meet season
season.meets.find(params[:meet_id])
end
def events_boy_permit
params.require(:events_boy).permit(:season_id, :meet_id, :athlete_id, :boys_400_m_im, :boys_1600_m, :boys_400_m, :boys_110_m_hh, :boys_800_m, :boys_3200_m, :boys_200_m, :boys_100_m, :time_400_m_im, :time_1600_m, :time_400_m, :time_110_m_hh, :time_800_m, :time_3200_m, :time_200_m, :time_100_m, :place_400_m_im, :place_1600_m, :place_400_m, :place_110_m_hh, :place_800_m, :place_3200_m, :place_200_m, :place_100_m)
end
end
View:
<h1><%= "Create new events for the boys for #{#meet.name}" %></h1>
<table id="events-table">
<tr>
<th></th>
<% #events.each do |event| %>
<th><%= event %></th>
<% end %>
</tr>
<% #events_boys.each do |event| %>
<tr>
<td><%= Athlete.find_by_id(event.athlete_id).name %></td>
<%= form_for [#season, #meet, event], :html => { :mulitpart => true } do |f| %>
<td><%= f.check_box :boys_400_m_im %></td>
<td><%= f.check_box :boys_100_m %></td>
<td><%= f.check_box :boys_1600_m %></td>
<td><%= f.check_box :boys_400_m %></td>
<td><%= f.check_box :boys_110_m_hh %></td>
<td><%= f.check_box :boys_800_m %></td>
<td><%= f.check_box :boys_3200_m %></td>
<td><%= f.check_box :boys_200_m %></td>
<td><%= f.submit "Submit", :class => 'btn' %></td>
<% end %>
</tr>
<% end %>
</table>
<script type="text/javascript">
var athletes = new Array();
var arrayInAthletes = new Array();
element = document.getElementById("events-table");
var athletesArray = element.children[0].children
for (i=1; i < athletesArray.length; i++) {
var rowArray = athletesArray[i].children;
arrayInAthletes = [];
arrayInAthletes[0] = rowArray[0].innerText;
var sum = 0;
for (j=1; j < rowArray.length; j++) {
var checkBox = rowArray[j].children[0];
var checkedValue = $('#'+checkBox.id+':checked').val();
if (checkedValue === "1") {
arrayInAthletes[sum+1] = rowArray[j].children[0].id;
sum += 1;
}
}
athletes[i-1] = arrayInAthletes;
}
</script>
I think what you are looking for is something like the code below (needs to be adapted to your example).
Contact.create([
{first_name: 'Ryan', last_name: 'Smith', email: 'ryan#smith.com'},
{first_name: 'John', last_name: 'Doe', email: 'john#doe.com'}
])
All you need to do is put your data into an array of hashes. Each hash is an object you want to save. This will do a batch insert, which is what I think you want.
You will need to pull the values for checked/unchecked from your params since that is where they are passed to your controller. Cycle through that hash and perform your logic on that.
I want to display some data from a table and display it in the table cells. I have the following.
Controller
#data = HospitalBooking.where(:created_at => #date_range)
#stuff = []
#stuff[0] = []
index = 0
#stuffs.each do |stuff|
#rotated[0][index] = stuff.detail0
index += 1
end
Not sure if I have gone about this the correct way also how would I display it in my view
If I understood it right, you want to display the result of a query in a html table.
Here is your query, in your controller:
#data = HospitalBooking.where(:created_at => #date_range)
In your view
<table>
<tr>
<th>field1</th>
<th>field2</th>
</tr>
<% #data.each do |data| %> #start loop
<tr>
<td><%= data.field1 %></td> #column field1 in your database
<td><%= data.field2 %></td> #column field2 in your database
</tr>
<% end %> #end loop
</table>