I want to have a drop down time select that saves as a string but I keep getting the following exception: 1 error(s) on assignment of multiparameter attributes. Here is the code that I have written:
<%= f.time_select :appointment_time, :minute_step => 5, :ignore_date => true %>
When I submit the form I get the following values in a params hash
"appointment_time(4i)"=>"12", "appointment_time(5i)"=>"00"
Is there any way to easily grab those two values and save the result as "12:00:00"?
Assuming that there are more than just the appointment keys in the params hash:
params[:your_model].select {|k,v| k =~ /^appointment_time/ }.
sort.map {|f| f.last.to_s }.join(':')
Of course, this also assumes that the appointment_time field in your table isn't a DateTime or Date field. You'd have to do this before updating the (assumed) ActiveRecord model instance's attributes. There are simpler ways to do this, but without seeing the code and backtrace it's tough to know whether they'd work.
Edit
processed = params.dup
processed[:your_model][:appointment_time] = params[:your_model].
select {|k,v| k =~ /^appointment_time/ }.sort.map {|f| f.last.to_s}.join(':')
#model.update_params(processed[:your_model])
That's probably more along the lines of what you're looking for.
I solved my problem by creating different columns for each value of the time as strings, and then joining everything together after creation. This is not the most elegant solution, but it works for my application
Related
i have this big problem, i have a input where i format my amounts like this.
15,550.55, the problem is that once i submit that value it store it as 15.50 because of the BigDecimal Object, it is not taking the whole number.
In my Parameters Im recieving that value as "dr_business_remuneration"=>"15,550.55"
The type of data in my postgresql DB is Numeric(19,2) for that attribute
The only thing i want is that once a submit the value be stored as 15550.55, but be shown in my view as 15,550.55.
i tried with a method in my model with a before_save callback, that erase my "," before saving that value.
before_save: montos_formateados
def montos_formateados
if !self.dr_business_remuneration.blank?
self.dr_business_remuneration.sub(",", "").to_f
end
end
but returns this error.
no implicit conversion of String into Integer
There are a few ways to do this. First, if you want it coded to show in terminal correctly, this should work:
'15550.55'.reverse.scan(/.{1,3}/).join(',').reverse
If you're displaying it on a webpage, this is the best:
<%= number_with_delimiter(#number, :delimiter => ',') %>
If you're OK with a few additional dependencies, this is probably the best way:
require 'active_support'
require 'active_support/core_ext/numeric/conversions'
number = 15550.55
number.to_s(:delimited) # => "12,345"
number.to_s(:delimited) # => "12,345.6789"
I hope that helps!
I'm importing a csv file into pg database, and am getting this error that I never got before upgrading to Rails 5
def self.assign_from_row(row)
member = Member.where(membership_id: row[:membership_id]).first_or_initialize
member.assign_attributes row.to_hash.slice(
:last_name, :first_name, :membership_id, :email
).merge(
:birthday => row[4].nil? ? nil : DateTime.strptime(row[4], "%m/%d/%Y").strftime("%Y/%m/%d")
)
member
end
The exact error is with the birthday line. When I remove from .merge to ), things work. The csv headers look like this:
"Last Name","First Name","Membership Id","E-mail","Birthday"
and the rows look like this:
"Aber","Barbara","00591 2","bab#example.com","07/05/2015"
I have also tried this line
:birthday => DateTime.strptime("%m/%d/%Y").strftime("%Y/%m/%d")
I believe the problem lies in the fact that many of the birthdays are populated with "", or are nil and I don't know how to tell the database to insert nil when it is expecting a date format. Any help most appreciated
You can rescue nil if the date conversion fails.
:birthday => (DateTime.strptime(row[4], "%m/%d/%Y").strftime("%Y/%m/%d") rescue nil)
In line rescue is generally not recommended as it can mask other raised exceptions (for example, if you accidentally typed DateTim instead of DateTime you wouldn't spot the problem) but used with care, in line rescue is a useful tool.
I had to go back to the csv original, open it in Office Calc and change the cells containing the date as a string. I first changed the column to a number, then a date with a format to match the sql format '2015-02-23' and it imported just fine. Thanks everybody!
So it wasn't a Rails issue to begin with, but rather the misidentification of the column. I actually had to go through some hoops in Calc to do it. I had to change the column to a number first, then to a date.
I have some code that is chugging through a set of Rails Active Record models, and setting an attribute based on a related value from a 2D Array.
I am essentially setting a US State abbreviation code in a table of US States which was previously only storing the full names. A library of state names is being used to derive the abbreviations, and it contains a 2D Array with each sub-array having a full name, and an abbreviation (i.e., [['New York', 'NY']['Pennsylvania', 'PA'][etc]]). I compare the state name from each record in the database to each full text name in this Array, then grab the corresponding sibling Array cell when there is a match.
This code works fine, and produces the correct results, but its frumpy looking and not easily understood without reading many lines:
# For the following code, StatesWithNames is an Active Record model, which is
# having a new column :code added to its table.
# Sates::USA represents a 2D Array as: [['StateName', 'NY']], and is used to
# populate the codes for StatesWithNames.
# A comparison is made between StatesWithNames.name and the text name found in
# States::USA, and if there is a match, the abbreviation from States::USA is
# used
if StatesWithNames.any?
StatesWithNames.all.each do |named_state|
if named_state.code.blank?
States::USA.each do |s|
if s[0] == named_state.name
named_state.update_column(:code, s[1])
break
end
end
end
end
end
What is the most Ruby style way of expressing assignments with logic like this? I experimented with a few different procs / blocks, but arrived at even cludgier expressions, or incorrect results. Is there a more simple way to express this in fewer lines and/or if-end conditionals?
Yea, there is a few ifs and checks, that are not needed.
Since it is Rails even though it does not state so in question's tags, you might want to use find_each, which is one of the most efficient way to iterate over a AR collection:
StatesWithNames.find_each do |named_state|
next unless named_state.code.blank?
States::USA.each do |s|
named_state.update_column(:code, s[1]) if s[0] == named_state.name
end
end
Also be aware, that update_column bypasses any validations, and if you wish to keep your objects valid, stick to update!.
And last thing - wrap it all in transaction, so if anything goes wrong all the way - it would rollback any changes.
StatesWithNames.transaction do
StatesWithNames.find_each do |named_state|
next unless named_state.code.blank?
States::USA.each do |s|
named_state.update!(:code, s[1]) if s[0] == named_state.name
end
end
end
You might use a different data structure for this.
With your existing 2D array, you can call to_h on it to get a Hash where
a = [['California', 'CA'], ['Oregon', 'OR']].to_h
=> { 'California' => 'CA', 'Oregon' => 'OR' }
Then in your code you can do
state_hash = States::USA.to_h
if StatesWithNames.any?
StatesWithNames.all.each do |named_state|
if named_state.code.blank?
abbreviation = state_hash[named_state.name]
if !abbreviation.nil?
named_state.update_column(:code, abbreviation)
end
end
end
end
the first thing you want to do is convert the lookup from an array of arrays to a hash.
state_hash = States::USA.to_h
if StatesWithNames.any?
StatesWithNames.all.select{|state| state.code.blank?}.each do |named_state|
named_state.update_column(:code, state_hash[named_state.name]) if state_hash[named_state.name]
end
end
The answer on this question has provided me with a nice roadmap for how to generate select tags with data from a collection on an association.
This works nicely and everything is going great.
The issue I have now is, how do I handle an empty collection?
With the regular :type => :input, I can just specify :nil => "Some nil message here".
But that doesn't seem to work for the collection, and to make matters worse, when there is nothing in the collection it seems to be displaying some integers (i.e. 1 and 2). I am assuming those are the IDs from the previously displayed objects in the collection, but for obvious reasons that doesn't make much sense.
Any ideas on how I can handle an empty collection with this gem?
Thanks.
Edit 1:
One alternative is to just put my original best_in_place helper tag inside an if statement for when a collection is not nil. But then how does the user edit it when it is blank? Perhaps there may be no way to handle this, because it would involve creating a new record in the collection.
I use a "workaround" for the empty options in a select tag, it could help you:
:type => :select, :collection => #my_colletion || [[I18n.t('common.none'), -1]]
When #my_colletion is nil, it shows a choice named 'None' with id = -1 (wich is not that bad to handle in the backend).
This part of code assumes the #my_collection is an array of arrays like [ [key, value], [key, value], ... ] OR nil.
Although, if you want your MyModel.all collection to fit the conditions for best_in_place, you can use the following:
#my_collection = MyModel.all.map{ |object| [object.name, object.value] }
# => this returns an array like [ [key, value], [key, value], ... ]
# => returns an empty array (NOT nil) if there is no entry in the DB
About the -1 id:
Using the -1 id as 'none' is easy because you don't need to explicitly handle the value nil (tests, etc). With the -1 id, you can use the following:
MyModel.where(id: params[:id]).first # => Returns the first object that has the params[:id]
# if params[:id] is -1, it will return nil and not raise an error.
I hope it helped :)
I cant see what im missing. I have and Order with nested Items, these Items each have a Kind. I want to manipulate the kind_id param from each Item but the "f[:kind_id]" always return 0.
#order.items.each do |f|
f[:kind_id] = Kind.find_by_name(f[:kind_id]).id
end
the params i get is
{"authenticity_token"=>"7wz7ARjwcVvCR/bpp/T04JQIQwHsMKDflF1eMCL8PTU=",
"order"=>{"items_attributes"=>{"1271160144889"=>{"price"=>"2",
"amount"=>"2",
"text"=>"2",
"kind_id"=>"fds",
"_destroy"=>""}},
"total_price"=>"4"}}
The above params is of course test data :)
Because :kind_id is an integer column, ActiveRecord is automatically interpreting it as an integer for you ("fds".to_i #=> 0). You should add attr_accessor :kind_name to the Item model and switch the form field to kind_name. Then you can do
#order.items.each do |f|
f.kind = Kind.find_by_name(f.kind_name)
end