Easy way to work with date data in the controller? - ruby-on-rails

Working on loading the datetime values being submitted from a datetime_select helper, so i can compare it to the existing saved data.
I'm using the following code, but it feels a bit cumbersome.
DateTime.parse("#{params['start_date(1i)'].to_i}-#{params['start_date(2i)'].to_i}-#{params['start_date(3i)'].to_i} #{params['start_date(4i)'].to_i}:#{params['start_date(5i)'].to_i} -500")
Is there an easier way to build a datetime object?
Edit:
Here's my form code:
= form_for(#charity) do |f|
- if #charity.errors.any?
#error_explanation
%h2
= pluralize(#charity.errors.count, "error")
prohibited this charity from being saved:
%ul
- #charity.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name, 'Name *'
= f.text_field :name
%fieldset
%legend Dates in Eastern Standard Time
.field
= f.label :start_date, 'Start Date *'
= f.datetime_select :start_date, :default => DateTime.now
.field
= f.label :end_date, 'End Date *'
= f.datetime_select :end_date, :default => DateTime.now
.field
= f.label :percentage, 'Percentage of sales to be donated *'
= f.text_field :percentage
.field
= f.label :charity_number, 'The identification number for your charity *'
= f.text_field :charity_number
.field
Donation options:
%span{ title: "Dollar amounts that you wish to allow people to donate on top of their order.", class: "tooltip_hover" }= image_tag "question.png"
- DonationOption.all.each do |option|
= f.label option.id, number_to_currency(option.amount, unit: "$"), class: "donation_label"
= check_box_tag "charity[donation_option_ids][]", option.id, #charity.donation_option_ids.include?(option.id), class: "donation_check"
.actions
= f.submit nil, class: "btn-primary"
Controller:
def update
#charity = Charity.find(params[:id])
respond_to do |format|
if #charity.update_values(params[:charity])
format.html { redirect_to #charity, notice: 'Charity was successfully updated.', :charity => #charity }
format.json { head :ok }
else
format.html { render action: "edit" }
format.json { render json: #charity.errors, status: :unprocessable_entity }
end
end
end
The update_values method:
def update_values(attributes)
s_date = DateTime.parse("#{attributes['start_date(1i)'].to_i}-#{attributes['start_date(2i)'].to_i}-#{attributes['start_date(3i)'].to_i} #{attributes['start_date(4i)'].to_i}:#{attributes['start_date(5i)'].to_i} -500")
attributes.delete('start_date(1i)')
attributes.delete('start_date(2i)')
attributes.delete('start_date(3i)')
attributes.delete('start_date(4i)')
attributes.delete('start_date(5i)')
# if the charity has not started yet
if DateTime.now.utc < self.start_date.utc
self.start_date = s_date
attributes.merge!(reset_create_job)
end
e_date = DateTime.parse("#{attributes['end_date(1i)'].to_i}-#{attributes['end_date(2i)'].to_i}-#{attributes['end_date(3i)'].to_i} #{attributes['end_date(4i)'].to_i}:#{attributes['end_date(5i)'].to_i} -500")
attributes.delete('end_date(1i)')
attributes.delete('end_date(2i)')
attributes.delete('end_date(3i)')
attributes.delete('end_date(4i)')
attributes.delete('end_date(5i)')
if DateTime.now.utc < self.end_date.utc
self.end_date = e_date
attributes.merge!(reset_delete_job)
end
self.update_attributes(attributes)
end

Related

rails: Is it possible that my receiver_id failling to be picked?

I am implementing a messaging solution for my rails app, I keep get the following error.
PG::InvalidTextRepresentation - ERROR: invalid input syntax for integer: ""
LINE 1: ...rsations" WHERE ((sender_id = 3 AND receiver_id = '') OR (se...
class MessagesController < ApplicationController
def create
if current_user.id == message_params[:receiver_id]
redirect_to request.referrer, alert: "You cannot send a message to yourself"
end
conversation = Conversation.where("(sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)",
current_user.id, message_params[:receiver_id],
message_params[:receiver_id], current_user.id
).first
if !conversation.present?
conversation = Conversation.create(sender_id: current_user.id, receiver_id: message_params[:receiver_id])
end
#message = Message.new(user_id: current_user.id,
conversation_id: conversation.id,
content: message_params[:content]
)
if #message.save
format.html { redirect_to request.referrer, notice: 'Message was successfully sent.' }
else
format.json { render json: request.referrer.errors, status: :unprocessable_entity }
end
end
Conversation model.
class Conversation < ApplicationRecord
belongs_to :sender, class_name: "User"
belongs_to :receiver, class_name: "User"
def last_message
message = Message.where(conversation_id: self.id).last
if message.present?
return message
else
return Message.new updated_at: Time.now
end
end
end
That happens because the value you're passing for reciever_id is an empty string, but the data type of that column in your database is an integer.
You can use or to make the query, but it'll transform your empty string to nil:
reciever_id = message_params[:reciever_id]
Conversation.where(sender_id: current_user.id, reciever_id: reciever_id)
.or(Conversation.where(sender_id: reciever_id, reciever_id: current_user.id))
Anyway, you might want to check what you're receiving in order to do the query you're performing. It can be assigning default values, returning early, adding constraints to your routes, etc.
Pasting the form directly works but putting it on the partial does not, i.e below this works.
- if current_user.id != profile.user.id
%small
%button.btn.btn-outline-light{"data-target" => "#modal_large", "data-toggle" => "modal", :type => "button"}
Send Message
= simple_form_for Message.new do |f|
= f.error_notification
= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
.form-inputs
.row
.col
= f.hidden_field :receiver_id, value: profile.user.id
= f.input :body, autofocus: true, label: "Type Your Message Below"
.form-actions
.row
.col
= f.button :submit, "Send Message", class: "btn btn-primary btn-lg mt-2 float-right"
= render partial: "message", locals: { user: profile.user }
This does not work..
#modal_large.modal.fade{"aria-hidden" => "true", "aria-labelledby" => "modal_large", :role => "dialog", :tabindex => "-1"}
.modal-dialog.modal-lg{:role => "document"}
.modal-content
.modal-header
%h5.modal-title Send a New Message
%button.close{"aria-label" => "Close", "data-dismiss" => "modal", :type => "button"}
%i.ti-close.font-size-14
.modal-body.py-4
= simple_form_for Message.new do |f|
= f.error_notification
= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
.form-inputs
.row
.col
= f.hidden_field :receiver_id, value: user.id #profile.user.id
= f.input :body, autofocus: true, label: "Type Your Message Below"
.form-actions
.row
.col
= f.button :submit, "Send Message", class: "btn btn-primary btn-lg mt-2 float-right"
The specific problem is on this line below.
= render partial: "message", locals: { user: profile.user }

Rails has_many update with empty array

There is the following form code:
= form_for #task, html: { class: 'form-horizontal' } do |f|
.form-group
.col-sm-9.col-sm-offset-3
= render partial: 'shared/form_errors', locals: { subject: #task }
.form-group
label.col-sm-3.control-label for='title' Title
.col-sm-9
= f.text_field :title, class: 'form-control', placeholder: 'Title'
.form-group
label.col-sm-3.control-label for='description' Description
.col-sm-9
= f.text_area :description, class: 'form-control', placeholder: 'Description'
.form-group
label.col-sm-3.control-label Teams
.col-sm-9
ul
- Team.all.each do |t|
li
= check_box_tag "team_ids", t.id, #task.teams.include?(t), name: 'task[team_ids][]'
= t.name
.form-group
.col-sm-9.col-sm-offset-3
= f.submit 'Save', class: 'btn btn-success'
As you can see I can select team for my task through checkboxes. My controller:
def update
#task = Task.find(params[:id])
if #task.update(task_params)
redirect_to tasks_path, flash: { alert: TASK_UPDATING_MESSAGE }
else
render 'edit'
end
end
private
def task_params
params.require(:task).permit(:title, :description, team_ids: [])
end
It works good if I update task with some checked teams; but also I want to have ability to check no teams and update taks with empty array of teams. But in this case tasks_params doesn't have team_ids array, and updating doesn't work. How can I fix it? Thanks!
My understanding is that when you submit your form with nothing checked, you have params[:task][:team_ids] = nil.
You can try something like:
def task_params
params[:task][:team_ids] = [] if params[:task][:team_ids].nil?
params.require(:task).permit(:title, :description, team_ids: [])
end
You can do it using collection_check_boxes, just replace the list of teams with:
ul
= f.collection_check_boxes :team_ids ,Team.all, :id, :name do |b|
= content_tag :li, raw("#{b.label { b.check_box } }" + b.object.name)
And this will do the trick.
Note: With this Rails add a hidden field, which fix your issue, also you will fix it only with this:
<input type="hidden" name="task[team_ids][]" value="" autocomplete="off">

Rails Controller Triggering Both Branches Of If-Else Statement

I'm new here so I hope it's appropriate for new accounts to ask questions straight away. I've been working with Rails for sometime now and usually I'm pretty good at researching and solving my own problems - but this one has had me stumped for a few days now.
I have a create action being called in a controller that contains an if-else statement that is conditional based on a check_box post parameter. I can see that the parameter is being posted to the controller so the statement should be able to correctly branch but something strange is happening. The controller executes both branches of the statement, but because my parameters are trimmed depending on that check_box, the second branch always errors out. I'm fairly confident this has little to do with routes.
Please see my code below:
Controller:
def create
#quote = Quote.find(params[:quote_id])
if params[:quote_item][:custom] == 1
#quote_item = #quote.quote_items.new(quote_item_params)
#quote_item.rate = nil
#quote_item.custom = true
#quote_item.unit_price = params[:quote_item][:unit_price]
#quote_item.rate_name = params[:quote_item][:title]
else
#quote_item = #quote.quote_items.new(quote_item_params)
#quote_item.custom = false
#rate = Rate.find(params[:quote_item][:rate_id])
#quote_item.unit_price = #rate.price
#quote_item.rate_name = #rate.product.name
end
respond_to do |format|
if #quote.save
format.html { redirect_to #quote, notice: 'Quote item was successfully added.' }
format.json { render :show, status: :created, location: #quote }
else
format.html { redirect_to #quote }
format.json { render json: #quote.errors, status: :unprocessable_entity }
end
end
View:
<% if #rates.any? %>
<%= bootstrap_form_for([#quote, #quote_item], layout: :inline) do |f| %>
<%= f.text_field :title, class: 'input-sm', hide_label: true, :placeholder => "Line Title" %>
<%= f.select(:rate_id, #rates.collect {|r| [r.select_summary_text, r.id ] }, { hide_label: true }, { :class => 'input-sm' }) %>
<%= f.number_field :quantity, class: 'input-sm', hide_label: true, :min => 1, :length => 2, :value => 1 %>
<%= f.text_field :unit_price, class: 'input-sm', hide_label: true, :min => 1, :length => 2, :prepend => "$" %>
<%= f.text_field :note, class: 'input-sm', hide_label: true, :placeholder => "Note (Optional)" %>
<%= f.submit "Add Quote Item", class: 'btn btn-sm btn-default' %>
<%= f.check_box :custom, label: "Override" %>
<% end %>
<% else %>
<div class="well well-sm"><i class="fa fa-usd"></i> No pricing for this customer has been set. Set product pricing for this jobs customer <%= link_to user_path(#quote.job.user) do %>here.<% end %></div>
<% end %>
My create method errors out here:
#rate = Rate.find(params[:quote_item][:rate_id])
With:
ActiveRecord::RecordNotFound (Couldn't find Rate with 'id'=):
app/controllers/quote_items_controller.rb:19:in `create'
This error is correct though, because the rate ID isn't processed in first branch of the if-else statement. I've tried different check_box form fields, directly overriding 'custom' and both branches still run.
Any help here is greatly appreciated!
The params hash contains strings.
Try swapping:
if params[:quote_item][:custom] == '1'
for your original:
if params[:quote_item][:custom] == 1

Rails Strong_params passing "param is missing"

I have a rails 4.1 app that is using Balanced to process credit cards. The credit card form I have is using ajax to post to the backend but I am getting the following error:
ActionController::ParameterMissing - param is missing or the value is empty
actionpack (4.1.4) lib/action_controller/metal/strong_parameters.rb:183:in `require'
here is my controller:
class TablechargesController < ApplicationController
def new
#event = Event.find(params[:event_id])
#table = #event.tablecharges.build
end
def index
#event = Event.find(params[:event_id])
#table = #event.tablecharges.all
end
def create
#event = Event.find(params[:event_id])
#table = #event.tablecharges.build(table_charge_params)
if #table.save
redirect_to #event, :notice => "Thanks for the cash"
else
render :new
end
end
private
def table_charge_params
params.require(:tablecharge).permit(:uri, event_attributes: :id)
end
end
here is my model:
class Tablecharge < ActiveRecord::Base
belongs_to :event
attr_accessor :cc_name
attr_accessor :cc_number
attr_accessor :cc_expiration_month
attr_accessor :cc_expiration_year
attr_accessor :cc_ccv
attr_accessor :uri
end
here is my Javascript:
jQuery ->
$('#cc-submit').click (e) ->
e.preventDefault()
handleResponse = (response) ->
if (response.status_code == 201)
fundingInstrument = (if response.cards? then response.cards[0] else response.bank_accounts[0])
alert(fundingInstrument.href)
$('#tablecharge_uri').val(fundingInstrument.href)
url = '/events/' + urlid + '/tablecharges'
alert(url)
jQuery.ajax({type: "POST", url: url, data: {uri: fundingInstrument.href, event_id: urlid}, sucess: (data) ->
alert data.id
error: (data) ->
alert "fuck"})
else
alert(response.status + JSON.stringify(response, false, 1))
payload = {
name: $('#cc-name').val()
number: $('#cc-number').val()
expiration_month: $('#cc-expiration-month').val()
expiration_year: $('#cc-expiration-year').val()
ccv: $('#cc-ccv').val()
}
balanced.card.create(payload, handleResponse)
here is my view:
<div class="authform">
<%= javascript_tag do %>
window.urlid = "<%= #table.event_id %>"
<% end %>
<%= simple_form_for [#event, #table] do |f| %>
<%= f.input :cc_name, input_html: {id: 'cc-name'}%>
<%= f.input :cc_number, input_html: {id: 'cc-number'} %>
<%= f.input :cc_expiration_month, as: :integer, input_html: {id: 'cc-expiration-month'} %>
<%= f.input :cc_expiration_year, as: :integer, input_html: {id: 'cc-expiration-year'} %>
<%= f.input :cc_ccv, input_html: {id: 'cc-ccv'} %>
<%= f.input :uri, as: :hidden %>
<%= f.button :submit, id: 'cc-submit', remote: true %>
<% end %>
The first value in your data object has to be :tablecharge as you specified that all the params belong to that object.
So the data you are passing in your ajax request should be formatted like this:
data: { tablecharge: {uri: fundingInstrument.href, event_id: urlid}}

Rails - undefined method `each' for 0:Fixnum

I get the following error in Ruby on Rails undefined method 'each' for 0:Fixnum.
Here is the application trace :
app/controllers/videos_controller.rb:23:in `new'
app/controllers/videos_controller.rb:23:in `create'
And my controller create and new actions :
def new
#video = Video.new
end
def create
method = 'get_' + params[:video][:provider] + '_video_id'
params[:video][:provider_video_id] = Video.send(method, params[:video][:url])
params[:video][:thumb] = Video.get_thumb_from_youtube(params[:video][:provider_video_id])
params[:video][:views] = params[:video][:likes] = 0
params[:video][:user_id] = current_user
#video = Video.new(params[:video])
if #video.save
redirect_to video_path(#video), notice:'Video added successfully.'
else
render :new
end
end
Here is my view.html.haml :
= form_for #video do |f|
- if #video.errors.any?
.error_explanation
%h2= pluralize(#video.errors.count, "error")
prohibited this user from being saved:
%ul
- #video.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :title
= f.text_field :title
.field
= f.label :description
= f.text_area :description
%br
.field
= f.label :url, 'URL'
= f.text_field :url
%br
.field
Provider
= radio_button :video, :provider, 'vimeo'
= f.label :provider, 'Vimeo', :value => 'vimeo'
= radio_button :video, :provider, 'youtube'
= f.label :provider, 'Youtube', :value => 'youtube'
%br
.field
Category
= collection_select(:video, :category_id, Category.all, :id, :name, :include_blank => true)
%br
.actions
= f.submit "Add video"
From
params[:video][:views] = params[:video][:likes] = 0
to
params[:video][:views] = 0
I assume that video.likes is an association, not a count, so it expects an Enumerable. If it's an association, rails tries to assign the elements you add to likes to your video model. The first step of adding them is to iterate - using each. That's where the error comes from.

Resources