Working with JSON in Rails - ruby-on-rails

I have a table called "Weights" that holds a user's weight for a specific day. I can retrieve all relevant data as JSON with the following line of code in my controller's index action:
#weights = Weight.where(:user_id => current_user.id).to_json
The output then looks like:
[{"id":72,"user_id":71,"kilograms":94.0,"day":"2016-06-03","created_at":"2016-06-03T06:58:35.139Z","updated_at":"2016-06-03T06:58:35.139Z"},{"id":75,"user_id":71,"kilograms":34.0,"day":"2016-06-02","created_at":"2016-06-03T13:05:49.862Z","updated_at":"2016-06-03T13:05:49.862Z"},{"id":76,"user_id":71,"kilograms":56.0,"day":"2016-05-29","created_at":"2016-06-03T13:06:01.747Z","updated_at":"2016-06-03T13:06:01.747Z"}]
However, what I would need is an output that looks like:
{2016-06-03 => 94.0, 2016-06-02 => 34.0, 2016-05-29 => 56.0}
How can I achieve this? (I just started coding so I'm sorry if this is a really noob question)
Many thanks.
UPDATE My request refers to a chart I want to display using Chartkick. The documentation says:
Times can be a time, a timestamp, or a string (strings are parsed)
<%= line_chart({20.day.ago => 5, 1368174456 => 4, "2013-05-07 00:00:00 UTC" => 7}) %>
My weights_controller.rb index action now
def index
result = {}
Weight.where(:user_id => current_user.id).each do |weight|
result[weight.day] = weight.kilograms
end
end
Thus I need my data in format described above.

Let try this:
#result = {}
Weight.where(:user_id => current_user.id).each do |weight|
result[weight.day] = weight.kilograms
end
Now the result will be a hash:
{'2016-06-03' => 94.0, '2016-06-02' => 34.0, '2016-05-29' => 56.0}
If you want result to be json:
#result.to_json
Update Simply use it in the view for example:
<% #result.each do |day, kg| %>
<p>Day: <%= day %>, Kg: <%= kg %><p>
<% end %>

Related

Kaminari Pagination with Filter

I'm using Kaminari on my site with a 'load more' button to show another six items when clicked. It works great but when I try to add a sorting order it's not passing the params to the link_to_next_page def although I can see it in the html...
The other question asked on this said to pass the params to the link_to_next_page but it doesn't make a difference.
Example: When I try to sort by lowest price > highest price the first six items are sorted but on 'load more' the sorting order is random.
Can anyone advise here??
Thanks.
Some code...
index.html.erb
<div id="offers">
<%= render :partial => #television_offers %>
</div>
<%= link_to_next_page #television_offers, 'Load More', :remote => true, :id=>"load_more_link", :params => params %> </div>
index.js.erb
$('#offers').append("<%= escape_javascript(render :partial => #television_offers)%>");
$('#load_more_link').replaceWith("<%= escape_javascript(link_to_next_page(#television_offers, 'Load More', :remote => true, :id=>'load_more_link', :params => params))%>");
application_helper.rb
def link_to_next_page(scope, name, options = {}, &block)
param_name = options.delete(:param_name) || Kaminari.config.param_name
link_to_unless scope.last_page?, name, {param_name => (scope.current_page + 1)}, options.merge(:rel => 'next') do
block.call if block
end
end
television_offers_controller.rb
def index
#television_offers = TelevisionOffer.page(params[:page]).per(6)
if params[:filter] == "large_screens"
#television_offers = #television_offers.large_size
elsif params[:filter] == "small_screens"
#television_offers = #television_offers.small_size
elsif params[:filter] == "price"
if params[:order] == "asc"
#television_offers = #television_offers.asc(:offer_price)
else
#television_offers = #television_offers.desc(:offer_price)
end
else
#television_offers = #television_offers.best
end
end
For anyone experiencing the same problem this was solved by simply updating kaminari to the latest version

Getting strange error when searching by date

I'm trying to make report page, on which user will choose start and end date and push buttopn report. Then hidden div became visible.
My search isn't on partial.
I am using jquery_datepicker so here is my code from view:
<%= form_tag(:controller => "financial_reports", :action => "index", :method => "post")%>
<%= datepicker_input "financial_report","start_date", :dateFormat => "dd/mm/yy" %>
<%= datepicker_input "financial_report","end_date", :dateFormat => "dd/mm/yy" %>
<%= submit_tag "Run Report"%>
<% end %>
Here is my code from controller:
def search
#financial_reports = current_user.financial_reports.search(params[:start_date], params[:end_date]
render :index
end
In my Model:
def self.search(from,to)
find(:all, :conditions => [ "BETWEEN ? AND ?", from, to])
end
And it gives me error:
ActiveRecord::StatementInvalid in FinancialReportsController#search
SELECT `financial_reports`.* FROM `financial_reports` WHERE `financial_reports`.`user_id` = 67 AND (BETWEEN NULL AND NULL)
and below this:
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"AMobLLRV3aAlNn6b4Au+1nRP2AN1TLQcBCytBXhDA/g=",
"type"=>"",
"financial_report"=>{"start_date"=>"05/08/2012",
"end_date"=>"11/08/2012"},
"commit"=>"Run Report",
"method"=>"post"}
Where is my error ?
If both parameters are set at all times, you can use:
#financial_reports = current_user.financial_reports.where(:created_at => ((params[:start_date].to_date)..(params[:end_date].to_date))
If that's not the case, you could (for example) do this:
#financial_reports = current_user.financial_reports
if params[:start_date].present?
#financial_reports = current_user.financial_reports.where("created_at >= ?", params[:start_date])
end
if params[:end_date].present?
#financial_reports = current_user.financial_reports.where("created_at <= ?", params[:end_date])
end
You will probably want to encapsulate this in scopes.

Assigning array name to a variable and sorting in RoR

Absolute RoR newbie here, I'm trying to render out multiple leagues in a loop, incrementing the div_# each time, here's a cut down version, without the html. It works when I hard code div_1 or div_2 to be sorted, but div_name doesn't work, even though it has the right contents I need it to be seen as the array.
<% div_1 = Array.new
div_1 << { :Name => 'Rob', :Played => '2', :Won => '1', :Lost => 1, :Points => 4}
div_2 = Array.new
div_2 << { :Name => 'Gavin', :Played => '2', :Won => '1', :Lost => 1, :Points => 4}
for i in (1..2)
i = i.to_s
div_name = "div_" + i
div_name.sort_by { |position| position[:Points] }.reverse!.each do |position| %>
<%= position[:Name] %>
There are lots of problems here:
div_1 = Array.new
div_1 << { :Name => 'Rob', :Played => '2', :Won => '1', :Lost => 1, :Points => 4}
div_1 is now an array with a single element, which is a hash. You don't need an array if you'll just have one element in it.
for i in (1..2)
Where's the block for this loop? After that statement, i is still undefined, so when you call
i = i.to_s
you'll get a NameError.
div_name = "div_" + i
Even if i == 1, div_name will be a string with value 'div_1', and not a copy or instance of the div_1 variable you define above.
div_name.sort_by { |position| position[:Points] }.reverse!.each do |position| %>
Now you're trying to call sort_by on a string, which doesn't respond to that, because it doesn't make sense.
<%= position[:Name] %>
You don't have a variable named position defined at this scope.
Also, when you find yourself putting lots of logic inside of a view within <% %> tags, that's a sign that you need to move that code elsewhere, like to the controller. You could define and calculate #positions as an array of hashes in the controller, and then in the view do something like:
<% #positions.each do |position| %>
<%= position[:name] %>
<% end %>

form_for, fields_for and two models

I have form that create two objects and save them to database.
I want to do next things:
save data in database (booth objects)
validate fields (I have validation in model)
and if validation fail, I want to populate fields with entered data
edit action for this form
Problems:
If I use #report I get:
Called id for nil, which would
mistakenly be 4 error
(can't find object). I have in controller, in encreate action #report = ReportMain.new and in action that render that view.
When I use :report_main (model name) it works, it save data to database, but I can't get fields populated when validation fails.
Questions:
What to do with this two models to make this to work (validation, populating fields, edit)?
Can you give me some advice if approach is wrong?
My view looks like this:
<%= form_for(#report, :url => {:action => 'encreate'}) do |f| %>
<%= render "shared/error_messages", :target => #report %>
<%= f.text_field(:amount) %>
<% fields_for #reporte do |r| %>
<%= r.check_box(:q_pripadnost) %>Pripadnost Q listi
<%= select_tag('nacinpakovanja',options_for_select([['Drveno bure', 'Drveno bure'], ['Kanister', 'Kanister'], ['Sanduk', 'Sanduk'], ['Kese', 'Kese'], ['Posude pod pritiskom', 'Posude pod pritiskom'], ['Kompozitno pakovanje', 'Kompozitno pakovanje'], ['Rasuto', 'Rasuto'], ['Ostalo', 'Ostalo']])) %>
<%= r.text_field(:ispitivanjebroj) %>
<%= r.text_field(:datumispitivanja) %>
<% end %>
<input id="datenow" name="datenow" size="30" type="text" value="<%= #date %>">
<div class="form-buttons">
<%= submit_tag("Unesi izvestaj") %>
</div>
<% end %>
encreate actin in ReportController:
def encreate
#report = ReportMain.new
#reporte = ReportE.new
#reportparam = params[:report_main]
#report.waste_id = params[:waste][:code]
#report.warehouse_id = Warehouse.find_by_user_id(current_user.id).id
#report.user_id = current_user.id
#report.company_id = current_user.company_id
#report.amount = #reportparam[:amount]
#report.isimport = false
#report.isfinished = false
#report.reportnumber = ReportMain.where(:company_id => current_user.company_id, :isimport => false).count.to_i+1
if #report.save
#reporte.report_main_id = #report.id
else
redirect_to(:action => 'exportnew')
return
end
#reporte.vrstaotpada = params[:vrstaotpada]
#reporte.nacinpakovanja = params[:nacinpakovanja]
#reporte.ispitivanjebroj = #reportparam[:ispitivanjebroj]
#reporte.datumispitivanja = #reportparam[:datumispitivanja]
#reporte.q_pripadnost = #reportparam[:q_pripadnost]
#reporte.datumpredaje = #date
if #reporte.save
redirect_to(:action => 'show', :id => #reporte.id)
else
redirect_to(:action => 'exportnew')
end
end
I think your problem in this case is that you use redirect_to instead of render. When you use redirect_to then you lose all the variables from your current action. I would probably do something like this in your encreate action:
if #reporte.save
render :show
else
render :exportnew
end
When you use render then it will use the variables from the current action but the view from the action you send to the render method. So when form_for is called with the #report variable, it is already populated with the values that was sent to encreate. Just make sure that you use the same variable names in the different actions but it looks like you do that already.

Rails form params changing in controller

I have a form:
<%= form_for(:report_main, :url => {:action => 'exporttoxiccreate'}) do |f| %>
<%= collection_select(:waste, :code, Waste.find_all_by_istoxic(false), :id, :code, :include_blank => '') %>
<%= f.check_box(:q_pripadnost) %>
<%= f.text_field(:amount) %>
<% end %>
and this code in controller:
def exporttoxiccreate
#report = ReportMain.new
#reportexport = ReportExport.new
#reportparam = params[:report_main]
#report.waste_id = #reportparam.waste.code
#report.amount = #reportparam.amount
if #report.save
#reportexport.report_main_id = #report.id
else
redirect_to(:action => 'exporttoxicnew')
end
#reportexport.q_pripadnost = #reportparam.q_pripadnost
if #reportexport.save
redirect_to(:action => 'show', :id => #reportexport.id)
else
redirect_to(:action => 'exporttoxicnew')
end
end
I want to save in two tables, in two objects data from this form, and I need to separate params to manipulate with. I tried with this:
#reportexport.q_pripadnost = #reportparam.q_pripadnost
I want to set q_pripadnost field in #reportexport with some value from param.
Where I make mistake?
When you get params from a form in Rails, it comes in the form of a hash. For example:
params[:report_main][:waste]
params[:report_main][:amount]
So when you call #reportparam = params[:report_main], you are setting #reportparam to a hash, but then you are trying to use it later like an object. For example, instead of #reportparam.q_pripadnost, use #reportparam[:q_pripadnost].
You can take a closer look at your variable by temporarily changing your action to show a text version of the variable, for example:
def exporttoxiccreate
#reportparam = params[:report_main]
render :text => #reportparam.to_yaml
end

Resources