Рубин на рельсах - activestorage
После попытки реализовать файловое поле, с помощью которого пользователи могут загружать скриншот с обратной связью с помощью скрепки, я получил некоторые "ошибки дескриптора". Я также сделал вопрос о моей проблеме скрепки здесь.
Глядя на комментарии к моему вопросу, это может быть связано с multipart.
НО, поскольку я не использую форму rails, я не могу сделать что-то вроде form_for multipart true. Я обрабатываю некоторые js через мою текущую форму и не хочу все это менять, поэтому сейчас я попытался переключиться с устаревшей скрепки на рельсы активного хранилища. Все идет нормально.
Моя форма все еще работает и работает нормально, пока я не дошёл до момента записи скриншота в базе данных.
Это пример ответа, который я получаю прямо сейчас при отправке отзыва.
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)
При попытке добавить параметр скриншота в мой метод контроллера (@feedback = Feedback.create name: ....., screenshot: params[:screenshot]
) Я получу следующий ответ:
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
Обновить:
После попытки реализовать то, что упомянул @Niraj, я получаю следующий ответ:
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
1 ответ
Примечание: как обсуждено в разделе комментариев
Я изменил ваш _feedback.html.erb
чтобы загрузка файла работала. Пожалуйста, попробуйте этот код и дайте мне знать. Убедитесь, что вы перезапустили свой сервер rails.
<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>