Select specific key from hash in Ruby - json

I have the following JSON which I convert to hash:
<%
json = '{
"speed": 50,
"braking": 50,
"time_on_task": 50
}'
json = JSON.parse(json)
%>
And currently I just loop through them and display them:
<ul>
<% json.each do |t| %>
<li><%= "<b>#{t.first.humanize}</b>: #{t.last}".html_safe %></li>
<% end %>
</ul>
However I'd like to build a method that can pick an particular item by its key name. e.g. show_score(json, 'speed')
I tried:
def show_score(hash, key)
hash.select { |k| k == key }
end
Which just returns: {"speed"=>50}
So I tried:
hash.select { |k, h| "<b>#{k.humanize}</b>: #{h}".html_safe if k == key }
But it returns the same...
How can I get to just return the string in the format I want if they key matches?

def show_score(hash, key)
"<b>#{key.humanize}</b>: #{hash[key]}"
end
And I'd change this
<%
json = '{
"speed": 50,
"braking": 50,
"time_on_task": 50
}'
json = JSON.parse(json)
%>
into
<%
hash = {
"speed" => 50,
"braking" => 50,
"time_on_task" => 50
}
json = hash.to_json
%>

I think you're thinking too hard, or maybe I'm not understanding your question fully.
<ul>
<% json.each do |k,v| %>
<li><%= "<b>#{k.humanize}</b>: #{v}".html_safe %></li>
<% end %>
</ul>
ps. using Enumerable#detect is so much faster than Enumerable#select.first

Related

Usage of array with MySQL Rails 4

I am trying to change in my "seeker_cvs" table column "location_id". It was an integer type. Now I want to make it as an array. (I am forced to make it without many-to-many association). So my model is:
class SeekerCv < ActiveRecord::Base
belongs_to :location, class_name: 'Category'
serialize :location_id, Array
end
Category has many seeker_cvs.
Also I have added and run new migration:
class ChangeLocationIdOnSeekerCvs < ActiveRecord::Migration
def change
change_column :seeker_cvs, :location_id, :integer, array: true, default: []
end
end
In seekers_cvs controller I have changed in permit "location_id" to "location_id: []":
class SeekerCvsController < ApplicationController
def new
#cv = SeekerCv.new
end
def create
#cv = SeekerCv.new(cv_params)
#cv.seeker = current_seeker
if #cv.save
redirect_to seeker_cv_path(#cv)
else
render :new
end
end
def edit
#cv = SeekerCv.find(params[:id])
authorize #cv
end
def update
#cv = SeekerCv.find(params[:id])
#cv.attributes = cv_params
if #cv.save
redirect_to seeker_cv_path(#cv)
else
render :edit
end
end
private
def cv_params
params.require(:seeker_cv).permit :name,
:category_id,
:no_experience,
location_id: []
end
end
In view I added multiple: true to form:
= simple_form_for #cv, html: { class: 'form-horizontal' } do |f|
.panel.panel-default
.panel-heading
h3.panel-title = t('.cv_name')
.panel-body#cv-category
= f.input :name
= f.input :category_id do
= f.select :category_id,
nested_set_options_opt_mod(Category.category.root.children.to_a) { |i| "#{'-' * i.level} #{i.name}" },
{ disabled: Category.category.find_all { |l| !l.leaf? }.map(&:id), include_blank: true },
{ class: 'form-control' }
= f.input :location_id do
= f.select :location_id,
nested_set_options_opt(Category.location.root) { |i| "#{'-' * i.level} #{i.name}" },
{ disabled: Category.location.root.id, include_blank: true },
{ multiple: true, class: 'form-control' }
But when I am trying to create or update seeker_cv (see picture) I am getting:
ActiveRecord::SerializationTypeMismatch at /app/en/seeker_cvs
Attribute was supposed to be a Array, but was a Fixnum. -- 0
P.S. I need to hold previously created seeker_cvs with location_id with integer type. And new one or updated has to have column with array type
The problem is that mysql doesn't have a native array type. So you have to use varchar as a column type
change_column :seeker_cvs, :location_id, :string

undefined method `[]' for nil:NilClass while importing csv file in rails

I have an application on which I want to provide the feature to import the records from CSV and Excel file formats. I am using roo gem for it, but at the time of importing it gives the error "undefined method `[]' for nil:NilClass".
Here is the code :
student.rb :
require 'roo'
def self.import(file)
spreadsheet = open_spreadsheet(file)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
product = find_by_id(row["id"]) || new
product.attributes = row.to_hash.slice(*accessible_attributes)
product.save!
end
end
def self.open_spreadsheet(file)
case File.extname(file.original_filename)
when ".csv" then Roo::CSV.new(file.path, nil, :ignore)
when ".xls" then Roo::Excel.new(file.path, nil, :ignore)
when ".xlsx" then Roo::Excelx.new(file.path, nil, :ignore)
else raise "Unknown file type: #{file.original_filename}"
end
end
student_controller.rb :
def import
Student.import(params[:file])
redirect_to students_path, notice: "Record imported Successfully."
end
new.html.erb :
<%= form_tag import_students_path, multipart: true do %>
<%= file_field_tag :file , :required=> true%> <br/>
<%= submit_tag "Import" , :class => "btn btn-primary btn-block" %>
<% end %>
Tell me what i am doing wrong?

How to do resolve this? Exporting CSV in Rails 4

I need export archive CSV in my project. Can anyone help me?
My controller
def export
#travel = Travel.find(params[:id])
#expense = #travel.expenses
respond_to do |format|
format.html
format.csv
end
end
My routes
resources :travels do
get 'export' , to: 'travels#export', as: :export
end
Rake routes
travel_export GET /travel/:travel_id/export(.:format) travels#export
My link to download
<%= link_to "CSV", travel_export_path(#travel,format: "csv") %>
My travel.rb
class Travel < ActiveRecord::Base
belongs_to :user
has_many :expenses
end
And finally, my export.csv.rb! I don't know what I need do here.
<%
headers = [
"User",
"Date",
"Location",
"Total",
"Expense",
"Expense value"
]
csv_output = CSV.generate do |csv|
csv << headers
csv << [
current_user,
date.strftime("%d-%m-%Y"),
location,
total
]
#travel_expenses.each do |expense|
csv<<[
expense.typ.description,
expense.value,
]
end
%>
<%= csv_output.html_safe %>
Please, I need help!
I think you are missing one end in export.csv.rb file at the end of #travel_expenses.each

How do I delete records saved with collection_select in Rails?

My goal is to be able to update a saved record when items are de-selected from a collection_select (and then that record is resubmitted.) Thanks in advance for your help!
Details
I've got a form for Newsavedmaps. Newsavedmaps can have many waypoints. Users can select waypoints in a collection_select, and when they save the Newsavedmap, these waypoints are saved to their own database table.
The problem: when users open the Newsavedmap they've saved, I want them to be able to de-select a waypoint. When they save the Newsavedmap again, I want the de-selected waypoint to be deleted.
This is a Rails 2.3X app I'm maintaining, which is why the collection_select uses a different format below.
Model
class Newsavedmap < ActiveRecord::Base
belongs_to :itinerary
has_many :waypoints, :dependent => :destroy
accepts_nested_attributes_for :waypoints, :reject_if => lambda { |a| a[:waypointaddress].blank? }, :allow_destroy => true
end
View
<% form_for #newsavedmap, :html => { :id => 'createaMap' } do |f| %>
<%= f.error_messages %>
<%= f.text_field :name, {:id=>"savemap_name", :size=>30 }%></p>
<%= collection_select :waypoints, :waypointaddress, #newsavedmap.waypoints, :waypointaddress, :waypointaddress, {}, { :multiple => true, :class => "mobile-waypoints-remove", :id =>"waypoints" } %>
<% end %>
Newsavedmaps Controller
def create
#newsavedmap = Newsavedmap.new(params[:newsavedmap])
waypoint = #newsavedmap.waypoints.build
respond_to do |format|
if #newsavedmap.save
flash[:notice] = 'The new map was successfully created.'
format.html { redirect_to "MYURL"}
format.xml { render :xml => #newsavedmap, :status => :created, :location => #newsavedmap }
else
format.html { render :action => "new" }
format.xml { render :xml => #newsavedmap.errors, :status => :unprocessable_entity }
end
end
end
def update
#newsavedmap = Newsavedmap.find(params[:id])
if #newsavedmap.itinerary.user_id == current_user.id
respond_to do |format|
if #newsavedmap.update_attributes(params[:newsavedmap])
flash[:notice] = 'Newsavedmap was successfully updated.'
format.html { redirect_to "MYURL" }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #newsavedmap.errors, :status => :unprocessable_entity }
end
end
else
redirect_to '/'
end
end
Params when creating new record
Parameters: {"newsavedmap"=>{"name"=>"Name of my map", OTHER FIELDS NOT SHOWN ABOVE, "waypoints"=>{"waypointaddress"=>["1600 Pennsylvania Ave NW, Washington, DC 20500", "350 5th Ave, New York, NY 10118"]}}
I think your problem is in correctly built form (and params which come from it).
I suggest to
look at gem cocoon or nested_form
add waypoints_attributes to attr_accessible
implement helpers from gem (from point #1) in your form
And Rails magic should done other job
Another variant (without using gems) (I think much more difficult way!)
You can remove accept_nested_attributes at all and work with your params directly. But in this case you should manage manually all process: correct inserting records, correct destroying them.
In your case it should smth like this (it is not tested!). The example based on your params which posted in the question.
def create
# delete params 'waypoints' it will be manage manually
waypoints = params[:newsavedmap].delete(:waypoints)
#newsavedmap = Newsavedmap.new(params[:newsavedmap])
waypoints.each do |waypoint|
#newsavedmap.waypoints.build(:waypointaddress => waypoint)
end
if #newsavedmap.save
...
end
end
the main troubles will be in method update
def update
# delete params 'waypoints' it will be manage manually
waypoints = params[:newsavedmap].delete(:waypoints)
# find and setup attributes
#newsavedmap = Newsavedmap.find(params[:id])
#newsavedmap.attributes = params[:newsavedmap]
# TROUBLES start here
# destroy not checked (but existed in DB) waypoints
existed_waypoints = #newsavedmap.waypoints
existed_waypoint_addresses = existed_waypoints.map(&:waypointaddress)
new_waypoints = []
waypoints.each do |waypoint|
if existed_waypoint_addresses.include?(waypoint)
# existed waypoint was selected on the form
# find it and add to new_waypoints
new_waypoints << #newsavedmap.waypoints.find_by_waypointaddress(waypoint)
else
# new waypoint was selected on the form
# build it and add to new_waypoints
new_waypoints << #newsavedmap.waypoints.build(:waypointaddress => waypoint)
end
end
# setup new records for waypoints
#newsavedmap.waypoints = new_waypoints
if #newsavedmap.save
# destroy existed but not selected waypoints
(existed_waypoints - new_waypoints).map(&:destroy)
...
end
end

Validations for Importing CSV data into MySql database in Rails 3.1?

i implemented the task of importing data from csv into MySQL database successfully. Now, my requirement is: i need to get error message with line number, if there is any mis match of data in csv file while importing.
This is my controller code:
**require 'csv' #at the top and followed by...
def load_csv
# no code
end
def import_csv
parsed_file = CSV.foreach(params[:csv].tempfile,:headers => true) do |row|
row = row.to_hash.with_indifferent_access
Institute.create!(row.to_hash.symbolize_keys)
redirect_to :action => :index
end
In my view/ load_csv.html.erb:
<%= form_for(:institute, :url => import_csv_institutes_path, :html => {:multipart => true}) do |f| %>
<div class="field">
<%= file_field_tag :csv %>
<%= f.submit 'Import' %>
</div>
<% end %>
These are the only two steps i used for importing. Model validations are working only for form and for csv, an error page displayed..
Please try to help me out.........................
Assign an error message to the flash[:notice] variable in the import_csv method. Do it before redirect.
http://guides.rubyonrails.org/action_controller_overview.html