ruby 在 rails - activestorage

ruby on rails - activestorage

在尝试实现一个文件字段后,用户可以上传带有回形针反馈的屏幕截图,我收到了一些 'no handle errors'。 我也提出了关于回形针问题的问题 here.

通过查看对我的问题的评论,它可能与 multipart 有关。

但是因为我不使用 rails 形式,所以我不能做类似 form_for multipart true 的事情。 我正在通过我当前的表单处理一些 js 并且真的不想更改所有这些,这就是为什么我现在尝试从已弃用的回形针切换到 rails 活动存储。到目前为止一切顺利。

我的表格仍然 运行 并且工作正常,直到我将屏幕截图写入数据库。

这是我在提交反馈时得到的回复示例。

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" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
   (0.2ms)  BEGIN
  Feedback Create (41.3ms)  INSERT INTO "feedbacks" ("message", "topic", "name", "created_at", "updated_at") VALUES (, , , , ) 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" =  ORDER BY "users"."id" ASC LIMIT   [["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" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
   (0.2ms)  BEGIN
  Feedback Create (1.4ms)  INSERT INTO "feedbacks" ("message", "topic", "name", "created_at", "updated_at") VALUES (, , , , ) 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" =  AND "active_storage_attachments"."record_type" =  AND "active_storage_attachments"."name" =  LIMIT   [["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'

更新2:

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

注:如评论区所述


我已经修改了您的 _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>