如何修改(编码和解码)路由id,但不更改模型或控制器?

时间:2015-05-29 14:23:23

标签: ruby-on-rails

我想公开我的数据库ID并使用routes helper对id进行编码/解码。对于编码,我使用Hashids gem。

现在我有:

的routes.rb

get 'companies/:id/:year', to: 'company#show', as: 'companies'

公司网址:

/companies/1/2015

对于id编码,我有编码/解码辅助方法:

def encode(id)
   # encode...
   return 'ABC123'
end

def decode(hashid)
   # decode...
   return 1
end

我如何实现,id将与路由助手转换? 所以必须显示URL:

/companies/ABC123/2015

并且控制器必须自动获取id为1的参数。

5 个答案:

答案 0 :(得分:2)

感谢您的回答!但我不会在没有模型或控制器变化的情况下解码params id。经过长时间的考虑,我已经决定在控制器获得params之前操纵params id。我在路线约束中操纵参数。

示例助手:

encoding_helper.rb

module EncodingHelper
  def encode(id)
    # encode...
    return 'ABC123'
  end

  def decode(hashid)
    # decode...
    return 1
  end
end

使用编码ID:

创建路径
companies_path(id: encode(1), year: 2015) # => /companies/ABC123/2015

在路线中操纵参数约束:

LIB /约束/ decode_company_id.rb

module Constraints
  class DecodeId
    extend EncodingHelper

    def self.matches?(request)
      request.params['id'] = decode(request.params['id']).to_s if request.params['id'].present?
      true
    end
  end
end

配置/ routes.rb中

constraints(Constraints::DecodeId) do
  get 'companies/:id/:year', to: 'company#show', as: 'companies'
end

使用约束解码params id并且在控制器中没有操作时,params id为1。

答案 1 :(得分:1)

您可以使用to_param方法。

#in Company
def to_param
  self.encoded_id
end

def encoded_id
  self.class.encode_id(self.id)
end

def find_by_encoded_id(encoded_id)
  self.find_by_id(self.class.decode_id(encoded_id)
end

#class methods
class << self
  def encode_id(id)
    #encoding algorithm here
  end

  def decode_id(encoded_id)
    #decoding algorithm here
  end
end

这将意味着具有公司ID的网址实际上将使用encoded_id,假设您将公司对象传递给路径助手,例如company_path(@company)

然后,在您的公司控制器中,您只需要确保find_by_encoded_id(params[:id])而不是find_by_id(params[:id])

答案 2 :(得分:0)

Rails路由器不应该进行任何解码:

  

The Rails router recognizes URLs and dispatches them to a controller's action.

逻辑应该属于控制器。

答案 3 :(得分:0)

当您的控制器收到编码的响应时:

#Appropriate controller

def show
  Company.decode(params[:id])
end

如果您将模型方法稍微调整为:

,这项工作很有效
def self.decode(code)
  # decode => get id
  find(id) #returns Company object
end

答案 4 :(得分:0)

你可以试试这个。友好id的自定义方法

在模型中

  extend FriendlyId
  friendly_id :decode

  # Try building a slug based on the following fields in
  # increasing order of specificity.
  def decode
     conditional_check(self.id)
  end

  private

  def conditional_check(id)
     return "ABC123" if id == 1
  end