Ruby on Rails - Action Mailer 400 Bad request - ruby-on-rails

I'm having the following error when I try send a form with Ruby on Rails 4.1 and Action Mailer:
Started POST "/contact_sponsors" for 127.0.0.1 at 2018-05-17 16:22:35 -0300
Processing by ContactSponsorsController#create as JS
Parameters: {"utf8"=>"✓", "contact_sponsor"=>{"company_name"=>"godocu#mailinator.com", "company_cnpj"=>"dahok#mailinator.com", "company_cep"=>"watyhib#mailinator.com", "company_address"=>"dofimocah#mailinator.com", "company_number"=>"duki#mailinator.com", "company_existence"=>"mamopiwir#mailinator.net", "company_sponsor_type"=>"", "responsible_name"=>"qomukuf#mailinator.com", "responsible_email"=>"ryhohiqe#mailinator.net", "additional_infos"=>"Eum sit nesciunt occaecat facere delectus vel aut sint animi pariatur Ut ipsum officia ratione est enim est"}}
HomeConfig Load (4.1ms) SELECT `home_configs`.* FROM `home_configs` ORDER BY `home_configs`.`id` ASC LIMIT 1
(0.2ms) BEGIN
(0.4ms) ROLLBACK
Rendered text template (0.0ms)
Completed 400 Bad Request in 16ms (Views: 0.8ms | ActiveRecord: 4.8ms)
Anyone can help me? I've tried to sort this out in many ways but to no avail. Here is my Controller, Mailer and Model:
class ContactSponsorsController < InheritedResources::Base
def create
#contact_sponsor = ContactSponsor.new
if #contact_sponsor.save
ContactSponsorMailer.delay_for(10.seconds, retry: true).create(#contact_sponsor)
render nothing: true, status: 200
else
render nothing: true, status: 400
end
end
end
class ContactSponsorMailer < ActionMailer::Base
default from: "Facens Lince <no-reply#facens.br>"
def create(contact_sponsor)
#contact_sponsor = contact_sponsor
mail(to: "felipe.marcon#atua.ag", subject: "Contato Através do Site")
end
end
class ContactSponsor < ActiveRecord::Base
validates :company_cnpj, :company_address, :company_number, :company_size, :company_existence, :company_sponsor_type, :responsible_name, :responsible_email, presence: true
end
Thanks.

Look, in the ContactSponsor you have validate those data which must be present but you have not passed any data that means empty that's why
Completed 400 Bad Request
and for this, you need to create a private method for strong parameters look at that below
class ContactSponsorsController < InheritedResources::Base
def create
#contact_sponsor = ContactSponsor.new(contact_sponsor_params)
if #contact_sponsor.save
ContactSponsorMailer.delay_for(10.seconds, retry: true).create(#contact_sponsor)
render nothing: true, status: 200
else
render nothing: true, status: 400
end
end
private
def contact_sponsor_params
params.require(:contact_sponsor).permit(:company_cnpj, :company_address, :company_number, :company_size, :company_existence, :company_sponsor_type, :responsible_name, :responsible_email)
end
end
I think it will work.

#contact_sponsor.save returned false therefore it returns 400.
Check the errors you had with #contact_sponsor.errors.full_messages when it returns false, or use save! to raise an exception (discouraged, use it only for debugging) and see what went wrong.

As per the logs shown and code snippet shared, it seems like the attribute "company_sponsor_type" seems to be blank string and in the model you have the written the presence true of the same attribute and thus it is getting rolled back.
So either remove the validation or send some value in the company_sponsor_type key.

Related

Keep Encountering 500 Error When Using Stripe Webhooks with Ruby on Rails 7

I'm developing an application where users can pay a one time fee to submit a screenplay. The current flow looks like this:
User fills out form
Upon submitting form, the user is redirected to Stripe Checkout
Stripe webhook listens for session.checkout.completed, once that happens the is_paid field is updated to TRUE.
Every thing except the webhooks are working fine. I can submit the form, be redirect to stripe, and make a payment. The issue that I'm encountering is that whenever I use Stripe CLI (stripe listen --forward-to localhost:3000/webhooks) and go through the checkout process on my local environment, I receive the following errors in the Stripe CLI tab:
payment_intent.created
[500] POST http://localhost:3000/webhooks
customer.created
[500] POST http://localhost:3000/webhooks
payment_intent.succeeded
[500] POST http://localhost:3000/webhooks
charge.succeeded
[500] POST http://localhost:3000/webhooks
checkout.session.completed
[500] POST http://localhost:3000/webhooks
And the following errors in my Rails Server tab:
Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms | Allocations: 454)
ArgumentError (wrong number of arguments (given 0, expected 1+)):
app/controllers/webhooks_controller.rb:8:in `create'
The above says there's an error on line eight which would be endpoint_secret = Rails.application.credentials.dig[:stripe, :webhook_secret] but I don't see what's wrong with this. I've checked my credentials and they're definitely correct (I've copy and pasted them numerous times, made sure they were test keys, compared them letter by letter etc).
When I use stripe trigger checkout.session.completed I get the same errors.
If anyone has an idea of where I'm going wrong it would be apppreciated!
Here's what my screenplay_controller looks like:
def create
#screenplay = current_user.screenplays.new(screenplay_params)
if #screenplay.save
session = Stripe::Checkout::Session.create({
line_items: [{
price: "removed for privacy",
quantity: 1,
}],
mode: "payment",
metadata: { screenplay_id: #screenplay.id },
customer_email: current_user.email,
success_url: root_url,
cancel_url: root_url,
})
redirect_to session.url, allow_other_host: true
else
render :new, status: :unprocessable_entity
end
end
This is my webhooks_controller:
class WebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def create
event = nil
sig_header = request.env["HTTP_STRIPE_SIGNATURE"]
payload = request.body.read
endpoint_secret = Rails.application.credentials.dig[:stripe, :webhook_secret]
begin
event = Stripe::Webhook.construct_event(
sig_header, payload, endpoint_secret
)
rescue JSON::ParserError => e
# Invalid payload
head 400
return
rescue Stripe::SignatureVerificationError => e
# Invalid signature
head 400
return
end
case event.type
when "checkout.session.completed"
session = event.data.object
screenplay = Screenplay.find_by(id: session.metadata.screenplay_id)
screenplay.update(is_paid: true)
end
end
end
This is what my routes look like:
Rails.application.routes.draw do
root "static_pages#home"
devise_for :users
resources :screenplays
resources :webhooks, only: [:create]
end
And this is what my Stripe initialiser looks like:
Stripe.api_key = Rails.application.credentials.dig(:stripe, :secret_key)
You need to replace square brackets with normal brackets
a = { b: :c }
a.dig(:b)
# Returns :c
a.dig[:b]
# ArgumentError: wrong number of arguments (given 0, expected 1+)

Confusion between url_for and host definition for ActionMailer

Rails mailer instances do not have any context about the request. However this is needed to service multiple hosts. I was hoping to invoke url_for for the mailer, but I am confused to both the placing of it AND how it should be constructed (the api documentation provides examples for controllers, not mailers).
The form submission has a hidden_field :host, value: #site.host which percolates to the request
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"email"=>"some#quack.com", "host"=>"localhost"}
environments/development.rb has config.action_mailer.default_url_options commented out.
initializer for devise has config.parent_mailer = 'DeviseMailer'
The users/passwords_controller.rb has been edited
class Users::PasswordsController < Devise::PasswordsController
def create
puts params[:host]
super
end
and mailers/devise_mailer.rb sets
class DeviseMailer < ActionMailer::Base
layout 'mailer'
before_action :set_mailers_url_host
def set_mailers_url_host
puts 'host'
puts params
ActionMailer::Base.default_url_options[:host] = params[:user][:host]
end
I did not expect the mailer to know the parameter as it is designed to inherit from < ActionMailer::Base
However, the log is indicating that the password controller generated is not being invoked. the 'host' string is being put, then an empty line indicates the mailer know nothing of the params
Processing by Devise::PasswordsController#create as HTML
[...]
↳ app/controllers/application_controller.rb:284:in `get_departments'
User Load (2.5ms) SELECT "users"...
User Load (1.2ms) SELECT "users"...
TRANSACTION (1.0ms) BEGIN
User Update (1.7ms) UPDATE "users" SET "reset_password_token" = $1, "reset_password_sent_at" = $2 WHERE "users"."id" = $3 [["reset_password_token", "..."], ["reset_password_sent_at", "..."], ["id", 45]]
TRANSACTION (6.1ms) COMMIT
host
Devise::Mailer#reset_password_instructions: processed outbound mail in 0.6ms
Completed 500 Internal Server Error in 745ms (ActiveRecord: 81.6ms | Allocations: 203970)
NoMethodError (undefined method `[]' for nil:NilClass):
app/mailers/devise_mailer.rb:8:in `set_mailers_url_host'
The error is expected given params[:user][:host] is an unknown entity to the mailer. The bypassing of the passwords controller, not.
Also attempted: commenting out the devise_mailer before_action and adding to the application_controller.rb, where #site is set in before_action :set_site :
def default_url_options
{ host: #site.host, locale: I18n.locale }
end
While this is the most succinct way of dealing with the case, that fails with error ActionView::Template::Error (Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true)
Why are the checks (via puts) in the passwords controller not being invoked?
How should url_for thus establish the required string based on params[:user][:site]
This is a way to solve your issue but I'm not quite satisfied with the beauty of this. 🤔
around_action :change_host
def change_host
default_options = Rails.application.routes.default_url_options
new_options = { host: param[:user][:host], port: :thing }
Rails.application.routes.default_url_options = new_options
Rails.application.configuration.action_mailer.default_url_options = new_options
yield
Rails.application.routes.default_url_options = default_options
Rails.application.configuration.action_mailer.default_url_options = default_options
end
Given all the moving parts, a quick review:
comment out config.action_mailer.default_url_options
submission of param in form for host
no need for DeviseMailer class
setting default_url_options in application_controller not necessary
url_for is uncalled for
First element of answer: get the routing established correctly:
devise_for :users, controllers: { passwords: 'users/passwords' }
Second element of solution (preliminary - works in development on remote server), modify the devise passwords controller.
def create
ActionMailer::Base.default_url_options[:host] = params[:user][:host]
super
end

401 Unauthorized error when making requests to rails api on heroku

I just deployed my first app to heroku and it used a Rails API (backend) and a React frontend. When I deployed my app I get 401 unauthorized errors whenever I try to make a request that involves the use of a JSON Web Token(JWT). I am sending the token from localstorage in my app and everything worked fine when I was sending it in my development environment. I only have this issue in production.
When I make the fetch request from my frontend and send over my JWT to my backend, I get the following messages in my heroku server logs:
2020-11-29T04:45:31.742735+00:00 app[web.1]: I, [2020-11-29T04:45:31.742670 #4] INFO -- : [f3c19eae-e431-4c9f-b93b-7499797f2c03] [active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.13ms)
2020-11-29T04:45:31.742984+00:00 app[web.1]: I, [2020-11-29T04:45:31.742919 #4] INFO -- : [f3c19eae-e431-4c9f-b93b-7499797f2c03] Filter chain halted as :authorized rendered or redirected
2020-11-29T04:45:31.744091+00:00 app[web.1]: I, [2020-11-29T04:45:31.744019 #4] INFO -- : [f3c19eae-e431-4c9f-b93b-7499797f2c03] Completed 401 Unauthorized in 2ms (Views: 0.7ms | Allocations: 218)
Another strange thing about this is that I get an error message along with the 401 status error in my React frontend that tells me to Please Log in even though I logged into my app to receive a token from my backend before I even attempted to make another fetch request
Below I will post other relevant code snippets so that you can see what I was trying to do
Here is the Code in my frontend that sends the request
addToCart = () =>{
//make a fetch request to add the item in the customer's current cart
fetch("https://health-and-fit-store-api.herokuapp.com/cart_products",{
method:"POST",
headers:{
"Authorization": localStorage.token,
"Content-Type":"application/json",
Accept:"application/json"
},
body:JSON.stringify({
productId :this.props.id
})
})
.then(res => res.json())
.then(data => {
this.props.addToCart(data)
toast.dark(`Added ${data.product.name.toLowerCase()} to your cart`)
})
}
Here is the code in my Rails API that receives the request
before_action :authorized, only: [:create,:delete]
def create
#will be receiving token in fetch request
#use the of the current cart and the product id passed in by the post request
current_cart = #customer.carts.find_by(checked_out:false)
product = Product.find(params[:productId])
new_cart_product = CartProduct.create(cart:current_cart,product:product, quantity:1)
render json: new_cart_product
end
Here is the code from my application controller that I used to set up JWT
class ApplicationController < ActionController::API
def encode_token(payload)
# should store secret in env variable
JWT.encode(payload, ENV['jwt_encode_string'])
#byebug
end
def auth_header
# { Authorization: 'Bearer <token>' }
request.headers['Authorization']
end
def decoded_token
if auth_header
token = auth_header
# header: { 'Authorization': '<token>' }
begin
JWT.decode(token, ENV['jwt_encode_string'], true, algorithm: 'HS256')
rescue JWT::DecodeError
nil
end
end
end
def logged_in_customer
if decoded_token
customer_id = decoded_token[0]['customer_id']
#customer = Customer.find_by(id: customer_id)
end
end
def logged_in?
!!logged_in_customer
end
def authorized
render json: { error_message: 'Please log in' }, status: :unauthorized unless logged_in?
end
end
If anyone can help me out with this, I would really appreciate it, I've been stuck on this for days. Also please note that I have checked out every other post involving this issue on StackOverflow and have exhausted every kind of search on Google that I could think of.
thanks to #snake, I actually ended up solving this issue. The problem wasn't with the token I was using, but their suggestion led me to go back and check out my fetch requests to the api endpoint and I had an extra comma at the end of the request that was causing the 401 status code error.
Once I fixed that, everything worked beautifully.

Getting rails error when using Spaceship::Tunes

In a rails app I am running:
54 def itunes_all_apps
55 begin
56 Spaceship::Tunes.login(params[:itunes_username], params[:itunes_password])
57 apps = Spaceship::Tunes::Application.all
58 render json: apps.to_json, status: 200
59 rescue => e
60 render json: {error: e}.to_json, status: 500
61 end
62 end
It returns a status 500 error with no other information every time.
However, if I change this around slightly, for example getting teams (note, from Spaceship, not Spaceship::Tunes) this works fine:
def itunes_all_apps
begin
spaceship = Spaceship.login(params[:itunes_username], params[:itunes_password])
teams = spaceship.teams
render json: teams.to_json, status: 200
rescue => e
render json: {error: e}.to_json, status: 500
end
end
I'm not using any fast file or or config or anything. Just passing in a username and password via an api call and trying to get a response back. I'm new to rails so it may be my implementation of the Spaceship examples provided.
Using spaceship 0.36.1 gem (the latest)
I've pored through the docs to no avail. Grasping for any leads on what I'm doing wrong.
http://www.rubydoc.info/gems/spaceship/Spaceship/Tunes
https://github.com/fastlane/fastlane/blob/master/spaceship/docs/iTunesConnect.md
Someone suggested I run these two commands in irb, which I did, and they worked perfect!
Spaceship::Tunes.login('myAppleId', 'myPassword')
Spaceship::Tunes::Application.all
So it's not an iTunes account problem or credentials problem (because it works in irb), routes problem (because I ran both rails methods above with same route), or params problem (because I ran both rails methods above with same param names).
I really appreciate any suggestions. Thanks.
Edit:
Commenting out begin, rescue, and rending the error, the stack trace is as follows:
2016-10-24T17:47:34.974650+00:00 app[web.1]: Started POST "/api/v1/users/13/itunes_all_apps" for 162.237.102.13 at 2016-10-24 17:47:34 +0000
2016-10-24T17:47:34.977478+00:00 app[web.1]: Processing by Api::V1::UsersController#itunes_all_apps as JSON
2016-10-24T17:47:34.977521+00:00 app[web.1]: Parameters: {"itunes_username"=>"myCorrectUsername", "itunes_password"=>"[FILTERED]", "team_id"=>"myCorrectTeamId", "id"=>"13", "user"=>{}}
2016-10-24T17:47:35.629629+00:00 heroku[router]: at=info method=POST path="/api/v1/users/13/itunes_all_apps" host=myHerokuApp.herokuapp.com request_id=002d906d-354e-4633-8b54-71aa5181e3a7 fwd="161.237.102.13" dyno=web.1 connect=2ms service=657ms status=500 bytes=259
2016-10-24T17:47:35.619597+00:00 app[web.1]: Completed 500 Internal Server Error in 642ms (ActiveRecord: 0.0ms)
2016-10-24T17:47:35.620430+00:00 app[web.1]:
2016-10-24T17:47:35.620432+00:00 app[web.1]: IOError (not opened for reading):
2016-10-24T17:47:35.620434+00:00 app[web.1]:
2016-10-24T17:47:35.620433+00:00 app[web.1]: app/controllers/api/v1/users_controller.rb:58:in `itunes_all_apps'
It seems that Spaceship::Fastlane::Application does not implement as_json method and the default as_json touches some IO object, which cannot be represented as json.
My suggestion would be to create JSON serializer. You could use active_model-serializer, but if you do not want to create a dependency just for one object, then you can create your own serializer.
class SpaceshipApplicationSerializer
attr_reader :spaceship_applications
def initialize(spaceship_applications)
#spaceship_applications = spaceship_applications
end
def as_json(options = {})
spaceship_applications.each_with_object([]) do |spaceship_application, memo|
memo << object_as_json(spaceship_application)
end
end
def object_as_json(object)
attributes.each_with_object({}) do |attribute, memo|
memo[attribute] = object.send(attribute)
end
end
def attributes
[
:apple_id,
:name,
:vendor_id,
:bundle_id,
:last_modified,
:issues_count,
:app_icon_preview_url
]
end
end
# In your controller
def itunes_all_apps
begin
Spaceship::Tunes.login(params[:itunes_username], params[:itunes_password])
apps = Spaceship::Tunes::Application.all
render json: SpaceshipApplicationSerializer.new(apps).to_json, status: 200
rescue => e
render json: {error: e}.to_json, status: 500
end
end
EDIT:
Yes, the classes return an array, but the actual objects in array don't play nicely with json. It's hard to say if the problem is with the library - on one hand Spaceship::Tunes::Application not returning a proper json representation is a missing feature, but if the to_json raises an exception (a method the class responds to) - then I would say that is a bug.
Creating your own serializer to build json representation the way you want it - is a common pattern.

Error during failsafe response: Ruby on Rails 3

I have a form_tag that works fine using html, but when I use ajax with the remote => true I am getting this error:-
My terminal log shows:-
Started GET "/" for 127.0.0.1 at 2010-11-01 01:19:49 +0000
Processing by HomepagesController#index as HTML
Homepage Load (0.6ms) SELECT "homepages".* FROM "homepages"
Rendered homepages/index.html.erb within layouts/application (23.0ms)
Completed 200 OK in 40ms (Views: 27.3ms | ActiveRecord: 0.6ms)
Error during failsafe response: incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string)
* then a load of cleaner.rb stuff
then:-
Started GET "/homepages?utf8=%E2%9C%93&search=hom" for 127.0.0.1 at 2010-11-01 01:19:56 +0000
Processing by HomepagesController#index as JS
Parameters: {"utf8"=>"✓", "search"=>"hom"}
Homepage Load (0.5ms) SELECT "homepages".* FROM "homepages" WHERE (section LIKE '%hom%')
Rendered homepages/index.js.erb (2.9ms)
Completed in 19ms
In my index.js.erb I have:-
$("testsearch").update("<%= escape_javascript(render(#homepages))%>");
and in my Controller I have:-
def index
#homepages = Homepage.search(params[:search])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #homepages }
format.js { render :layout => false }
end
in my view I have:-
which prints #homepages using a table using <% #homepages.each do |homepage| %> which is not being updated.
Anyone have any ideas as to why I get this error.
I have cracked it by going onto an IRC chat room (irc.freenode.net RubyonRails) and a ProjectZen (human being somewhere out there in the ether) helped me to get it working.
Apparently what was happening was that I was following Ryan Bates who does many extremely good Railcast videos, but he builds on previous Railcast. Therefore in his 205 Railscast, which deals with Ajax calls, he did not mention that you must have:-
format.js in the action in the controller.
His xxxx.searchxxxxx needs to be created in the controller or model.
And that when I did :-
<%= render(#homepages)%> <!-- (in his case <%= render(#products)%>) -->
The render was looking for a partial called "_homepage" (not "homepages") (I did not even have a partial therefore I got the UTF8 to ASCII error).
And then in "_homepage" I would add my code to render the results.
What I have now done in my index.html.erb is to put <%= render(#homepages)%>, in the (div id = testsearch) in place of the code I use to render #homepages and then place that code in a partial "_homepage". Now I can use "_homepage" for the html and the Ajax call.
At the moment I have a slight problem in that it is rendering all the data in the"#homepages" as many times as the number of records. At the moment I do not know why, but at least the Ajax call is working.

Resources