carrierwave works with form but not API in Rails 5 - ruby-on-rails

I am using carrierwave to accept an image from a Python API. I have the following code:
def create
#person = Person.new(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render :show, status: :created, location: #person }
else
format.html { render :new }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
def person_params
params.permit(:client_file_name, :name, :picture)
end
I had to take out params.require(:person) because the Python library I am using called requests does not allow you to send files in that form.
According to the server logs, the image is saving:
Started POST "/people" for 127.0.0.1 at 2017-11-19 11:49:19 -0500
Processing by PeopleController#create as */*
Parameters: {"picture"=>#<ActionDispatch::Http::UploadedFile:0x007fe5e8e900b8 #tempfile=#<Tempfile:/var/folders/77/2f_jjrld0dxgq3t8xv6clvph0000gn/T/RackMultipart20171119-13141-1nunpha.png>, #original_filename="Phil.png", #content_type=nil, #headers="Content-Disposition: form-data; name=\"picture\"; filename=\"Phil.png\"\r\n">}
(0.0ms) begin transaction
SQL (0.2ms) INSERT INTO "people" ("picture", "created_at", "updated_at") VALUES (?, ?, ?) [["picture", "Phil.png"], ["created_at", "2017-11-19 16:49:19.776189"], ["updated_at", "2017-11-19 16:49:19.776189"]]
(0.6ms) commit transaction
Redirected to http://localhost:3000/people/8
Completed 302 Found in 15ms (ActiveRecord: 1.5ms)
I am only doing this locally. When I look in the directory where the image should be saved, there is an image there called Phil.png which is what should happen except the image has zero bytes.
When I upload the same image using a form, everything works as expected. How do I fix this?

So I figured it out. Rails requires you to set the content-type to image/png, so adding that to the request solved the problem.

Related

redirect_to inside controller action doesn't work

I use Rails 5.1 and the "redirect_to #search" inside create action doesn't work.
My SearchesController:
class SearchesController < ApplicationController
def new
#search = Search.new
end
def create
#search = Search.create!(search_params)
redirect_to #search # search_path(#search) doesn't work either
end
def show
#search = Search.find(params[:id])
end
private
def search_params
params.require(:search).permit!
end
end
After creating a new search entry by clicking the submit button it doesn't redirect to show page.
My app/views/searches/new.html.erb:
<div>
<h1>Advanced Search Form</h1>
<%= form_with model: #search do |form| %>
<%= form.text_field :keywords %>
<%= form.select :ort, options_from_collection_for_select(Imagecapturing.cities, :ort, :city_name, prompt: false, include_blank: false) %>
<%= form.submit("Suchen", :id=>"button", :class=>"Test", :name=>"submit") %>
<% end %>
</div>
config/routes.rb:
Rails.application.routes.draw do
root 'imagecapturings#index'
resources :searches
end
Log:
Started POST "/searches" for ::1 at 2018-06-14 17:37:54 +0200
Processing by SearchesController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"B91lIUxZZvanOx1luhhfWBJ9mAO5Np/6Bx4xzPdv2Ygj29bprWk5+wIBP7kMVl5Eoxz0KcyJF5DK8UaVUhQaFQ==", "search"=>{"keywords"=>"", "ort"=>"A-St. Paul"}, "submit"=>"Suchen"}
(0.6ms) BEGIN
SQL (22.8ms) INSERT INTO `searches` (`keywords`, `ort`, `created_at`, `updated_at`) VALUES ('', 'A-St. Paul', '2018-06-14 15:37:58', '2018-06-14 15:37:58')
(11.1ms) COMMIT
Redirected to http://localhost:4000/searches/23
Completed 302 Found in 50ms (ActiveRecord: 34.5ms)
Started GET "/searches/23" for ::1 at 2018-06-14 17:37:58 +0200
Processing by SearchesController#show as JS
Parameters: {"id"=>"23"}
Search Load (0.7ms) SELECT `searches`.* FROM `searches` WHERE `searches`.`id` = 23 LIMIT 1
Rendering searches/show.html.erb within layouts/application
Imagecapturing Load (10.4ms) SELECT `imagecapturing`.* FROM `imagecapturing` WHERE (ort LIKE '%A-St. Paul%') ORDER BY `imagecapturing`.`id` DESC
Rendered searches/show.html.erb within layouts/application (62.5ms)
Rendered layouts/_top_nav.html.erb (6.0ms)
Imagecapturing Load (17.0ms) SELECT distinct(ort) FROM `imagecapturing` ORDER BY `imagecapturing`.`ort` ASC
Rendered searches/_links.html.erb (33.5ms)
Completed 200 OK in 409ms (Views: 340.1ms | ActiveRecord: 28.0ms)
Is in "Processing by SearchesController#show as JS" the "as JS" part the issue?
How can I get the redirect working so that after clicking the submit button it redirects to the show action?
--- UPDATE
With suggestion of user Rockwell I modified the create action to:
def create
#search= Search.create!(search_params)
respond_to do |format|
if #search
format.html {redirect_to #search}
format.json { render :show, status: :created, location: #step }
format.js { redirect_to #search }
else
format.html { render :new }
format.json { render json: #search.errors, status: :unprocessable_entity }
format.js { render :new }
end
end
end
But it still processes "as JS":
Started POST "/searches" for ::1 at 2018-06-14 18:09:18 +0200
Processing by SearchesController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"D7l5ibv8hu08Z18VKqa0Y+iqGHfT+SIZTIoM8vHdcpArv8pBWszZ4Jldfcmc6LV/Wct0XaZGqnOBZXurVKaxDQ==", "search"=>{"keywords"=>"", "ort"=>"Cologny"}, "submit"=>"Suchen"}
(0.2ms) BEGIN
SQL (11.8ms) INSERT INTO `searches` (`keywords`, `ort`, `created_at`, `updated_at`) VALUES ('', 'Cologny', '2018-06-14 16:09:18', '2018-06-14 16:09:18')
(17.0ms) COMMIT
Redirected to http://localhost:4000/searches/30
Completed 302 Found in 36ms (ActiveRecord: 29.0ms)
Started GET "/searches/30" for ::1 at 2018-06-14 18:09:19 +0200
Processing by SearchesController#show as JS
Parameters: {"id"=>"30"}
Search Load (0.8ms) SELECT `searches`.* FROM `searches` WHERE `searches`.`id` = 30 LIMIT 1
Rendering searches/show.html.erb within layouts/application
Imagecapturing Load (28.1ms) SELECT `imagecapturing`.* FROM `imagecapturing` WHERE (ort LIKE '%Cologny%') ORDER BY `imagecapturing`.`id` DESC
Rendered searches/show.html.erb within layouts/application (16157.3ms)
Rendered layouts/_top_nav.html.erb (3.6ms)
Imagecapturing Load (27.6ms) SELECT distinct(ort) FROM `imagecapturing` ORDER BY `imagecapturing`.`ort` ASC
Rendered searches/_links.html.erb (39.2ms)
Completed 200 OK in 16404ms (Views: 16314.1ms | ActiveRecord: 56.5ms)
I believe that you are correct, the Processing by SearchesController#show as JS is what is causing your error. If you respond to the format it should solve your issue. I added HTML and JSON here but you wouldn't need to if you know you will never need that, just the js should be fine.
def create
#search = Search.new(search_params)
respond_to do |format|
if #search.save
format.html {redirect_to #search}
format.json { render :show, status: :created, location: #step }
format.js { redirect_to #search }
else
format.html { render :new }
format.json { render json: #search.errors, status: :unprocessable_entity }
format.js { render :new }
end
end
end
If you are sending this as an AJAX you could specify the type that gets sent as well, but I would need to see the JS code for that to give a solution to fix that.
it is working as expected, you can see it on the log, the insert is done and then the redirect too.
but the problem is the format you are asking. it seems like the create is called as js Processing by SearchesController#create as JS (maybe you are doing an ajax request with that format or your form has remote:true). and then the redirect isn't done visually of course. you need to make the create request without js format or don't make the redirect on the controller and create a "create.js" view that does the redirect. but of course it's not the best solution.
if you want to do the redirect, the best way is to change the format of the create request.

ActionController::UnknownFormat in MeetingsController#update

I have read countless SO questions about this issue, and can not find a solution.
I have a button that updates Meeting here:
<%= form_for(meeting) do |f| %>
<%= f.hidden_field :accepted, value: true %>
<%= button_tag(type: 'submit', class: "btn_primary") do %>
Accept <svg><use xlink:href="#checkmark"/></svg>
<% end %>
<% end %>
I get an unknown format error, BUT it still updates. What is causing this error?
I have tried removing respond_to do |format| from the update method. which solves the problem for this one button, but then breaks all the other buttons on the platform that calls meetings/update.
class MeetingsController < ApplicationController
respond_to :json, :html
def update
respond_to do |format| **error highlights this line**
if #meeting.update(meeting_params)
format.json { render :show, status: :ok, location: #meeting }
else
format.html { render :edit }
format.json { render json: #meeting.errors, status: :unprocessable_entity }
end
end
end
end
Console:
Started PATCH "/meetings/224" for 127.0.0.1 at 2016-11-11 16:05:27 -0500
Processing by MeetingsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hK6AoOZuw9DWyKUXw1dXWOSUolooWgBUPnkItUJX5Tm7XvimsHd9518pkqwVvNhUi3L3vlA4OZaJZiAgrbS0Ig==", "meeting"=>{"accepted"=>"true"}, "button"=>"", "id"=>"224"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Meeting Load (0.2ms) SELECT "meetings".* FROM "meetings" WHERE "meetings"."id" = ? LIMIT 1 [["id", 224]]
(0.3ms) begin transaction
SQL (0.5ms) UPDATE "meetings" SET "accepted" = ?, "updated_at" = ? WHERE "meetings"."id" = ? [["accepted", "t"], ["updated_at", "2016-11-11 21:05:27.882521"], ["id", 224]]
(1.3ms) commit transaction
Completed 406 Not Acceptable in 24ms (ActiveRecord: 2.7ms)
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/meetings_controller.rb:65:in `update'
This was never an issue, and seemingly came out of no where. What is the cause of this error? Thanks!
I think I know what the issue is. I've added a line to your update method
class MeetingsController < ApplicationController
respond_to :json, :html
def update
respond_to do |format| **error highlights this line**
if #meeting.update(meeting_params)
format.html { redirect_to some_rails_path }
format.json { render :show, status: :ok, location: #meeting }
else
format.html { render :edit }
format.json { render json: #meeting.errors, status: :unprocessable_entity }
end
end
end
end
The reason you're getting an unknown format error but still successfully updating meeting is because your method has solid logic, so it's updating the meeting, but then once it does that, and you're only telling it what to do in terms of JSON but not in terms of HTML, you address both in your else statement, but not if the update succeeds.
Is this supposed to be an ajax request? It doesn't seem to be. But you're rendering json instead of html. If you're going to allow the page to reload you need to add an html option to if #meeting.update(meeting_params)
Something like: format.html { redirect_to #meeting, notice: 'Meeting was successfully updated.' }
If you're doing an ajax request this isn't the correct answer, but I don't see any indication in your question that you are. Lmk if you need further clarification.

Rails REST put using Firefox RESTclient

I'm trying to test REST input into a Rails 3 application. I'm using Firefox add-on called RESTclient. For staters, I'm just trying to PUT (Update) one column in a the database (contact2="Bart").
I get back 200, but the column doesn't get updated in the database and the response shows the column to still contain "Mary2"
Here's a pic:
This is the controller:
# PUT /workorders/1
# PUT /workorders/1.json
def update
#workorder = Workorder.find(params[:id])
respond_to do |format|
if #workorder.update_attributes(params[:workorder])
format.html { redirect_to #workorder, notice: 'Workorder was successfully updated.' }
format.json { render json: #workorder }
else
format.html { render action: "edit" }
format.json { render json: #workorder.errors, status: :unprocessable_entity }
end
end
end
Rails Log:
Started PUT "/workorders/56673.json" for 127.0.0.1 at 2015-12-17 14:40:30 -0700
[1m[35mWostatus Load (0.2ms)[0m SELECT "wostatuses".* FROM "wostatuses" ORDER BY position ASC LIMIT 1
Processing by WorkordersController#update as JSON
Parameters: {"id"=>"56673"}
WARNING: Can't verify CSRF token authenticity
[1m[36mWorkorder Load (0.3ms)[0m [1mSELECT "workorders".* FROM "workorders" WHERE "workorders"."id" = $1 LIMIT 1[0m [["id", "56673"]]
[1m[35m (0.1ms)[0m BEGIN
[1m[36m (0.1ms)[0m [1mCOMMIT[0m
Completed 200 OK in 143ms (Views: 0.8ms | ActiveRecord: 0.5ms)
Is the parameter "contact2" not being sent?
I got it working using Wiztools RESTclient.
I had to use:
Body = application/json; charset=UTF-8
{
"contact2": "Bart"
}

Received JSON in Rails API is not stored

I am working on a web service in Rails that receives data in JSON format from another Rails application. When the web service receives the data, it reads it but does not insert into the database. This is from the log file:
Processing by OrdersController#create as JSON
Parameters: {"name"=>"dst", "address"=>"dst", "email"=>"sdt"}
[1m[36m (0.2ms)[0m [1mbegin transaction[0m
[1m[35mSQL (0.5ms)[0m INSERT INTO "orders" ("created_at", "updated_at")
What should I do to get this data inside the INSERT statement? Do I need a new json.jbuilder file or something else? What am I missing?
Update: Putting the controller#create code here. Didn't paste it initially because it is the default created from the scaffold generator.
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
order_params is presumably defined somewhere in your OrdersController. Normally model parameters in a request are nested under the resource ({order: {"name"=>"dst", "address"=>"dst", "email"=>"sdt"}) and then in order_params would be
def order_params
params.require(:order).permit(:name, :address, :email)
end
But if you can't change the JSON payload, you could just nix the require(:order) part and call params.permit(:name, :address, :email).
You can read the Rails guide on Strong Parameters here: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters

Completed 406 Not Acceptable in 773ms

My client app sends JSON encoded POST to rails server but the server shows 406 error and doesn't respond to json.
UsersController create
# POST /users
# POST /users.json
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
Rails console:
Started POST "/users.json" for 127.0.0.1 at 2013-05-21 16:38:47 +0100
Processing by Devise::RegistrationsController#create as JSON
Parameters: {"user"=>{"name"=>"", "available"=>"true", "email"=>"", "sex"=>"male", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
WARNING: Can't verify CSRF token authenticity
(0.2ms) begin transaction
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '' LIMIT 1
(0.2ms) rollback transaction
Completed 406 Not Acceptable in 773ms (ActiveRecord: 6.1ms)
Can anyone help me?
Going to try to answer this a while later in case anyone sees it. I've run into this problem over and over even when I've only had JSON as the format option at the bottom of my controller (like this in your example):
respond_to do |format|
format.json { render json: #user, status: :created, location: #user }
end
Even when calling it explicitly with $.getJSON on my requests which does call it with JSON data types.
The trick I found was calling it with .json on my page name.
$.getJSON('controllername-your-calling.json?', function(json){
//do your stuff...
});
Maybe it helps someone.
You'll need to add respond_to :json, only: [:create] at the top of your controller. You may need to add respond_to :html for the actions that take HTML.

Resources