简体   繁体   English

分解具有相似模式的多条路线(路线4)

[英]Factor multiple routes that have similar patterns (Rails 4)

How could I factor this code. 我该如何考虑此代码。 i'm a Rails newbie and know it should be possible to DRY this and factor it: 我是Rails的新手,知道应该可以对此进行干燥并进行分解:

MyApp::Application.routes.draw do 

match "/france",          to: 'static_pages#set_france_in_session_and_redirect',          via: 'get'
match "/germany",         to: 'static_pages#set_germany_in_session_and_redirect',         via: 'get'
match "/unitedstates",    to: 'static_pages#set_us_in_session_and_redirect', path: 'us',  via: 'get'
match "/andsoon.....",    to: 'static_pages#set_us_in_session_and_redirect', path: 'us',  via: 'get'

end

As i will use it for about 20 countries couldn't I factor this , in order , not to have 20 lines of code? 因为我将在大约20个国家/地区使用它,所以不能将其分解为20条代码?

EDIT 编辑

##################################### ####################################

Following all the insightful answers/suggestions (thanks!), I think I have not provided enough context and info on my objectives. 在所有有见地的答案/建议(谢谢!)之后,我认为我没有提供足够的背景信息和目标信息。 So I'll give here more insights as answers do not answer what I'd like to do due to lack of relevant info on my part. 因此,我将在此处提供更多见解,因为由于缺乏相关信息,答案无法回答我想做的事情。

Here's the deal: I'm trying to build a daily deal Rails app. 这是交易:我正在尝试构建每日交易Rails应用。

I have a homepage called http://myapp.com 我有一个名为http://myapp.com的主页

Thanks to IP detection (geocoder gem), when a French user loads the homepage, he arrives on http://myapp.com and I only display content for French people (deals for French residents). 感谢IP检测(地理编码器宝石),当法国用户加载首页时,他到达了http://myapp.com,而我仅显示法国人的内容(法国居民的交易)。

Now, the user has the ability to go to a page called http://myapp.com/global and chooses another country if he wishes: see below 现在,用户可以转到名为http://myapp.com/global的页面,并根据需要选择其他国家/地区:请参见下文

在此处输入图片说明

If he clicks on "Germany", this does basically 2 things: 如果他点击“德国”,这基本上会做两件事:

  1. set in session[:country]= Germany 设置为会话[:国家/地区] =德国
  2. then redirects him to the homepage myapp.com (but with 'germany' now stored in the session so I can only display to him 'deals for German residents') 然后将他重定向到myapp.com主页(但会话中现在存储了“德国”,因此我只能向他显示“德国居民的交易”)

I have one BIG constraint that I know is not very Rails-way but definitely want to keep it like that : I want the URL visitors see in the browser to always be http://myapp.com and NOT http://myapp.com/france or http://myapp.com/germany , and so on... 我有一个BIG约束 ,我知道它不是Rails-way,但绝对希望保持这样: 我希望访问者在浏览器中看到的URL始终为http://myapp.com,而不是http:// myapp。 com / francehttp://myapp.com/germany ,依此类推...

So that's why I could not use params as one person suggested session[:counrty] = params[:country] 这就是为什么我不能将params用作一个人建议的session [:counrty] = params [:country]

Indeed, using params[:country] would result in the creation of URLs like http://myapp.com/country=germany or http://myapp.com/germany (maybe I'm too newbie but I could not make it work, and use params while having only ONE url of homepage that reads http://myapp.com ) 确实,使用params [:country]会导致创建类似http://myapp.com/country=germanyhttp://myapp.com/germany的URL(也许我太新手,但我做不到。工作,并使用params,而只有一个网址为http://myapp.com的网址

So the "trick" I found which is not Rails-way and I know it's not object oriented is the following: 因此,我发现的不是Rails-way的“技巧”,并且我知道它不是面向对象的:

The page http://myapp.com/global 页面http://myapp.com/global

<p>
<%= link_to "MyApp France", france_path, 
            confirm: "Are you sure you want to switch to MyApp France?" %><br/>
<%= link_to "MyApp  Germany", germany_path,
            confirm: "Are you sure you want to switch to MyApp Germany? " %><br/>
<%=  link_to "MyApp  US", unitedstates_path,
            confirm: "Are you sure you want to switch to MyApp US? " %>  
</p>

Then once they clicked on this link (for example on the german one), the visitor is sent to germany_path for which I created a route: 然后,一旦他们单击此链接(例如,德语链接),就将访问者发送到我为其创建路线的germany_path:

  match "/france",          to: 'static_pages#set_france_in_session_and_redirect',          via: 'get'
  match "/germany",         to: 'static_pages#set_germany_in_session_and_redirect',         via: 'get'
  match "/unitedstates",    to: 'static_pages#set_us_in_session_and_redirect', path: 'us',  via: 'get'

And static_pages#set_germany_in_session_and_redirect points to /app/controllers/static_pages_controller.rb: 并且static_pages#set_germany_in_session_and_redirect指向/app/controllers/static_pages_controller.rb:

# Enable not logged-in user to choose country version in the page/global)
  def set_france_in_session_and_redirect
    session[:country] = "France"
    redirect_to_root
  end


  def set_germany_in_session_and_redirect
    session[:country] = "Germany"
    redirect_to_root
  end

  def set_us_in_session_and_redirect
    session[:country] = "United States"
    redirect_to_root
  end

Clearly it's not Rails-way and I want to improve that, learning from you guys but I don't know how to do it. 显然,这不是Rails-way,我想改善这一点,向你们学习,但我不知道该怎么做。

Can you help me do this but in a better Rails-way, clean and proper ? 您可以帮助我做到这一点,但是要使Rails-way更好,更清洁,更合适吗?

Seems like you made 20 different actions for setting one session variable only. 似乎您仅设置一个会话变量就采取了20种不同的操作。 So combine all action and make one action and send country info/name in parameters and there set in session and redirect it appropriately. 因此,组合所有操作并执行一个操作,然后在参数中发送国家/地区信息/名称,然后在会话中进行设置并适当地重定向它。

def set_countries_session
  session[:counrty] = params[:country]
  redirect 'your path'
end

If you still want to go with your approach of 20 actions and then you can refactor your routes code by using an array of countries 如果您仍然希望采用20个动作的方法,那么可以通过使用多个国家/地区来重构路线代码

['germany', 'france', 'so on'].each do |country|
  match "/#{country}", to: "static_pages#set_#{country}_in_session_and_redirect",  via: 'get'
end

Routes 路线

Rails' routing structure is built around resources , which is built on the object-orientated nature of Ruby (the language which Rails is built on) Rails的路由结构是围绕resources构建的, resources是基于Ruby(Rails所基于的语言) 的面向对象的本质而构建的

Simply, your routes should reflect the objects you wish to populate, NOT the "functionality" you wish to achieve. 简而言之,您的路线应反映您希望填充的对象 ,而不是您希望实现的“功能”。 It's a bit of a mind-bender to begin with, but once you realize how it works, it becomes a lot simpler: 首先,它有点笨拙,但是一旦您意识到它是如何工作的,它将变得更加简单:

#config/routes.rb
resources :static_pages, only: :show, path: "", as: :country #-> domain.com/:id

This is the "conventional" way that Rails will provide a path for you. 这是Rails为您提供路径的“常规”方式。 Whilst admittedly, it won't give you the [country]_path helper, it will keep your code super clean (as demonstrated below) 诚然,它不会为您提供[country]_path帮助器,它将使您的代码保持超级干净(如下所示)


Controller 控制者

Your problem is with your controller , which you need to resolve before your routes will fix. 您的问题出在控制器上 ,您需要先解决该问题,然后才能修复路由。

The real issue is that you're using 20 different controller actions. 真正的问题是您正在使用20种不同的控制器动作。 Is that object orientated ? 那是面向对象的吗? Nope. 不。

I'd do this: 我会这样做:

#app/controllers/static_pages_controller.rb
Class StaticPagesController < ApplicationController
   def show
       country = params[:id]
       ... business logic
   end
end

This will give you the ability to use the country variable as much as you need in the single show action. 这将使您能够在单个show操作中根据需要使用country变量。 This is object orientated, as the show action will show your static_page 面向对象的,因为show动作将显示您的static_page


Slug ug

To give you the "sluggable" URL ability, you'll be best using the friendly_id gem : 为了给您“可伸缩的” URL功能,最好使用friendly_id gem

#app/models/your_model.rb
Class Model < ActiveRecord::Base
   friendly_id :column, use: [:slugged, :finders]
end

This gives you the ability to use the country object as a slug and not an id : 这使您能够将country对象用作slug而不是id

#view
<%= link_to "France", country_path("france") %>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM