我有一个 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 & 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 & 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