after trying to implement a file field that users can upload a screenshot with on a feedback with paperclip I recieved some 'no handle errors'. I also made a question about my paperclip issue here.
By looking at the comments to my question it might have to do with multipart.
BUT since I don't use a rails form I can't do something like form_for multipart true. I'm handling some js via my current form and don't really want to change all of this, that why I now tried switching from deprecated paperclip to rails active storage. So far so good.
Got my form still running and works fine until I come to the point of writing the screenshot in the database.
This is a example response of what I get right now when submitting a feedback.
Started POST "/feedback" for 127.0.0.1 at 2018-10-25 12:21:13 +0200
Processing by FeedbackController#create as */*
Parameters: {"name"=>"dunnothename", "message"=>"blablablablablabla", "topic"=>"Bug", "screenshot"=>"C:\\fakepath\\dhdr.jpeg"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
Feedback Create (41.3ms) INSERT INTO "feedbacks" ("message", "topic", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["message", "blablablablablabla"], ["topic", "Bug"], ["name", "dunnothename"], ["created_at", "2018-10-25 10:21:13.410630"], ["updated_at", "2018-10-25 10:21:13.410630"]]
(0.6ms) COMMIT
(0.2ms) BEGIN
(0.2ms) COMMIT
No template found for FeedbackController#create, rendering head :no_content
Completed 204 No Content in 1268ms (ActiveRecord: 48.1ms)
When trying to add the screenshot param to my controller-method ( @feedback = Feedback.create name: ....., screenshot: params[:screenshot]
) Ill get the following response:
Started POST "/feedback" for 127.0.0.1 at 2018-10-25 12:31:34 +0200
Processing by FeedbackController#create as */*
Parameters: {"name"=>"dunnothename", "message"=>"blablablablablabla", "topic"=>"Bug", "screenshot"=>"C:\\fakepath\\dhdr.jpeg"}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Completed 500 Internal Server Error in 64ms (ActiveRecord: 11.0ms)
ActiveSupport::MessageVerifier::InvalidSignature - ActiveSupport::MessageVerifier::InvalidSignature:
app/controllers/feedback_controller.rb:6:in `create'
Feedback.rb
class Feedback < ApplicationRecord
validates :name, presence: true, length: {minimum: 3}
validates :message, presence: true, length: {minimum: 5}
validates :topic, length: {minimum: 3}
has_one_attached :screenshot
end
_feedback.html.erb
<div id="feedback-message" class="feedback-message" style="color: green;">Feedback sent</div>
<span class="label label-info">Name</span><%= text_field_tag :name, "", class: 'form-control' %>
<span class="label label-info">Topic</span>
<select name="topic" id="topic" class="form-control">
<option value="Bug">Bug</option>
<option value="Suggestion">Suggestion</option>
<option value="Other">Other</option>
</select>
<span class="label label-info">Screenshot</span>
<label class="image-upload form-control">
<i class="fa fa-cloud-download" id="upload_button"></i>
<input id="upload_input" type="file" name="feedback[screenshot]"/>
</label>
<span class="label label-info">Message</span> <%= text_area_tag :message, "", class: 'form-control', rows: 3 %>
<hr>
<%= submit_tag 'Submit', id: 'submit-feedback', class: 'btn btn-success center' %>
<script>
$(document).ready(function () {
var msg = document.getElementById('feedback-message');
var submit = $('#submit-feedback');
submit.click(function () {
msg.style.display = 'block';
submit.prop('disabled', true);
setTimeout(function () {
submit.prop('disabled', false);
msg.style.display = 'none';
}, 5000);
$.ajax({
url: '/feedback',
type: 'POST',
data: {
authenticity_token: $('[name="authenticity_token"]').val(),
name: $('#name').val(),
message: $('#message').val(),
topic: $('#topic').val(),
screenshot: $('#upload_input').val(),
},
});
});
});
var button = document.getElementById('upload_button');
var input = document.getElementById('upload_input');
var span = document.createElement('span');
span.style.paddingLeft = '20px';
span.style.color = 'green';
button.appendChild(span);
input.style.display = 'none';
button.style.display = 'initial';
button.addEventListener('click', function (e) {
e.preventDefault();
input.click();
});
input.addEventListener('change', function () {
span.innerText = '' + this.value;
});
</script>
feedback_controller.rb
class FeedbackController < ApplicationController
def index;
end
def create
@feedback = Feedback.create name: params[:name], message: params[:message], topic: params[:topic]
@feedback.screenshot.attach(params[:screenshot])
authorize @feedback
if @feedback.save
#FeedbackMailer.with(user: @user).feedback_sent.deliver_later
end
end
end
Update:
After trying to implement what @Niraj mentioned I get the following response:
Started POST "/feedback" for 127.0.0.1 at 2018-10-25 13:06:34 +0200
Processing by FeedbackController#create as */*
Parameters: {"name"=>"askdalskjdajsdpojapsdo", "message"=>"asdasldkaspdkasüpdkapsod", "topic"=>"Bug", "screenshot"=>"C:\\fakepath\\dhdr.jpeg"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
Feedback Create (1.4ms) INSERT INTO "feedbacks" ("message", "topic", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["message", "asdasldkaspdkasüpdkapsod"], ["topic", "Bug"], ["name", "askdalskjdajsdpojapsdo"], ["created_at", "2018-10-25 11:06:34.518275"], ["updated_at", "2018-10-25 11:06:34.518275"]]
(0.9ms) COMMIT
ActiveStorage::Attachment Load (0.3ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id", 3], ["record_type", "Feedback"], ["name", "screenshot"], ["LIMIT", 1]]
Completed 500 Internal Server Error in 67ms (ActiveRecord: 9.4ms)
ActiveSupport::MessageVerifier::InvalidSignature - ActiveSupport::MessageVerifier::InvalidSignature:
app/controllers/feedback_controller.rb:7:in `create'
Update2:
class FeedbackPolicy < ApplicationPolicy
def index?
true
end
def create?
user.present?
end
def new?
user.present?
end
def update?
return true if user.present?
end
def destroy?
return true if user.present?
end
private
def feedback
record
end
end
Note: As discussed on comment section
I have modified your _feedback.html.erb
to make file upload working. Please try this code and do let me know. Make sure your have re-started your rails server.
<div id="feedback-message" class="feedback-message" style="color: green;">Feedback sent</div>
<form>
<span class="label label-info">Name</span><%= text_field_tag :name, "", class: 'form-control' %>
<span class="label label-info">Topic</span>
<select name="topic" id="topic" class="form-control">
<option value="Bug">Bug</option>
<option value="Suggestion">Suggestion</option>
<option value="Other">Other</option>
</select>
<span class="label label-info">Screenshot</span>
<label class="image-upload form-control">
<i class="fa fa-cloud-download" id="upload_button"></i>
<input id="upload_input" type="file" name="feedback[screenshot]"/>
</label>
<span class="label label-info">Message</span> <%= text_area_tag :message, "", class: 'form-control', rows: 3 %>
<hr>
<%= submit_tag 'Submit', id: 'submit-feedback', class: 'btn btn-success center' %>
</form>
<script>
$(document).ready(function () {
var submit = $('#submit-feedback');
submit.on('click', function(e) {
e.preventDefault();
var msg = document.getElementById('feedback-message');
var formData = new FormData();
formData.append('authenticity_token', $('[name="authenticity_token"]').val());
formData.append('name', $('#name').val());
formData.append('message', $('#message').val());
formData.append('topic', $('#topic').val());
// Attach file
formData.append('screenshot', $('#upload_input')[0].files[0]);
$.ajax({
url: '/feedback',
type: 'POST',
data: formData,
contentType: false,
processData: false,
beforeSend: function() {
msg.style.display = 'none';
submit.prop('disabled', true);
},
success: function(resp) {
submit.prop('disabled', false);
msg.fadIn().delay(5000).fadeOut();
},
error: function() {
alert('Something went wrong.')
}
})
});
});
var button = document.getElementById('upload_button');
var input = document.getElementById('upload_input');
var span = document.createElement('span');
span.style.paddingLeft = '20px';
span.style.color = 'green';
button.appendChild(span);
input.style.display = 'none';
button.style.display = 'initial';
button.addEventListener('click', function (e) {
e.preventDefault();
input.click();
});
input.addEventListener('change', function () {
span.innerText = '' + this.value;
});
</script>