Rails-created apps only generate routing errors in production (AWS)

Asked 2 years ago, Updated 2 years ago, 401 views

rails 6.0.2.1
ruby 2.6.3
amazon linux
mysql
unicorn nginx

We are currently creating an Instagram clone app and deploying it to AWS.
"I would like to make ""Easy Login"" and ""Regular User Logout"" work in the same way as in the development environment."

·I can't log in easily in the production environment
·Regular users cannot log out (login is possible)

·Additional
It works fine in the development environment, so I think the routing configuration itself is correct.
The problem is that in the development environment, the ones that were running post and delete are running as get in the production environment.

If both fail,

The page you are looking for doesn't exist.
You may have mistyped the address or the page may have moved.

On the error screen and log/production.log,

ActionController::RoutingError

appears.

routes.rb

Rails.application.routes.drawdo
  get 'like/create'
  get 'like/destroy'
  get 'sessions/new'
  root'main_page#main'
  get '/signup', to: 'users#new'
  get '/login', to: 'sessions#new'
  post '/login', to: 'sessions#create'
  delete '/logout', to: 'sessions#destroy'
  get '/newpost', to: 'microposts#new'

  resources —users do
    member do
      get:following,:followers
    end
    resources:favorites, only::index
  end

  resources: microposts, only: [:create,:destroy,:show] do
    resources:comments, only:[:create,:destroy]
    resource:favorites, only: [:create,:destroy]
  end

  resources:relationships, only:[:create,:destroy]
  resources:testsessions, only: —create
  resources:like, only:[:create,:destroy]
end

testssessions_controller.rb

class TestsController<ApplicationController
  def create
    user=User.find_by (email: "[email protected]")
    session[:user_id] = user.id
    flash[:success] = "You have logged in as a test user."
    redirect_to root_url
  end
end

sessions_controller.rb

class SessionsController <ApplicationController
  def new
  end

  def create
    user=User.find_by (email:params[:session][:email].downcase)
    if user&user.authenticate (params[:session][:password])
      log_in user
      redirect_back_or user
    else
      flash.now [:danger] = "The email address and password combination are different"
      render 'new'
    end
  end

  def destroy
    log_out
    redirect_to root_url
  end
end

sessions_helper.rb

module SessionsHelper
  deflog_in(user)
    session[:user_id] = user.id
  end

  current_user?(user)
    user==current_user
  end

  current_user
    if session [:user_id]
      @current_user||=User.find_by (id:session[:user_id])
    end
  end

  deflogged_in?
    !current_user.nil?
  end

  deflog_out
    session.delete(:user_id)
    @current_user=nil
  end

  # Redirect to stored URL (or default value)
  default_back_or (default)
    redirect_to (session[:forwarding_url]||default)
    session.delete(:forwarding_url)
  end

  # remember the URL someone tried to access
  def store_location
    session[:forwarding_url] = request.original_url if request.get?
  end
end

users_controller.rb

class UsersController<ApplicationController
  before_action: logged_in_user, only: [:edit,:update,:destroy,:following,:followers]
  before_action: test_user, only: [:edit,:destroy,:following,:followers]
  before_action: correct_user, only: [:edit,:update]

  def show
    @user=User.find (params[:id])
    @[email protected] (page:params[:page])
  end

  def new
    @user=User.new
  end

  def create
    @user=User.new(user_params)
    [email protected]
      log_in@user
      flash[:success] = "Registration completed"
      redirect_to@user
    else
      render 'new'
    end
  end

  default
    @user=User.find (params[:id])
  end

  default update
    @user=User.find (params[:id])
    [email protected]_attributes(user_params)
      flash[:success] = "Your profile has been updated"
      redirect_to@user
    else
      render 'edit'
    end
  end

  def following
    @title="Following"
    @user=User.find (params[:id])
    @[email protected] (page:params[:page])
    render 'show_follow'
  end

  def followers
    @title="Followers"
    @user=User.find (params[:id])
    @[email protected] (page:params[:page])
    render 'show_follow'
  end

  private

    def user_params
      param.require(:user).permit(:name,:email,:password,:password_confirmation,:usericon)
    end

    def correct_user
      @user=User.find (params[:id])
      redirect_to(root_url)unless current_user?(@user)
    end

    def test_user
      @user=User.find(1)
    end
end

user.rb

class User<ApplicationRecord
  has_many:microposts,dependent::destroy
  has_many:active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent::destroy
  has_many:passive_relationships,class_name:"Relationship",foreign_key:"followed_id",dependent::destroy
  has_many:following, through::active_relationships, source::followed
  has_many:followers,through::passive_relationships,source::follower
  has_many:like,dependent::destroy
  has_many:comments,dependent::destroy
  has_many:favorites, dependent::destroy
  has_many:favorite_microposts, through::favorites, source::micropost
  before_save {self.email=email.downcase}
  values:name,presence:true,length:{maximum:50}
  VALID_EMAIL_REGEX=/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  values:email, presence:true,length:{maximum:200},format:{with:VALID_EMAIL_REGEX},
            unity: {case_sensitive:false}
  has_secure_password
  values:password,presence:true,length:{minimum:6},allow_nil:true
  validate —usericon_size
  mount_uploader: usericon, UsericonUploader

  def User.digest(string)
    cost=ActiveModel::SecurePassword.min_cost?BCrypt::Engine::MIN_COST:BCrypt::Engine.cost
    BCrypt::Password.create(string, cost:cost)
  end

  defeed
    Micropost.where ("user_id=?", id)
  end

  defeed
    following_ids="SELECT followed_id FROM relationships WHERE follower_id=:user_id"
    Micropost.where("user_id IN(#{following_ids})OR user_id=:user_id", user_id:id)
  end

  def follow(other_user)
    following <<other_user
  end

  default(other_user)
    active_relationships.find_by (followed_id:other_user.id).destroy
  end

  def following?(other_user)
    following.include?(other_user)
  end

  private
    def usericon_size
      if usericon.size>5.megabytes
        errors.add(:usericon, "Please set the image size to 5MB or less")
      end
    end
end

_header.html.erb

<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%=link_to "Portgram", root_path, id: "logo"%>
    <nav>
    <%if logged_in?%>
      <ul class="nav navbar-nav navbar-center">
        <%=form_tagroot_path, :method=>'get'do%>
          <%=text_field_tag:search,params[:search],placeholder:"Search Posts"%>
          <%=submit_tag "search",:name=>nil,class:"btn btn-primary"%>
        <%end%>
      </ul>
      <ul class="nav navbar-nav navbar-right">
        <li><%=link_to "post", newpost_path%>/li>
        <li><%=link_to "favorites", user_favorites_url(current_user)%>/li>
        <li><%=link_to "My Page", current_user%>/li>
        <li><%=link_to "logout", logout_path, method::delete%>/li>    
      </ul>
    <%end%>
    </nav>
  </div>
</header>

main.html.erb

<%if logged_in?%>
  <div class="row">
    <aside class="col-md-4">
      <section class="user_info">
        <%=render'shared/user_info'%>
      </section>
    </aside>
    <div class="col-md-8">
      <%=render'shared/feed'%>
    </div>
  </div>
<%else%> 
  <div class="center jumbotron background">
    <h1>Portgram</h1>
    <p>Share memories of the sea with everyone</p>

    <%=link_to "Start Now", signup_path, class: "btn btn-lg btn-primary" %>
    <%=link_to "login", login_path, class: "btn btn-lg btn-primary" %>
    <%=link_to "easy login", testsessions_path, method: :post, class: "btn btn-lg btn-primary" %>
  </div>
<%end%>

·Compile assets
·Confirmation of operation in development environment → Everything is fine

When I looked it up, I found out that there was some information about implementing it with heroku and device, but it was not helpful because I didn't use it.
There has been no similar case, so there has been no progress.

If anyone understands, please advise me.

I also checked Google's verification tool and found that the situation is very close to the following.
I think it's related that the js file is not loaded, but I don't understand why it's not resolved by pre-compiling.

http://www.366service.com/jp/qa/9ece5f5fd1de61c43a51cd864834174d

javascript ruby-on-rails aws

2022-09-30 21:49

2 Answers

I solved myself.
Rather than solving the problem directly, it's closer to avoiding it in a different way...

When I used easy login and logout as post and delete HTTP methods in routing,
By changing it to get, it started to work.
I referred to the following articles, but it seems to be related to loading in js.

However, I didn't know exactly how it was affecting me.

https://nisshiee.hatenablog.jp/entry/2017/05/12/100725
https://stackoverflow.com/questions/23368994/no-route-matches-get-logout-rails
https://sevasu.net/programming-2/
Rails application is having trouble with css in production.


2022-09-30 21:49

JavaScript is not working properly, so it is not being treated as POST or DELETE, and routing is failing. Modify JavaScript to work properly. However, the solution is not specific because it requires error messages from the browser verification tool, generated HTML code, and what happens if you access JavaScript files directly.(If you want to solve the problem, the summary of the question has changed, so you should ask a different question while associating it with this question.)

It seems to be handled by changing the routing so that GETs can read it, but that's not a very good way.JavaScript should work properly.

Below is a detailed explanation of the cause.

Why does POST and DELETE routing fail if JavaScript does not work properly?

Rails link_to allows you to optionally specify method::post or method::delete where link_to generates tags for the a element, but with these options data-method="post or These attributes are meaningless in HTML and do not change anything whether JavaScript is still running or not.

By default in Rail 6.0 and later, application.js should be loaded via webpacker in the header of each viwe template (/app/viwe/layouts/application.html.erb).If you look at the source of this application.js (app/javascript/packs/application.js), you will see a module called @rails/ujs.Here's the secret of how link_to works against the tag you just created.

@rails/ujs is a collection of JavaScript that aids Rails. After rails yarn:install, you can see the code in node_modules/@rails/ujs/lib/assets/completed/rails-ujs.js (for version 6.1.3).This JavaScript does many things, but one of them is to change the behavior of the a element with data-method to the specified method.I just took a quick look at the source code, and it seems that it behaves the same way as method specified in form_with etc. (creating a set of form` elements or designating a method in Ajax).

In other words, @rails/ujs allows the browser to have the same access as when POSTing or DELETE using form even though the HTML is just a link to the a element.Rails is determining that and is routing according to the method.Conversely, if @rails/usj does not work properly, the link in the a element is just a link, so it does not occur except for the GET method, and routing may fail.

If you allow routing to be received by GET, you may be able to resolve it.But you're just putting off the fundamental problem of JavaScript not working.@rails/ujs has a lot of other supporting features that can cause problems.Therefore, try to ensure that JavaScript works properly.


2022-09-30 21:49

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.