【问题标题】:Accessing hashes with slash separated keys使用斜线分隔的键访问哈希
【发布时间】:2018-04-09 05:31:11
【问题描述】:

假设我的一个名为 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

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

【问题讨论】:

    标签: ruby-on-rails json ruby hash


    【解决方案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 放在哈希的末尾。

    【讨论】:

    • 哦,谢谢
    • 另外,你能告诉我如何抽象那个位吗?我真的很感激它
    • 当然,我会将其添加到我的答案中。其他一点对你有用吗?
    • 我目前正在实现它,但我相信它会起作用!
    • 完美答案!正是我想要的!!非常感谢
    【解决方案2】:

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

    get 'field_names' => 'controller#action'
    

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

    /field_names?company=TEAM&attribute=founders
    

    然后,这些属性将在您的控制器中可用

    params[:company]
    params[:attribute]
    

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

    【讨论】:

    • 如果我也想要 person_info 对象怎么办?这就是创始人 obj 里面的内容
    • 然后添加人员信息的 ID。然后你可以做 PersonInfo.find(params[:person_info_id], /field_names?person_info_id=14
    • personinfo 实际上不是模型。它是嵌套对象之一
    猜你喜欢
    • 2011-03-12
    • 2013-03-22
    • 1970-01-01
    • 2016-01-20
    • 2014-05-06
    • 2011-10-31
    • 1970-01-01
    • 2011-12-29
    相关资源
    最近更新 更多