0

我有一个 Rails 应用程序,我在其中使用一些参数实现搜索。我有一个 Product 模型,它有两个参数 State 和 City,在主页上我有一个具有相同参数 State 和 City 的搜索表单。逻辑是,如果用户在特定州和城市搜索特定产品,他将看到具有相同州和城市的产品的结果。

该网站在 Heroku 上运行(这是应用程序)并且在我的笔记本电脑上运行良好,但在移动设备上我收到此错误,此错误仅在选择状态时出现在移动设备上:

Failed to submit error Unauthorized

我检查了日志并得到了这个

2019-05-19T11:29:09.982781+00:00 app[web.1]: [2571fe96-0174-4c3f-bc2c-a3bbe126bf55] Started POST "/get_cities_by_state" for 47.15.193.135 at 2019-05-19 11:29:09 +0000
2019-05-19T11:29:09.984478+00:00 app[web.1]: [2571fe96-0174-4c3f-bc2c-a3bbe126bf55] Processing by ProductsController#get_cities_by_state as JSON
2019-05-19T11:29:09.984857+00:00 app[web.1]: [2571fe96-0174-4c3f-bc2c-a3bbe126bf55]   Parameters: {"state"=>"1"}
2019-05-19T11:29:09.985638+00:00 app[web.1]: [2571fe96-0174-4c3f-bc2c-a3bbe126bf55] Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)
2019-05-19T11:49:06.438325+00:00 heroku[router]: at=info method=POST path="/get_cities_by_state" host=powerful-reef-70297.herokuapp.com request_id=551700ff-038b-40e9-ad8d-7cb35f7ff7ca fwd="47.15.193.135" dyno=web.1 connect=0ms service=8ms status=401 bytes=678 protocol=https
2019-05-19T11:49:06.433346+00:00 app[web.1]: [551700ff-038b-40e9-ad8d-7cb35f7ff7ca] Started POST "/get_cities_by_state" for 47.15.193.135 at 2019-05-19 11:49:06 +0000
2019-05-19T11:49:06.437059+00:00 app[web.1]: [551700ff-038b-40e9-ad8d-7cb35f7ff7ca] Processing by ProductsController#get_cities_by_state as JSON
2019-05-19T11:49:06.437115+00:00 app[web.1]: [551700ff-038b-40e9-ad8d-7cb35f7ff7ca]   Parameters: {"state"=>"2"}
2019-05-19T11:49:06.437883+00:00 app[web.1]: [551700ff-038b-40e9-ad8d-7cb35f7ff7ca] Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)

我的产品表格

<!DOCTYPE html>
<html lang="en">

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<%= render 'welcome/sub' %>
<%= form_with(model: product, local: true) do |form| %>
  <% if product.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2>

      <ul>
      <% product.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

<div class="form-style-5">
<form>
<fieldset>
<legend><span class="number">1</span> General Info</legend>
<%= form.text_field :name, id: :product_name, placeholder: "Add name of your product or service here" %>
<%= form.text_area :description, id: :product_description, placeholder: "Full Description" %>
<label for="job" style="color:#000;">Images:</label>
<%= form.file_field :image, id: :product_image %>
<%= form.file_field :imagetwo, id: :product_image %>
<%= form.file_field :imagethree, id: :product_image %>   
</fieldset>
<fieldset>
<legend><span class="number">2</span> Additional Info</legend>
<label for="job" style="color:#000;">Categories:</label>
</fieldset>
<fieldset>

<%= form.select :state, options_for_select([["Select a state",""]] + State.all.map { |c| [c.name, c.id] },selected:  product.state ), {}, id: "state"%>
<%= form.select :city, options_for_select([["Select a City",""]]),{}, :id => 'city' %>

</fieldset>
<div class="actions">
    <%= form.submit %>
  </div>
</form>
</div>
<% end %>



<script type="text/javascript">
var  selectedCity;
<% if product.city.present? %>
  selectedCity = <%= product.city  %>;
<% end %>
$(function() {
  if ($("select#state").val() == "") {
    $("select#city option").remove();
    var row = "<option value=\"" + "" + "\">" + "city" + "</option>";
    $(row).appendTo("select#city");
   }
   var $val = $("select#state").val();
   if($val != ""){
     getCitiesOfState($val)
   }

   $("select#state").change(function() {
    var id_value_string = $(this).val();
    if (id_value_string == "") {
     $("select#city option").remove();
     var row = "<option value=\"" + "" + "\">" + "city" + "</option>";
     $(row).appendTo("select#city");
    } else {
     // Send the request and update city dropdown
      getCitiesOfState(id_value_string)

    }
   });

  });  
</script>

我的产品控制器

class ProductsController < ApplicationController
  before_action :authenticate_user!, except: [:index, :show]
  before_action :set_product, only: [:show, :edit, :update, :destroy]

  # GET /products
  # GET /products.json
  def index
    @products = Product.all
  end

  # GET /products/1
  # GET /products/1.json
  def show
  end

  # GET /products/new
  def new
    @product = current_user.shop.products.build

  end

  # GET /products/1/edit
  def edit
  end

  # POST /products
  # POST /products.json
  def create
    @product = current_user.shop.products.build(product_params)
    @product.user = current_user

    respond_to do |format|
      if @product.save
        format.html { redirect_to @product, notice: 'Product was successfully created.' }
        format.json { render :show, status: :created, location: @product }
      else
        format.html { render :new }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /products/1
  # PATCH/PUT /products/1.json
  def update
    respond_to do |format|
      if @product.update(product_params)
        format.html { redirect_to @product, notice: 'Product was successfully updated.' }
        format.json { render :show, status: :ok, location: @product }
      else
        format.html { render :edit }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /products/1
  # DELETE /products/1.json
  def destroy
    @product.destroy
    respond_to do |format|
      format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
      format.json { head :no_content }
    end
  end
  #new methods
  def get_cities_by_state
    @cities = State.find(params[:state]).cities
    respond_to do |format|
      format.json { render :json => @cities }
    end
  end 

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_product
      @product = Product.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def product_params
      params.require(:product).permit(:name, :price, :description, :image, :imagetwo, :imagethree, :category, :city, :state, :sub_category)
    end
end

我的主页

<% if mobile_device == "mobile" %>
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
    <meta name="author" content="Colorlib">
    <meta name="description" content="#">
    <meta name="keywords" content="#">
    <!-- Page Title -->
    <title>Listing &amp; Directory Website Template</title>
    <!-- Bootstrap CSS -->

    <!-- Google Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700,900" rel="stylesheet">
    <!-- Simple line Icon -->
    <link rel="stylesheet" href="/assets/simple-line-icons.css">
    <!-- Themify Icon -->
    <link rel="stylesheet" href="/assets/themify-icons.css">
    <!-- Hover Effects -->
    <link rel="stylesheet" href="/assets/set1.css">
    <!-- Main CSS -->
    <link rel="stylesheet" href="/assets/style.css">
</head>

<body>

  <%= render 'welcome/sub' %>


<section class="slider d-flex align-items-center" style="max-height:80px;">
        <!-- <img src="/assets/slider.jpg" class="img-fluid" alt="#"> -->
        <div class="container" >
            <div class="row d-flex justify-content-center">
                <div class="col-md-12">
                    <div class="slider-title_box">
                        <div class="row">
                            <div class="col-md-12">
                                <div class="slider-content_wrap">


                                    <br>
                                    <br>
                                </div>
                            </div>
                        </div>
                        <div class="row d-flex justify-content-center">
                            <div class="col-md-10">
                                <form class="form-wrap mt-4">
                                    <div class="btn-group" role="group" aria-label="Basic example">
                                        <input type="text" placeholder="What are your looking for?" id="search" class="btn-group1">


                                        <%= select_tag :state, options_for_select([["Select a state",""]] + State.all.map { |c| [c.name, c.id] } ), id: "state"%>
                                        <%= select_tag :city, options_for_select([["Select a City",""]]), :id => 'city' %>

                                        <a href="/welcome/search" class="btn-form search-btn">SEARCH<i class="pe-7s-angle-right"></i></a>
                                    </div>
                                </form>

                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>


                <div class="col-md-5">
                    <div class="styled-heading">
                        <h3>What are you finding?</h3>
                    </div>
                </div>

  </div>



  </body>
</html>


    <script>
function openNav() {
  document.getElementById("mySidenav").style.width = "250px";
}

function closeNav() {
  document.getElementById("mySidenav").style.width = "0";
}
</script>

    <script>
        $(window).scroll(function() {
            // 100 = The point you would like to fade the nav in.

            if ($(window).scrollTop() > 100) {

                $('.fixed').addClass('is-sticky');

            } else {

                $('.fixed').removeClass('is-sticky');

            };
        });
    </script>
</body>

</html>

<% else %>

<!DOCTYPE html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="author" content="Colorlib">
    <meta name="description" content="#">
    <meta name="keywords" content="#">
    <!-- Page Title -->
    <title>Listing &amp; Directory Website Template</title>
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="/assets/bootstrap.min.css">
    <!-- Google Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700,900" rel="stylesheet">
    <!-- Simple line Icon -->
    <link rel="stylesheet" href="/assets/simple-line-icons.css">
    <!-- Themify Icon -->
    <link rel="stylesheet" href="/assets/themify-icons.css">
    <!-- Hover Effects -->
    <link rel="stylesheet" href="/assets/set1.css">
    <!-- Main CSS -->
    <link rel="stylesheet" href="/assets/style.css">
</head>
    <section class="slider d-flex align-items-center">
        <!-- <img src="/assets/slider.jpg" class="img-fluid" alt="#"> -->
        <div class="container">
            <div class="row d-flex justify-content-center">
                <div class="col-md-12">
                    <div class="slider-title_box">
                        <div class="row">
                            <div class="col-md-12">
                                <div class="slider-content_wrap">

<br>
<br>
<br>
<br>
                                    <h1>Discover what's great Near You</h1>
                                    <h5>Let's uncover the best places to eat, drink, and shop nearest to you.</h5>
                                </div>
                            </div>
                        </div>
                        <div class="row d-flex justify-content-center">
                            <div class="col-md-10">
                                <form class="form-wrap mt-4">
                                    <div class="btn-group" role="group" aria-label="Basic example">
                                        <input type="text" placeholder="What are your looking for?" id="search" class="btn-group1">


                                        <%= select_tag :state, options_for_select([["Select a state",""]] + State.all.map { |c| [c.name, c.id] } ), id: "state"%>
                                        <%= select_tag :city, options_for_select([["Select a City",""]]), :id => 'city' %>

                                        <a href="/welcome/search" class="btn-form search-btn">SEARCH<i class="pe-7s-angle-right"></i></a>
                                    </div>
                                </form>
                                <div class="slider-link">
                                    <a href="/welcome/popular">Browse Popular</a><span>or</span> <a href="/welcome/recent">Recently Addred</a>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <script>
function openNav() {
  document.getElementById("mySidenav").style.width = "250px";
}

function closeNav() {
  document.getElementById("mySidenav").style.width = "0";
}
</script>


</body>
<% end %>
 </script>

     <script>
        $(window).scroll(function() {
            // 100 = The point you would like to fade the nav in.

            if ($(window).scrollTop() > 100) {

                $('.fixed').addClass('is-sticky');

            } else {

                $('.fixed').removeClass('is-sticky');

            };
        });
        var selectedCity;
        $("select#state").change(function() {
          var id_value_string = $(this).val();
          if (id_value_string == "") {
           $("select#city option").remove();
           var row = "<option value=\"" + "" + "\">" + "city" + "</option>";
           $(row).appendTo("select#city");
          } else {
           // Send the request and update city dropdown
            getCitiesOfState(id_value_string)

          }
         });
        $(".search-btn").on("click", function(e){
          e.preventDefault()
          var $this = $(this);
          var $href = $this.attr("href");
          var state = $("#state").val()
          var city = $("#city").val()
          var search = $("#search").val()
          window.location = $href + '?search=' + search+ "&state=" +state+ "&city="+ city
        })
        function getCitiesOfState(val){
        $.ajax({
          dataType: "json",
          cache: false,
          beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
          url: '/get_cities_by_state',
          type: 'post',
          data: {"state" : val},
          timeout: 5000,
          error: function(XMLHttpRequest, errorTextStatus, error) {
           alert("Failed to submit : " + errorTextStatus + " ;" + error);
          },
          success: function(data) {
           // Clear all options from city select
           $("select#city option").remove();
           //put in a empty default line
           // Fill city select

           var row = "<option value=\"" + "" + "\">" + "Select a city" + "</option>";
           $(row).appendTo("select#city");
           $.each(data, function(i, j) {
            if(j.id == selectedCity){
              row = "<option value=\"" + j.id + "\" selected>" + j.name + "</option>";
            }else{
              row = "<option value=\"" + j.id + "\">" + j.name + "</option>"; 
            }
            $(row).appendTo("select#city");
           });
          }
         });
       }
    </script>
</html>

我的搜索

def search
  @products = Product.where('(name LIKE ? OR description LIKE ? )', "%#{params[:search]}%", "%#{params[:search]}%")
  @products = @products.where(state: params[:state]) if params[:state].present?
  @products = @products.where(city: params[:city]) if params[:city].present?
  end

*Routes*
  post :get_cities_by_state,       action: :get_cities_by_state, controller: :products
4

1 回答 1

0

尝试在 in 之后添加此行ApplicationController

#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  skip_before_action :verify_authenticity_token
end

有关这方面的详细信息,请查看此博客:https ://www.codementor.io/kristophmatthews/how-to-configure-your-first-rails-rest-api-du1084ym0#turn-off-forgery-protection

于 2019-05-21T08:59:26.057 回答