Strange locale issue in the Rails - ruby-on-rails

I have a url
<li><%= link_to "#{t('feed.add')}", feed_path(locale) %></li>
And the problem is, that after the registration, when I press this link for the first time it redirects me to the mydomain.com/feed and prints the next error:
"feed" is not a valid locale
in the
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
But when I return back and clicks again it redirects me to the:
mydomain.com/en/feed
So, what is the problem of this strange problem?
UPDATE
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
match '', :via => [:get], to: redirect("/#{I18n.locale}")
get '/en/youarethechampion' => "winners#winner"
get "/en/hook" => "feed#hook"
get '/thisvideonotfound' => 'feed#notFound'
get '/:locale/feed', to: 'feed#index', as: 'feed'
post '/:locale/feed/create', to: "feed#create"
get '/:locale/feed/new', to: "feed#new", as: 'feed_new'
get '/:locale/feed/destroy', to: "feed#destroy", as: 'feed_destroy'
get '/:locale/feed/edit', to: "feed#edit", as: 'feed_edit'
get '/:locale/feed/update', to: "feed#update", as: 'feed_update'
scope :path => "(:locale)", :locale => /en|ru/ do
devise_for :users
end
match '/:locale/posts/search/', to: 'home#search', as: 'search', via: :get
get '/:locale/page/:page_slug' => 'home#about'
get '/:locale/:category/:id/', to: 'home#show', as: 'feed_show'
get '/:locale/:id/', except: 'search', to: 'home#by_category', as: 'category'
get '/:locale/posts/user/:name/', to: 'home#by_user', as: 'user'
get '/:locale/posts/tag/:tag/', to: 'home#by_tag', as: 'tag'
get '/:locale/pages/:page/', to: 'page#show', as: 'page'
post '/feed/:id/comments/', to: 'home#create_comment'
get '/:locale/', to: "home#index"

Ok, looks like scenario after the registration: locale is nil, and this line
<li><%= link_to "#{t('feed.add')}", feed_path(locale) %></li>
make link to just /feed. (Try it print it in front of the link)
<li>
Locale is <%= locale %>
<%= link_to "#{t('feed.add')}", feed_path(locale) %>
</li>
Then routes think that /feed is belongs to this route
get '/:locale/', to: "home#index"
and it tries to set feed as the locale. It doesn't work! Then you move to another page you define "real" local through default_locale -> en.
I18n.locale = params[:locale] || I18n.default_locale

Related

Weird path_helper error when using english locale

I am experiencing a weird error that I no longer want to work around but understand.
When recently adding an english version of our homepage, I found that I can't generate the pathes as I do for the german locale:
2.3.0 :023 > I18n.available_locales
=> [:de, :en]
2.3.0 :019 > apps_path(locale: :de)
=> "/de/apps"
2.3.0 :020 > apps_path(locale: :en)
ActionController::UrlGenerationError: No route matches
{:action=>"apps", :controller=>"pages", :locale=>:en} missing required keys: [:locale]
As I said, I was able to work around that, by using either url_for or – when sticking with our example apps_en_path.
But I wanna know what causes this weird problem.
EDIT
A git bisect session helped me to find out that this happens since I added the route-translater gem to my project. Besides this issue it works fine for us.
I had this settings (in development.rb):
# RouteTranslator.config
config.force_locale = true
config.locale_param_key = :locale
My routes.rb:
require_relative "#{Rails.root}/app/route_constraints/can_access_devops"
Rails.application.routes.draw do
get 'health', to: 'health#show'
# Redirect requests with trailing 'null'
get '/*path/null', to: redirect('/%{path}')
namespace :admin do
root to: redirect('/admin/magazine_articles')
resources :jobs
resources :users
resources :magazine_categories
resources :magazine_articles
resources :media_assets
resources :advertisements do
member do
get 'preview'
end
end
namespace :devops do
authenticate :user do
constraints CanAccessDevOps do
mount PgHero::Engine, at: '/pghero'
end
end
end
end
scope '/:locale', locale: /#{I18n.available_locales.join("|")}/ do
root to: 'pages#home'
localized do
devise_for :users, controllers: { sessions: 'sessions' }
# redirect terms of use to cockpit; this is required because
# the packaging has a link that should point to cockpit
get 'home', to: 'pages#home'
get 'imprint', to: 'pages#imprint', as: 'imprint'
get 'lottery', to: 'pages#lottery', as: 'lottery'
get 'privacy', to: 'pages#privacy', as: 'privacy'
get 'terms', to: 'pages#terms', as: 'terms'
get 'faq', to: 'pages#faq', as: 'faq'
get 'declaration-of-conformity', to: 'pages#declaration_of_conformity', as: 'declaration_of_conformity'
# Contact Page / Support Cases
resource :support_cases, only: [:create, :new], path_names: { new: 'new_support_case' } do
get :success, on: :collection
end
# redirect using the url helper to respect route localization. ugly but it works
get 'kontakt', to: redirect { |_, _| Rails.application.routes.url_helpers.new_support_cases_path }
# Workshop
get 'workshop', to: 'pages#workshop', as: 'workshop'
get 'autofit', to: 'pages#autofit', as: 'autofit'
# App-related
get 'app', to: 'pages#app', as: 'app'
get 'apps', to: 'pages#apps', as: 'apps'
get 'cars', to: 'pages#cars', as: 'cars'
get 'roadmap', to: 'pages#roadmap', as: 'roadmap'
# Press Material
get 'press', to: 'press_materials#index', as: 'press_materials'
get 'press/brand', to: 'press_materials#brand', as: 'press_materials_brand'
get 'press/team', to: 'press_materials#team', as: 'press_materials_team'
get 'press/app', to: 'press_materials#app', as: 'press_materials_app'
get 'press/pace-link', to: 'press_materials#pace_link', as: 'press_materials_pace_link'
get 'press/graphics', to: 'press_materials#graphics', as: 'press_materials_graphics'
# Feature pages
get 'features/automatic-emergency-call', to: 'features#ecall', as: 'ecall'
get 'features/fuel-saving-trainer', to: 'features#fuel_saving_trainer', as: 'fuel_saving_trainer'
get 'features/trouble-code-analysis', to: 'features#trouble_code_analysis', as: 'trouble_code_analysis'
get 'features/find-my-car', to: 'features#find_my_car', as: 'find_my_car'
get 'features/logbook', to: 'features#logbook', as: 'logbook'
# old route – preserved as there might be old links somewhere pointing at this
get 'features/automatisches-fahrtenbuch', to: 'features#automatic_logbook'
# actual route: find-the-cheapest-gas-station
get 'features/gas-station-finder', to: 'features#gas_station_finder', as: 'gas_station_finder'
get 'features/fuel-cost-tracking', to: 'features#fuel_cost_tracking', as: 'fuel_cost_tracking'
get 'features/performance-monitor', to: 'features#performance_monitor', as: 'performance_monitor'
get 'features/traffic-monitor', to: 'features#traffic_monitor', as: 'traffic_monitor'
# Endpoints for car finder
get 'cars/query', to: 'cars#identify'
get 'cars/:id', to: 'cars#show'
# Job adverts
get 'jobs', to: 'jobs#index', as: 'jobs'
get 'jobs/:slug', to: 'jobs#show', as: 'job'
# Newsletter related routes
post 'newsletter-sign-up', to: 'subscribers#newsletter_create', as: 'newsletter'
get 'newsletter-confirmation(/:list)', to: 'subscribers#newsletter_after_confirm'
end
# Routes that we want to have under the german locale, but without translated route go here:
# Magazine
scope 'magazin' do
get '', to: 'magazine#index', as: 'magazine', constraints: { locale: 'de' }
# Redirect path without locale to locale equivalent path
get '/*path', to: redirect("/#{I18n.locale}/%{path}"),
constraints: lambda { |req|
!req.path.match(%r{^\/(404|422|500)$}) &&
!req.path.match(%r{^\/(#{I18n.available_locales.join("|")})\/.*})
}
# Redirect root to detected locale
root to: 'application#redirect_to_localized_root', as: :redirected_root
end
I had a quick play through with your routes, and I had I similar issue with the de route. I think the apps_path route you're getting will only allow your default locale as param.
Adding the following option solved it for me:
RouteTranslator.config do |config|
config.generate_unlocalized_routes = true
end
This will generate the unlocalized routes correctly, so you can pass multiple locales to apps_path.
There is nothing that looks super suspicious to me except this localized block. Does this come from some gem? If so does the apps_path(locale: 'en') request work outside of this localized block?
You can use Rails.application.routes.url_helpers.app_path(locale: :en) on the console to test this after adjusting the routes file.

Can't link to another page with user

I want link to another page with my user, but i have an error:
RuntimeError in WelcomeController#edit
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
In my current page
<%= link_to "edit", welcome_edit_path(#user) %>
thi is my controller
def edit
user = User.find_by_id(#user.id)
end
in my page i want link to
<%= user.id %>
I know my problem is my #user was nil, but i dont know how to link to another page with my #user
So, please! help me
this my routes file
get "micropost/new"
get "user/new"
get "user/saved"
get "post/new"
get "post/show"
get "welcome/index"
get "welcome/sucess"
get "welcome/edit"
root :to => "welcome#index"
get '/users/:id', :to => 'welcome#sucess', :as => "user"
match '/relations', to: 'relation#create', via: 'post'
match '/relations/:id', to: 'relation#destroy', via: 'delete'
resources :users
resources :relations, only: [:create, :destroy]
resources :microposts
match '/login', to: 'welcome#create', via: 'post'
match '/logout' => 'welcome#destroy', as: :logout
match '/create', to: 'micropost#create', via: 'post'
match '/signup', to: 'user#signup', via: 'post'
Your code in edit method makes no sense. First thing, you have to define your route properly:
get '/welcome/edit/:id', to: 'welcome#edit', as: 'welcome_edit'
Then, in the WelcomeController:
def edit
#user = User.find(params[:id])
end
and the link to this page:
<%= link_to 'edit', welcome_edit_path(#user) %>

Couldn't find User with id=sign_out

Sign-out link isn't working in my rails application.
I have checked my routes.rb which is listed below and my application.html.erb looks to follow the right path.
Getting the following error.
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with id=sign_out
Rails.root: /Users/patrickwalsh/rails_projects/ytutorial
Application Trace | Framework Trace | Full Trace
app/controllers/users_controller.rb:4:in `show'
lib/disable_assets_logger.rb:11:in `call'
My routes.rb
Refectory::Application.routes.draw do
devise_for :users, :controllers => { :registrations => "users" }
devise_scope :user do
get 'login', to: "devise/sessions#new", as: "login"
get 'logout', to: "devise/sessions#destroy", as: "logout"
get 'logout', to: "users/sessions#destroy", as: "logout"
get 'signup', to: "users#new", as: "signup"
match '/users/:id', :to => 'users#show', :as => :user
end
root :to => 'tutorials#index'
devise_for :users do get '/users/sign_out' => 'devise/sessions#destroy'
get 'users/:id' => 'users#show'
end
resources :tutorials
resources :comments, only: [:show, :create, :update, :destroy]
resources :tutorials do
member { post :vote }
end
if Rails.env == "development"
match 'errors/404' => 'errors#error_404'
match 'errors/500' => 'errors#error_500'
end
unless Rails.application.config.consider_all_requests_local
match '*not_found', to: 'errors#error_404'
end
match 'tagged' => 'tutorials#tagged', :as => 'tagged'
end
and my application.html which seems to be following the right route from what I can see.
Any help is greatly appreciated!
<% if current_user.present? %>
<li><%= link_to "Log out", destroy_user_session_path, (:method => "delete") %></li>
<% else %>
<li><%= link_to "Log in", new_user_session_path %></li>
<li><%= link_to "Sign up", new_user_registration_path %></li>
<% end %>
My users controller as well as I have a suspicion this is where the problem lies but not sure what the error is.
class UsersController < Devise::RegistrationsController
def show
#user = User.find(params[:id])
#tutorials = #user.tutorials
end
end
I had the same issue. My routes were in the correct order, the link_to method was properly used, and Rails kept triggering the users/:id route with :id => :sign_out. I figured out that was because I removed jquery_ujs from my application.js file...
jquery_ujs handles the data-method attribute in the links (generated by link_to when you use the method option), which is used to determine the correct route as explained here: https://thoughtbot.com/blog/a-tour-of-rails-jquery-ujs
So just make sure the you have the following included in your application.js:
//= require jquery
//= require jquery_ujs
If you are calling /users/sign_out directly from the URL it won't work because the routes is:
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
id est, it uses the DELETE method. You need to change your devise initializer to:
config.sign_out_via = :get
other option would be to create a small form and its button with DELETE as method.
This worked for me
#form
<%= link_to(destroy_user_session_path, {:class => "nav-link", :method => :delete}) do %>
<span class="sidebar-normal"> Logout </span>
<% end %>
#routes
devise_scope :user do
get '/users/sign_out' => 'devise/sessions#destroy'
end
I have started noticing this error after removing rails-ujs. This was done as part of the upgrade to Rails 7 with ImportMap and Hotwire suite. Changing link_to to button_to has fixed this error in this case.
<%= button_to 'Log out', destroy_user_session_path, method: :delete %>
https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#replacements-for-rails-ujs-functionality
None of this solutions worked for me.
Also it happens just in development mode for me...
I fixed it by adding
if params[:id] = "sign_out"
sign_out current_user
return
end
in the set user function. Not the prettiest solution but it works...
You need to move:
devise_for :users do get '/users/sign_out' => 'devise/sessions#destroy'
over your devise_scope. Rails is looking for routes from top of Routes file. Your sign out url matches users/:id, hence it is trying to render show action with sign_out being an id.
UPDATE:
Actually, do you really need the last line in your devise_scope block?
Since non of the other answers worked, I found that you could change the base path for every Devise endpoint as described here. So, what I did was to user devise_for on routes.rb:
devise_for :users,
path: 'devise'
Then, all my Devise routes started with devise instead of users so the conflict was gone.
Sorry to bump this up but the "correct" anwser is not to mess around with routes risking breaking many things.
IF you want a disconnect on a GET then actually configure Devise like so in initializer/devise.rb
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :get
As mentionned in the Devise documentation.
Short answer: use link_to with method DELETE
<%= link_to 'Logout', destroy_user_session_path(current_user), method: :delete %>
explanation:
If you take a look at your Routes you'll see
Helper
destroy_user_session_path
the HTTP verb is
DELETE
the Path
/users/sign_out(.:format)
Controller#Action
devise/sessions#destroy
link_to defaoult method is get, this is "the why" (in a simplistic way of explaning). However, you can specify by using method: :method name
I got this error when using devise in a rails 7 app (with bootstrap):
ActiveRecord::RecordNotFound (Couldn't find User with 'id'=sign_out)
I don't fully understand it myself yet, but basically just open another terminal window, type ./bin/dev and hit enter, and (I guess) it loads your javascripts.

how to remove action and controller from url in rails link_to

Here is my link_to
<%= link_to sub_category.name, controller: :posts, action: :product, id: "#{sub_category.slug}-#{sub_category.id}" %>
Which is pointing to the url
http://localhost:3000/posts/product/fifith-category-s-sub-category-2
I need the url as follows
http://localhost:3000/fifith-category-s-sub-category-2
How can i do it.
my route.rb
resources :posts
match ':controller(/:action(/:id))(.:format)', via: [:get,:post]
what #MarekLipka suggests is correct but defining your routes like this will take up all the single level namespace in your app i.e. "/anything" will route by default to posts#product.
I recommended using some form of identifier to figure out which routes should go to posts#product. What will work for you depends on why you want to do this. Couple of options are:
Use a short namespace:
scope '/pp' do
get ':id', to: 'posts#product
end
# "/pp/:id" routes to 'posts/product'
# pp is a random short name I picked, it could be anything
# link
<%= link_to sub_category.name, "pp/#{sub_category.slug}-#{sub_category.id}" %>
Use a constraint:
get ':id', to: 'posts#product`, constraints: { :id => /sub\-category/ }
# only id's with 'sub-cateogry' route to 'posts/product'
# link (assuming that sub_category.slug has 'sub-category' words in it)
<%= link_to sub_category.name, "#{sub_category.slug}-#{sub_category.id}" %>
If you want path /:id match your posts#product, you should have something like this in your routes:
resources :posts
match ':id', to: 'posts#product`, via: :get
match ':controller(/:action(/:id))(.:format)', via: [:get, :post]

Routing Error: uninitialized constant UserFriendshipsController

I am working on a Team Treehouse Ruby on Rails app that emulates a basic Facebook app.
I am now added social feature's like friends.
I recently added the following link to one of my views:
<%= link_to "Add Friend", new_user_friendship_path(friend_id: #user), class: 'btn' %>
When click the resulting button, I get the following error:
Routing Error
uninitialized constant UserFriendshipsController
Try running rake routes for more information on available routes.
I am thinking the problem is in either my "user_friendship_controller.rb" of "config/routes.rb " file.
Here is my "user_friendship_controller.rb file:
class UserFriendshipsController < ApplicationController
before_filter :authenticate_user!, only: [:new]
def new
if params[:friend_id]
#friend = User.where(profile_name: params[:friend_id]).first
#user_friendship = current_user.user_friendships.new(friend: #friend)
else
flash[:error] = "Friend required"
end
rescue ActiveRecord::RecordNotFound
render file: 'public/404', status: :not_found
end
end
And here is my "config/routes" file:
Treebook::Application.routes.draw do
as :user do
get '/register', to: 'devise/registrations#new',via: :get, as: :register
get '/login', to: 'devise/sessions#new', via: :get, as: :login
get '/logout', to: 'devise/sessions#destroy', via: :delete, as: :logout
end
devise_for :users, :skip => [:sessions]
as :user do
get '/login' => 'devise/sessions#new', as: :new_user_session
post '/login' => 'devise/sessions#create', as: :user_session
delete '/logout' => 'devise/sessions#destroy', as: :destroy_user_session
end
resources :user_friendships do
end
resources :statuses
get 'feed', to: 'statuses#index', as: :feed
root to: 'statuses#index'
get '/:id', to: 'profiles#show', as: 'profile'
end
Any help figuring out this bug is a great help.
Thanks
It looks like it's just a simple mis-naming of your file.
Try renaming it to user_friendships_controller.rb. Rails expects your class declaration to match the file name (as it stands it'd be looking for you to define UserFriendshipController).

Resources