【问题标题】:URL Permalinks for pages AND users (similar to facebook) for Rails4. Friendly_id?Rails4 的页面和用户的 URL 永久链接(类似于 facebook)。友好ID?
【发布时间】:2014-12-11 01:02:22
【问题描述】:

也许我误解了 Friendly_id gem 的功能,但我也没有找到任何其他方法来实现这一目标:

我有一个应用程序,用户可以在其中获取他们自己的页面 URL,类似于 facebook 所做的(例如http://www.notfacebook.com/mypermalink)。我已经具备这种能力。也类似于 facebook,我想让页面有自己的 URL(例如http://www.notfacebook.com/pagepermalink)。

我添加了 friendly_id gem,认为它能够检查 User.permalink 和 Page.permalink 之间的唯一性 - 跨两个不同表/模型中的列的唯一性。相反,我得到了一个类似于 http://www.notfacebook.com/pages/pagepermalink 的页面 URL 模式。

我不能用

resources :pages, path: ''

也没有

get '/:friendly_id', to: 'pages#show'

在 routes.rb 中,因为这不适用于我现有的用户永久链接路由。

有没有办法在我的应用中获取唯一页面用户永久链接?

我正在考虑使用自定义子域而不是永久链接,但我使用的是 heroku,根据我的阅读,即使我有自己的域名,我也不能在 heroku 上使用子域。那是对的吗? (是的,这是一个单独的问题。)

【问题讨论】:

标签: ruby-on-rails permalinks unique-constraint friendly-id wildcard-subdomain


【解决方案1】:

我不熟悉 friendly_id,但在浏览文档后似乎可以使用这种方法。

你只需要一个wildcard route:

config/routes.rb结尾:

get "*friendly_id" => "pages#show"

我在拉起页面时在wiki app 中执行此操作。您会注意到我必须将该路由放在文件的底部,以便最后对其进行评估。

【讨论】:

  • 这不起作用,因为我首先在 routes.rb 中匹配了 '/:permalink' => "users#show", :as => :user_profile, via: 'get'。此外,没有办法确保 User.permalink 和 Page.permalink 是唯一的。
【解决方案2】:

使用路由约束可以很好地解决这个问题。

使用路由约束

正如rails routing guide 所建议的那样,您可以定义路由约束以检查路径是否属于用户或页面。

# config/routes.rb
# ...
get ':permalink', to: 'users#show', constraints: lambda { |request| User.where(permalink: request[:permalink]).any? }
get ':permalink', to: 'pages#show', constraints: lambda { |request| Page.where(permalink: request[:permalink]).any? }

顺序定义了优先级。在上面的示例中,如果语言和类别具有相同的名称,则该语言将胜出,因为它的路径定义在类别路径之上。

上述解决方案要求模型具有定义 url 友好名称的 permalink 列。但是如果你已经有一个对 url 友好的属性,例如User#alias,你也可以用这个:

# config/routes.rb
# ...
get ':alias', to: 'users#show', constraints: lambda { |request| User.where(alias: request[:alias]).any? }
get ':permalink', to: 'pages#show', constraints: lambda { |request| Page.where(permalink: request[:permalink]).any? }

使用永久链接模型

如果您想确保所有路径都是唯一的,一种简单的方法是定义 Permalink 模型并在那里使用验证。

生成数据库表:rails generate model Permalink path:string reference_type:string reference_id:integer && rails db:migrate

并在模型中定义验证:

class Permalink < ApplicationRecord
  belongs_to :reference, polymorphic: true
  validates :path, presence: true, uniqueness: true

end

并将其与其他对象类型相关联:

class Page < ApplicationRecord
  has_many :permalinks, as: :reference, dependent: :destroy

end

这还允许您为记录定义多个永久链接路径。

page_about_rails.permalinks.create path: 'rails'
page_about_rails.permalinks.create path: 'ruby-on-rails'

使用此解决方案,路由文件必须如下所示:

# config/routes.rb
# ...
get ':permalink', to: 'users#show', constraints: lambda { |request| Permalink.where(reference_type: 'User', path: request[:permalink]).any? }
get ':permalink', to: 'pages#show', constraints: lambda { |request| Permalink.where(reference_type: 'Page', path: request[:permalink]).any? }

并且,作为在控制器中使用 can gem 和 load_and_authorize_resource 的其他用户的旁注:在调用 load_and_authorize_resource 之前,您必须通过永久链接加载记录:

class Page < ApplicationRecord
  before_action :find_resource_by_permalink, only: :show
  load_and_authorize_resource

  private

  def find_resource_by_permalink
    @page ||= Permalink.find_by(path: params[:permalink]).try(:reference)
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 2011-05-02
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多