I'm using the bootstrap3-datetimepicker-rails gem to let users store the scheduled_date of a WorkOrder in my application (a 'DateTime' property), but I'm getting an argument out of range error when the user submits the form to create the WorkOrder, and the date is very different than what was selected whenever the user pops open the edit screen. The funny thing is that it used to work, but I don't know what code could have changed to break it.
I added the required dependencies & included the proper directives in my CSS/JS files:
gem 'momentjs-rails', '~> 2.5.0'
gem 'bootstrap3-datetimepicker-rails', '~> 3.0.0'
As far as I can tell, my code looks identical to the example on the documentation. Here's the snippet of my form:
<div class="row">
<div class="col-md-4">
<div class="form-group">
<%= f.label :scheduled_date %>
<div class='input-group date'>
<span class="input-group-addon"><span class="fa fa-calendar"></span></span>
<%= f.text_field :scheduled_date, class: 'form-control input-lg', id: "service_date_picker" %>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(function () {
$('#service_date_picker').datetimepicker({
icons: {
time: "fa fa-clock-o",
date: "fa fa-calendar",
up: "fa fa-arrow-up",
down: "fa fa-arrow-down"
}
});
});
</script>
EDIT (forgot to add controller code - super simple):
work_orders_controller.rb
def create
#work_order = WorkOrder.new(work_order_params)
... [it errors on the line above]
end
And my parameter whitelist:
def work_order_params
params.require(:work_order).permit(:caller_name, :brief_job_details, :contract_price, :quoted_by, :job_description, :scheduled_date, :time_materials_details, :sheduled_time, :contact_name, :payment_method, :notes, :customer_id, :job_site_id)
end
And an example of the parameters that give the argument out of range error when I save the form:
work_orders_attributes"=>{"0"=>{"caller_name"=>"Justin", "time_materials_details"=>"", "contract_price"=>"", "quoted_by"=>"", "payment_method"=>"", "job_description"=>"", "scheduled_date"=>"05/23/2014 1:28 PM", "notes"=>""}}
Same as my customers_controller.rb where I have a nested form for a WorkOrder inside of the new customer form (everything else on that form works perfectly):
def create
#customer = Customer.new(customer_params)
... [errors above]
end
The date and time saves correctly if it is within 24 hours of now, but even when it saves correctly, the date displays completely weird and unformatted in the text field when I go to edit that WorkOrder. For instance:
When I select the date from the date picker: 05/06/2014 10:28 AM
When I edit the WorkOrder: 2014-06-05 10:28:00.000000
Any ideas? Any preference for whether I should make that field a Date, Time, or DateTime (currently)? Right now, we're working in Central time zone, but that won't always be the case.
Thanks in advance for pointing me in the right direction!
#Uri Agassi is right: it's the values that you're passing to create the WorkOrder that are the most relevant here.
Try putzing around with the custom date formatting options provided to you by bootstrap-datepicker. If you can get a format that looks good and is easy to parse on the backend, then you'll want to intercept that parameter before it goes to the model for validation.
Regardless of what you'll go with for date formatting on the client-side, you'll still want to parse it into a useable Date or DateTime object server-side in your controller. Check out DateTime#strptime. You can also call #strptime on Date.
Untested, but the idea is there:
def create
order_params = work_order_params
order_params[:scheduled_date] = Date.strptime(order_params[:scheduled_date],
'%m/%d/%Y %I:%M %p')
#work_order = WorkOrder.new(order_params)
end
You can remove the modifications from the Controller all together by updating the values in the model. I feel this is a much cleaner (and reusable) approach.
class Work < ActiveRecord::Base
def scheduled_date=(date)
begin
parsed = Date.strptime(date,'%m/%d/%Y %I:%M %p')
super parsed
rescue
date
end
end
end
It's me helped:
To file application.js writing to end file:
$(function() {
$('.datepicker').datepicker({format: 'dd-mm-yyyy'});
});
This plugin uses moment.js. Basically you need to choose the time format you would like.
example
$(function () {
$('#datetimepicker').datetimepicker({format: 'MMMM Do YYYY, h:mm'});
});
Related
I've started playing a bit with the react-rails gem and am struggling to understand why I am unable to render a custom model attribute in react.js.
All database persisted attributes work fine, it's just custom getters that are returning nothing.
For the sake of simplicity, here's my User model with email, first_name and last_name as persisted attributes.
class User < ActiveRecord::Base
def full_name_and_email
"#{first_name} #{last_name} (#{email})"
end
end
When rendering my view, I initialize a react component:
<%= react_component 'Header', { data: current_user } %>
And within the Header component, if I try the following inside the render function:
var user = this.props.data;
...
return(
<p>Welcome {user.email}</p>
)
My rendered HTML is:
<p data-reactid=".0.0.2">
<span data-reactid=".0.0.2.0">Welcome </span>
<span data-reactid=".0.0.2.1">super_admin#email.com</span>
</p>
However if I try
render(
<p>Welcome {user.full_name_and_email}</p>
)
My rendered HTML results in
<p data-reactid=".0.0.2">
<span data-reactid=".0.0.2.0">Welcome </span>
</p>
I'm probably missing something pretty basic here so if anyone could please help me understand what's going on it would be great!
Thanks!
Answering my own question after re-reading the documentation for the gem:
props is either an object that responds to #to_json or an
already-stringified JSON object (eg, made with Jbuilder, see note
below).
And to add methods to to_json
current_user.to_json(methods: :full_name_and_email)
I am very new to Ruby on Rails (4.0), and I'm struggling to find the best way forward for something I'm attempting to implement. I've been searching for a while and find myself getting even more confused. At its core, I'd like to have a homepage that lets a user have a dropdown populated by my Requirements model, and when the user clicks on a Requirements.title, only those rows with the same title to be displayed. Right now I have the following:
_req_dropdown.html.erb
<div id="category_select">
<%= collection_select(:requirement, :id, Requirement.all, :id, :title, options={:prompt => "Select a requirement"}, html_options={:onchange => 'this.form.submit()'} ) %>
</div>
_req_item.html.erb
<ol id="<%= req_item.id %>">
<span class="req_num">R<%= req_item.req_num %></span>
<span class="title"><%= req_item.title %></span>
<span class="description"><%= req_item.description %></span>
</ol>
static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
if signed_in?
#requirement = current_user.requirements.build
#req_items = current_user.req_list.paginate(page: params[:page])
end
end
user.rb
class User < ActiveRecord::Base
def req_list
Requirement.where("user_id = ? ", id)
end
What's the best way to implement a homepage that uses a dropdown to filter data? Any suggestions would be great, and let me know if I haven't added enough info
You can achieve this by using ajax and replacing expected div with new data. I am explaining small code snippet, I hope it will help you.
Load your default page, As there will not be any filter at first point.
Select drop down- Fire ajax call on change event and get new data from db.
= select_tag('new_data', options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"])
// replace below div
.replace_me
Ajax call
// searching the kids when session alone changes
$('#new_data').live('change', function() {
searching_new_data()
}).change();
function searching_new_data()
{
$.ajax({
url: "/controller/methods",
data: { new_data: $('#new_data').val(){
$("#form_loading").show();
},
complete: function(){
$('#form_loading').hide();
},
success: function(html){
$('#form_loading').hide();
$('#loading').empty();
$('#loading').append(html);
}
})
}
controller:
def new_data
// query logic will goes here
end
View:
// replaced view code
_new_data.html.haml
It's brief flow of your requirement.
I am using below button_to tag inside view file (index.html.erb)
<textarea rows="2" cols="20"><%=#write_date%></textarea>
<%= button_to t(:get_date_write_new),channel_get_dates_path(#channel, :write => 1) %>
when i click the button it will get date from device and prints it on screen.
my question is that how do i make call to function "channel_get_dates_path(#channel, :write => 1)" continuously, and display the date in textarea without refreshing the page. by pressing the button only once?
my controller file:
class GetDatesController < ApplicationController
include DateUtilities
before_filter :require_user, :set_channels_menu
def index
#channel = current_user.channels.find(params[:channel_id])
#write_date = #channel.get_dates.write_dates.first
end
def create
#channel = current_user.channels.find(params[:channel_id])
#get_date = #channel.get_dates.write_dates.first
if (#get_date.nil?)
#get_date = GetDate.new
#get_date.channel_id = #channel.id
#get_date.user_id = current_user.id
#get_date.write_flag = params[:write]
end
#get_date.get_date = generate_get_date
#get_date.save
redirect_to channel_get_dates_path(#channel)
end
end
and i have date generation file(myapp/lib) as:
module DateUtilities
def generate_get_date
require 'rubygems'
require 'socket'
hostname = '127.0.0.1'
port = 2000
streamSock = TCPSocket.new( hostname, port )
streamSock.write "ON"
while line = streamSock.gets
k = line
end
k
end
end
In order to change the page without refreshing it, you need AJAX.
This can be done quite easily in rails by passing a :remote => true attribute in a form :
<%= form_tag(myupdate_path, :remote => true) do %>
<%= form_tag(channel_get_dates_path(#channel, :write => 1), :remote => true) do %>
<input type="submit" value="Get Today's Date">
<input id="thedate" type="text" value="<%=#write_date%>">
<% end %>
<% end %>
The remote option will call the myupdate method in your controller, and tell it to render a javascript view instead of a html view. Let's say you have in your controller :
def myupdate
#thedate = params['wathever'] # get the params from the form
end
Then you can add your javascript method in myController/myupdate.js.erb ( instead of myupdate.html.erb). Assuming you're using jquery, this would be
$("#thedate").val("<%= #thedate %>") # dynamically update
By doing this you're able to get the params from the form, process it as you want with a controller, and tell javascript to update your page according to whathever you just put in your instance variable.
Edit : I used your form as the example. Hopefully the javascript is now more clear : the idea of the javascript view is to get the "thedate" html element in your page, and set its value according to the updated instance variable #thedate. This is where you tell javascript to dynamically update your page.
Hope this helps
#Aurel,thanks for your suggestions. i followed your steps.
in my view file changed the code as:
<%= form_tag(channel_get_dates_path(#channel, :write => 1), :remote => true) do %>
<input type="submit" value="Get Today's Date">
<input type="text" value="<%=#write_date%>">
<% end %>
after this when i press the submit button the update method is called(and i can see that device is sending the date), but the date is not displaying in text field. when i refresh the page the last obtained date from device is displayed in text field.
Is it possible to display the date every time when press submit button?
I have a form for payments like this:
<%= f.label :invoice_id %>
<%= f.select(:invoice_id, current_user.outstanding_invoices_collection) %>
<%= f.label :amount %>
<%= f.text_field :amount %>
I wonder if there's a way to populate the value of the amount text field somehow, e.g. with the open balance of the associated invoice?
In my Invoice model have this function:
def balance
payments.map(&:amount).sum - total
end
How can this be done?
Im assuming you want to populate the text box based on the selection of a invoice from dropdown. In that case
The idea is
You need to make a ajax call onchange of the invoice dropdown.
That ajax response should update the value of the text box.
And with rails-3 i think its recommended to do this in unrobustive way. Here is a link you can follow. Start playing with it meanwhile I will try to make something functional. Hope to get a good result again.
Are you looking for how to populate the value only?
Update:
Here is the ajax part
#Application.js or any sutable js file
$(function($) {
$("#your_drop_down_id").change(function() {
#Your the url to your controller action here
$.ajax({url: '/get_amount',
data: 'invoice_id=' + this.value,
dataType: 'script'})
});
});
#in get_amount Action
invoice = Invoice.find(params[:invoice_id]) #Other appropriate logic to get the invoice
#amount = invoice.balance
#get_amount.js.erb
$('#your_text_box_id').val('<%= #amount %>');
#routes.rb
#This part is written following the gist: https://gist.github.com/3889180 by #TinTin
resources :payments do
collection do
get 'get_amount'
end
end
Let me know if any part is confusing to you.
In your controller you can assign any value to any field, and it will be displayed in the view.
def new
#payment = new Payment()
#payment.amount = 100
end
If you want some dynamic value, e.g: based on a combobox selection, then do it in javascript or with AJAX.
I'm trying to get the checkSwear method to run on each textfield before it's submitted..
I have basically this: (stripped down)
<%= form_for(#profile) do |f| %>
<div class="field">
<%= f.label 'I love to ' %>
<%= f.text_field :loveTo %>
</div>
<div class="field">
<%= f.label 'I hate to ' %>
<%= f.text_field :hateTo %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In my controller I have:
def checkSwear
antiSwear.checkSwear(What goes here?)
end
In routes:
match '/check' => 'profiles#checkSwear'
Any help much appreciated!
(checkSwear is a separate gem; i.e. a separate problem! The what does here means what kind of variable is received from the form, to be put through the checkswear gem)
UPDATE:
Sorry for the camelcasing, I'm a Java developer studying Rails etc., old habits die hard. This is for a project. I'm supposed to be writing a small gem to do some ruby logic and apply it to something. The contents of the gem are:
module antiSwear
#swearwords = ["f**k", "f***ing", "shit", "shitting", "lecturer"]
#replacements = ["fornicate", "copulating", "poop", "pooping", "Jonathan"]
def self.checkText(text)
#swearwords.each do |swearword|
if text.include?(swearword)
index = #swearwords.index(swearword)
replacement = #replacements[index]
text.gsub(swearword, replacement)
end
end
return text
end
end
:/
This should really be done in model validations.
class Profile < ActiveRecord::Base
validate :deny_swearing
private
def deny_swearing
if AntiSwear.check_swear(love_to) || AntiSwear.check_swear(hate_to)
errors.add_to_base('Swearing is not allowed.')
end
end
end
That said, if you insist on this being in controller, you can check params[:profile][:love_to] and params[:profile][:hate_to] to see what's been submitted.
P.S. In this example I used proper ruby naming conventions, since we don't use "camelCasing".
Are you doing this as part of validation? You can do it one of a few ways. You can run the check before save, via a custom validation method or override the setter directly. I show you the custom validation approach here:
class Profile < ActiveRecord::Base
validate :clean_loveTo
protected
def clean_loveTo
errors.add(:loveTo, "can't contain swears") if antiSwear.checkSwear(loveTo)
end
end
I'm assuming checkSwear returns a boolean here.
I'd use an intersection on arrays, one of which is the source text split into words, then gsub the replacements in. You have to be sure to have a 1:1 relationship between the words and their replacements, in which case I'd suggest using a hash for your dictionary (coincidentally what hashes are sometimes called in other languages).
module antiSwear
# var names changed for formatting
#swears = ["f**k", "f***ing", "shit", "shitting", "lecturer"]
#cleans = ["fornicate", "copulating", "poop", "pooping", "Jonathan"]
def self.checkText(text)
# array intersection. "which elements do they have in common?"
bad = #swears & text.split # text.split = Array
# replace swear[n] with clean[n]
bad.each { |badword| text.gsub(/#{badword}/,#cleans[#swears.index(badword)] }
end
end
You might need to futz with text.split arguments if the replacement gets hung up on \n & \r stuff.