Ruby Rails 3.2 Locale with folder_name path in URL - ruby

I have a trio of Ruby/Rails applets running under the following setup:
services.mydomain.com/applet1
services.mydomain.com/applet2
services.mydomain.com/applet3
These are served via Phusion Passenger, and App1 and App2 work exactly as expected.
The problem is with App3 which uses I18n Locales embedded in the URL:
services.mydomain.com/applet3/en/
services.mydomain.com/applet3/fr/
services.mydomain.com/applet3/es/
The problem seems to be that the link_to URLs don't seem to include the "applet3". So instead of:
services.mydomain.com/applet3/en/signin
I get:
services.mydomain.com/en/signin
... which is unrouteable.
My routes.rb looks like:
Rails.application.routes.draw do
scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
resources :users
resources :sessions, only: [:new, :create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
root to: "static_pages#home"
end # scope locale
end # Rails.application.routes.draw do
... and in app/controllers/application_controller.rb I have:
before_filter :set_locale_from_params
def url_options
{ only_path: true, locale: I18n.locale }
end
protected
def set_locale_from_params
if params[:locale]
if I18n.available_locales.include?(params[:locale].to_sym)
I18n.locale = params[:locale]
else
flash.now[:notice] = 'Translation not available'
logger.error flash.now[:notice]
end
end
end
... and in config/environments/production.rb I have:
Rails.application.routes.default_url_options[:host] = 'http://services.mydomain.com/applet3/'
EDIT1: add example link_to statement
<%= link_to(t(".#{language}"), root_path(locale: language)) %>
/EDIT1
If I move App3 to a more "normal" arrangement where there is no "folder_name" in the URL path, everything works fine. So it's something simple I'm missing with how to set up the scope or the URL Options.
Thanks in advance for any help & suggestions!

what about use constraints into your route to define your sub module route ?
Rails.application.routes.draw do
constraints(:host) do
scope :path => ":locale" , locale: /#{I18n.available_locales.join("|")}/ do
resources :users
resources :sessions, only: [:new, :create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
root to: "static_pages#home"
end # scope locale
end # constraints
end # Rails.application.routes.draw do

You are using root_path and expecting applet3 to be added, on doing rake routes did you check what was the path for root ?
You might have to explicitly set the root path in your routes file to enable routes_path work properly.

Related

What's the equivalent of rake routes in Phoenix?

Ruby on Rails comes with the terminal command rake routes. Is there an equivalent in Phoenix?
The command is $ mix phoenix.routes
As #Martimatix pointed out $ mix phx.routes print all routes for the default router, here's the documentation
This is an example of routes generated for this router.ex file:
defmodule MessageApi.Router do
use MessageApi.Web, :router
pipeline :api do
plug :accepts, ["json"]
end
scope "/api", MessageApi do
pipe_through :api
resources "/messages", MessageController, except: [:new, :edit]
resources "/message_details", MessageDetailController, except: [:new, :edit]
end
end
then routes generated will be:
message_path GET /api/messages MessageApi.MessageController :index
message_path GET /api/messages/:id MessageApi.MessageController :show
message_path POST /api/messages MessageApi.MessageController :create
message_path PATCH /api/messages/:id MessageApi.MessageController :update
PUT /api/messages/:id MessageApi.MessageController :update
message_path DELETE /api/messages/:id MessageApi.MessageController :delete
message_detail_path GET /api/message_details MessageApi.MessageDetailController :index
message_detail_path GET /api/message_details/:id MessageApi.MessageDetailController :show
message_detail_path POST /api/message_details MessageApi.MessageDetailController :create
message_detail_path PATCH /api/message_details/:id MessageApi.MessageDetailController :update
PUT /api/message_details/:id MessageApi.MessageDetailController :update
message_detail_path DELETE /api/message_details/:id MessageApi.MessageDetailController :delete

Issue with Routes when implementing a nested form

I am building out a CAD App with Rails 4 Ruby 2
I have a Call model and a Update model and I am beginning the process to nest the Update into my call.
I have already completed the views and controller nesting etc but I seem to be hung up on my Routes.rb.
The error I am getting is:
Can't use collection outside resource(s) scope
My Routes.rb file looks like:
resources :calls do
resources :updates, except: [:index], controller: 'calls/updates'
end
collection do
get 'history'
end
member do
patch :update_unit_on_scene
patch :update_unit_clear
patch :update_unit2_os
patch :update_unit2_cl
patch :update_unit3_os
patch :update_unit3_cl
patch :update_unit4_os
patch :update_unit4_cl
end
I am very new with Nested forms / views etc so I am thinking this is where I am going wrong.
My Full Routes File:
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'registrations' }
devise_scope :user do
authenticated :user do
root 'calls#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
resources :sites
resources :calls do
resources :updates, except: [:index], controller: 'calls/updates'
end
collection do
get 'history'
end
member do
patch :update_unit_on_scene
patch :update_unit_clear
patch :update_unit2_os
patch :update_unit2_cl
patch :update_unit3_os
patch :update_unit3_cl
patch :update_unit4_os
patch :update_unit4_cl
end
end
Your routes file seems to have a misplaced end keyword. Try writing your routes file like so:
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'registrations' }
devise_scope :user do
authenticated :user do
root 'calls#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
resources :sites
resources :calls do
resources :updates, except: [:index], controller: 'calls/updates'
# end keyword was placed here initially, which was closing off
# the resource scope for the routes being defined below,
# causing the error you were seeing
collection do
get 'history'
end
member do
patch :update_unit_on_scene
patch :update_unit_clear
patch :update_unit2_os
patch :update_unit2_cl
patch :update_unit3_os
patch :update_unit3_cl
patch :update_unit4_os
patch :update_unit4_cl
end
# moving end keyword to this position ensures that the calls resource
# properly encloses the collection and member routes
end
end
Hope it helps!

heroku: ActionController::RoutingError (No route matches [GET] "/newrelic")

ERROR
ActionController::RoutingError (No route matches [GET] "/newrelic")
# and I am getting error page for both staging and production heroku servers
Documentation
https://devcenter.heroku.com/articles/newrelic
GEM
https://github.com/newrelic/rpm
# ruby 2.1.0p0
# rails 4.0.1
Both environment variables NEW_RELIC_LICENSE_KEY and NEW_RELIC_APP_NAME are set to heroku config variable
Gemfile
gem "newrelic_rpm", "~> 3.5.7.59"
config/newrelic.yml
common: &default_settings
license_key: <%= ENV['NEW_RELIC_LICENSE_KEY'] %>
app_name: <%= ENV["NEW_RELIC_APP_NAME"] %>
monitor_mode: true
developer_mode: false
log_level: info
browser_monitoring:
auto_instrument: true
audit_log:
enabled: false
capture_params: false
transaction_tracer:
enabled: true
transaction_threshold: apdex_f
record_sql: obfuscated
stack_trace_threshold: 0.500
error_collector:
enabled: true
capture_source: true
ignore_errors: "ActionController::RoutingError,Sinatra::NotFound"
development:
<<: *default_settings
monitor_mode: true
developer_mode: true
test:
<<: *default_settings
monitor_mode: false
production:
<<: *default_settings
monitor_mode: true
staging:
<<: *default_settings
monitor_mode: true
app_name: <%= ENV["NEW_RELIC_APP_NAME"] %> (Staging)
[NOTE: I have two application hosted to heroku:]
(staging).herokuapp.com
(production).herokuapp.com
And I want to configure new-relic for both environments/servers.
Also, Note that this configuration is working fine in development(localhost) environmet.
EDITED
config/routes.rb
Demo::Application.routes.draw do
root :to => "home#index"
devise_for :users,:controllers => {:sessions => "sessions",:omniauth_callbacks => "omniauth_callbacks" }
post '/tinymce_assets' => 'tinymce_assets#create'
resources :home
namespace :admin do
resources :dashboards
resources :users do
member do
get :reset
put :reset_pw
put :delete_record
put :restore_user
end
end
end
resources :drives do
member do
put :destroy_drive
post :add_consolidation
put :delete_consolidation
post :add_driveorganizer
put :delete_drive_organizer
put :restore_drirve
end
collection do
get :recalculate_consolidation
end
resources :drive_details do
resources :images
end
end
resources :products do
member do
post :add_category
put :destroy_pc
put :delete_product
put :restore_products
end
end
resources :stores do
member do
put :delete_store
end
end
resources :store_products do
member do
put :delete_storeproduct
post :add_package_items
put :delete_package_item
put :restore_store_product
get :get_product_price
end
collection do
get :autocomplete_others
end
end
resources :orders do
member do
put :delete_order
put :restore_order
get :charge_stripe
end
resources :order_items do
collection do
post :display_price
end
member do
put :delete_record
end
end
end
resources :categories do
member do
put :delete_category
put :restore_category
end
collection do
get :move
end
end
namespace :user do
resources :campaigns do
member do
get :single_campaign
end
resources :stores
resources :carts do
collection do
post :carts_update
get :checkout_final
get :payment
post :payment
get :update_payment
get :update_payment_and_redirect
get :confirmation
post :confirmation
get :finish
post :confirmation_update
put :empty_cart
post :shelter_survey
end
member do
put :destroy_oi
put :checkout
end
end
end
end
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end
# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable
# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end
Thanks
Based on the error you're getting, it looks like you're trying to access the route to the New Relic Ruby agent's developer mode in your staging and production environments. Developer mode installs a middleware in your app that responds to any URL prepended with /newrelic. Because you've enabled Developer mode in your development (localhost) environment (the developer_mode key is set to true in your newrelic.yml under development), accessing this route succeeds there, but it fails in staging and production because you don't have developer mode enabled in those environments.
Your current configuration is usually desirable, since Developer mode introduces a large amount of overhead that is generally unacceptable in production. Rather than attempt to access the route in staging or production, use it during development only.
You may also want to consider upgrading the version of the agent you are using, since version 3.5.7 does not fully support Ruby 2.0 or Rails 4. More information on releases can be found at https://docs.newrelic.com/docs/releases/ruby.

rails 3 multiple language for any user

I want my app has multiple languages. To do this, I read railscasts #138
But there, the writer put a language column to User model and thus users can see pages only in their language as I understand right. But I want my website can be seen in any language by any user just like usual.
How can this be done?
I have solved. I added to controllers/application_controller.rb this:
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
private
def default_url_options(options={})
logger.debug "default_url_options is passed options: #{options.inspect}\n"
{ :locale => I18n.locale }
end
Then I added this to views/layouts/_header.html.erb:
<li><% if I18n.locale == I18n.default_locale %>
<%= link_to "Türkçe", :locale=>'tr'%>
<% else %>
<%= link_to "English", :locale=>'en'%>
<%end%></li>
Then to config/routes.rb this:
scope "(:locale)", :locale => /en|tr/ do # at the beginning
match '/home' , to: 'static_pages#home'
match '/help' , to: 'static_pages#help'
match '/about' , to: 'static_pages#about'
.....
end
Thats it!
You might want to take a look at this great Rails guide.
in addition to #Pierre-Louis answer, you can look at globalize3 gem

inherited_resources - best practices for missing parent model

Maybe you have seen/read the Railscast/Asciicast about subdomains in Rails 3. I'd like you to ask about best practices on how to implement an application behavior when the parent (in this article: "blog") is not found. Let me explain.
blog1.example.com/articles # it's normal situation
example.com/articles # abnormal situation.
In the second example no blog to find, but articles's routes are still available. I know, I can use something like this ...
def rescue_action(exception)
case exception
when ActiveRecord::RecordNotFound
return redirect_to blogs_path, :status => :moved_permanently
end
super
end
... but is it the "Rails way"? Any idea/comment on this?
What I did in this case, was to restrict the routing based on subdomain or no subdomain. In that case, you can easily have routes that only work on subdomains, resulting in a routing error (404) if someone tries to access that same route without a subdomain.
So for example:
routes.rb
Backend::Application.routes.draw do
constraints AppDomainRoutes.new do
# signup paths
get "/signup" => "accounts#new", as: "signup"
post "/signup" => "accounts#create", as: "signup"
# root
root to: "accounts#new"
end
constraints AccountDomainRoutes.new do
# password reset paths
get "/reset_password/:password_reset_token" => "reset_passwords#edit", as: "reset_user_password"
put "/reset_password/:password_reset_token" => "reset_passwords#update", as: "reset_user_password"
# websites
resources :websites
# root
root to: "websites#new"
end
# request password reset paths
get "/reset_password" => "reset_passwords#new", as: "reset_password_request"
post "/reset_password" => "reset_passwords#create", as: "reset_password_request"
# login paths
get "/login" => "sessions#new", as: "login"
post "/login" => "sessions#create", as: "login"
# logout paths
get "/logout" => "sessions#destroy", as: "logout"
delete "/logout" => "sessions#destroy", as: "logout"
end
And then in lib/routes:
app_domain_routes.rb
class AppDomainRoutes
def matches?(request)
request.subdomain.blank? || request.subdomain == "www"
end
end
account_domain_routes.rb
class AccountDomainRoutes
def matches?(request)
request.subdomain.present? && request.subdomain != "www"
end
end
Now, /signup is only accessible from the main application domain www.mydomain.com or mydomain.com and /websites/new is only accessible from *.mydomain.com. But /login is still accessible in both situations, for convenience sake.
Obviously this doesn't solve the issue of visiting invalid.mydomain.com when invalid in fact is not an account in the database.
For this you go back to the application_controller.rb and handle redirection there, like this:
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :redirect_unknown_account
private
# returns current subdomain (account.subdomain) or nil
def account_subdomain
#account_subdomain ||= request.subdomain if request.subdomain.present? && request.subdomain != "www"
end
def current_account
#current_account ||= Account.find_by_username(account_subdomain) if account_subdomain
end
def redirect_unknown_account
if account_subdomain && ! current_account
redirect_to signup_url(host: app_domain), alert: "This account does not exist."
end
end
def account_domain
#account_domain ||= "#{current_account.username}.#{app_domain}" if current_account
end
def app_domain
#app_domain ||= "mydomain.com"
end
end

Resources