使用斜杠分隔键访问哈希

时间:2017-10-27 14:55:07

标签: ruby-on-rails json ruby hash

假设我的一个名为Company的模型中有以下哈希值。

FIELDS = {
    TEAM: {
        'num_founders': 'Number of Founders',
        'num_employees': 'Number of Employees',
        'founders': {
            'person_info': {
                'full_name': 'Full Name',
                'first_name': 'First Name',
                'last_name': 'Last Name',
                'location': 'Location',
                'gender': 'Gender',
                'biography': 'Biography',
                'num_articles': 'Number of Articles'
            }
        }
    }
}

我在我的应用程序控制器中有一个动作,它将此哈希呈现为json:

def field_names
    module_name = params[:module]
    category = params[:category]

    case module_name
    when 'company'
      render json: Company::FIELDS[category.to_sym].to_json
    end
end

所以现在如果我打开localhost:3000/field_names/company/TEAM,我就会得到json。但我现在面临的问题是我需要得到这个哈希的子哈希。就像我想要/field_names/company/TEAM/founders/person_info并获得相应的对象一样。

首先,我用斜杠拆分网址以获取密钥。我无法弄清楚如何使用这些字符串来访问哈希值。

如果我定义路线,如get '/field_names/:query', to: 'application#field_names

如果我点击localhost:3000/field_names/company/TEAM/founders 该操作应该呈现Company::FIELDS[:TEAM]["founders"]对象,这将是

'person_info': {
    'full_name': 'Full Name',
    'first_name': 'First Name',
    'last_name': 'Last Name',
    'location': 'Location',
    'gender': 'Gender',
    'biography': 'Biography',
    'num_articles': 'Number of Articles'
}

为此,我的行动应该是这样的:

def field_names
    query = params[:query]
    keys = query.split("/")
    #keys.first::FIELDS[key2][key3]... .to_json
end

我如何实现这一目标?谢谢:))

2 个答案:

答案 0 :(得分:1)

这是您项目中的路由问题。实际上,您应该有一条路径来检索这些字段名,例如:

get 'field_names' => 'controller#action'

然后,您可以在您的网址上传递任何参数。 例如

/field_names?company=TEAM&attribute=founders

然后,这些属性将在您的控制器中显示为

params[:company]
params[:attribute]

所以你只能渲染你想要的属性

答案 1 :(得分:1)

这样的事情怎么样:

fields = {
  TEAM: {
    'num_founders': 'Number of Founders',
    'num_employees': 'Number of Employees',
    'founders': {
      'person_info': {
        'full_name': 'Full Name',
        'first_name': 'First Name',
        'last_name': 'Last Name',
        'location': 'Location',
        'gender': 'Gender',
        'biography': 'Biography',
        'num_articles': 'Number of Articles'
      }
    }
  }
}.with_indifferent_access


'TEAM/founders'.split('/').each do |key|
  fields = fields[key]
end

puts fields

=> {"person_info"=>{"full_name"=>"Full Name", "first_name"=>"First Name", "last_name"=>"Last Name", "location"=>"Location", "gender"=>"Gender", "biography"=>"Biography", "num_articles"=>"Number of Articles"}}

仅用于控制台,我将FIELDS更改为fields(SHOUTING_CASE通常保留用于常量,fwiw)。而且,我使用with_indifferent_access因为您的嵌套哈希值使用stringssymbols作为键。

如果你想要person_info,那么:

fields = {
  TEAM: {
    'num_founders': 'Number of Founders',
    'num_employees': 'Number of Employees',
    'founders': {
      'person_info': {
        'full_name': 'Full Name',
        'first_name': 'First Name',
        'last_name': 'Last Name',
        'location': 'Location',
        'gender': 'Gender',
        'biography': 'Biography',
        'num_articles': 'Number of Articles'
      }
    }
  }
}.with_indifferent_access

'TEAM/founders/person_info'.split('/').each do |key|
  fields = fields[key]
end

puts fields    

=> {"full_name"=>"Full Name", "first_name"=>"First Name", "last_name"=>"Last Name", "location"=>"Location", "gender"=>"Gender", "biography"=>"Biography", "num_articles"=>"Number of Articles"}

如果网址格式错误,您可能需要在其中添加一些try

此外,您可以在任何地方抽象和简化该位:

case module_name
when 'company'
  render json: Company::FIELDS[category.to_sym].to_json
end

假设你有(routes.rb):

get '/field_names/:query'

你点击了:

localhost:3000/field_names/company/TEAM/founders

那么你的参数应包括:

{query: 'company/TEAM/founders'}

在这种情况下,您可以执行以下操作:

def field_names
  query_split = params[:query].split

  module_name = query_split.shift.camelize
  fields = "#{module_name}::FIELDS".constantize.clone.with_indifferent_access
  query_split.each{|key| fields = fields[key]}
  render json: fields

end

您不必将to_json放在哈希的末尾,顺便说一句。