如何通过密钥访问哈希

时间:2017-01-13 14:39:43

标签: ruby-on-rails ruby

我正在尝试构建一个Rails助手,它将创建一个嵌套的下拉菜单,其中包含最顶层的链接,#34; All"或者当前参数和下拉列表包含除当前参数之外的其他选项。

例如,如果我没有post_type参数,我会看到:

<ul>
    <li><a href="">All</a>
        <ul>
            <li><a href="">Discussions</a></li>
            <li><a href="">Snaps</a></li>
            <li><a href="">Code</a></li>
            <li><a href="">Links</a></li>
        </ul>
    </li>
</ul>

但如果我有一个post_type参与讨论&#39;然后我会看到:

<ul>
    <li><a href="">Discussions</a>
        <ul>
            <li><a href="">All</a></li>
            <li><a href="">Snaps</a></li>
            <li><a href="">Code</a></li>
            <li><a href="">Links</a></li>
        </ul>
    </li>
</ul>

在我看来,我有:

<ul class="filter-menu">
  <li>
    <%= current_post_type(params) %>
    <ul class="filter-menu__drop-down">
      <%= list_post_types(params) %>
    </ul>
  </li>
</ul>

在我的助手中我有:

module PostsHelper

  def post_types
    @post_types = {
        :all => {
            :text => 'All post types',
            :icon => 'icon-file-text2',
            :post_type => nil}
    }, {
        :discussions => {
            :text => 'Discussions',
            :icon => 'icon-bubbles2',
            :post_type => 'discussions'}
    }, {
        :snaps => {
            :text => 'Snaps',
            :icon => 'icon-images',
            :post_type => 'snaps'}
    }, {
        :code => {
            :text => 'Code',
            :icon => 'icon-embed2',
            :post_type => 'code'}
    }, {
        :links => {
            :text => 'Links',
            :icon => 'icon-link',
            :post_type => 'links'}
    }
  end

  def post_type_text(icon, text, drop_down = false)
    raw('<i class="' + icon + '"></i> ' + text + (drop_down ? ' <span class="chevron">&#9662;</span>' : ''))
  end

  def post_type_path(post_type)
    posts_path(:filter => params[:filter], :time => params[:time], :post_type => post_type)
  end

  def current_post_type(params)
    if params[:post_type].present? # todo: check matches above
      post_type = params[:post_type].downcase
      link_to post_type_text(post_types[post_type][:icon], post_types[post_type][:text], true), post_type_path(post_types[post_type][:post_type])
    else
      link_to post_type_text(post_types[:all][:icon], post_types[:all][:text], true), post_type_path(post_types[:all][:post_type])
    end
  end

  def list_post_types(params)
    post_types.each do |post_type| # todo: exclude current post_type
      link_to post_type_text(post_types[post_type][:icon], post_types[post_type][:text]), post_type_path(post_types[post_type][:post_type])
    end
  end

end

我如何访问哈希?我收到错误

no implicit conversion of Symbol into Integer

执行post_types[:all]

我认为这是因为post_types正在返回一个散列数组,其中我想要的是一个可通过键名访问的散列哈希。

我可以通过:all访问post_types[0][:all][:icon],但这对我的其他哈希不起作用,因为我想通过post_types[post_type][:icon]访问post_type我试图访问的post_type密钥的名称。

2 个答案:

答案 0 :(得分:1)

首先,声明一个哈希而不是一个数组:

@post_types ||= {
        :all => {
            :text => 'All post types',
            :icon => 'icon-file-text2',
            :post_type => nil},
        :discussions => {
            :text => 'Discussions',
            :icon => 'icon-bubbles2',
            :post_type => 'discussions'},
        :snaps => {
            :text => 'Snaps',
            :icon => 'icon-images',
            :post_type => 'snaps'},
        :code => {
            :text => 'Code',
            :icon => 'icon-embed2',
            :post_type => 'code'},
        :links => {
            :text => 'Links',
            :icon => 'icon-link',
            :post_type => 'links'}
    }

问题在于:

post_types.each do |post_type| # todo: exclude current post_type
  link_to post_type_text(post_types[post_type] ...

您已在迭代哈希,post_type此处是一个数组,同时包含keyvalue

使用:

post_types.each do |k, v| # todo: exclude current post_type
  link_to post_type_text(v[:icon] ...

要了解发生了什么:

post_types.each do |post_type| # todo: exclude current post_type
  puts post_type.inspect

另外,旁注:仅实例化实例变量一次:

def post_types
  #           ⇓⇓⇓ HERE
  @post_types ||= {...}

答案 1 :(得分:0)

这就是我最终解决了我的问题。

非常感谢 mudasobwa 我接受了他的答案,但我想分享最终代码对于遇到此问题的人的看法。

module PostsHelper

  def post_types
    @post_types ||= {
        :all => {
            :text => 'All post types',
            :icon => 'icon-file-text2',
            :post_type => nil},
        :discussions => {
            :text => 'Discussions',
            :icon => 'icon-bubbles2',
            :post_type => 'discussions'},
        :snaps => {
            :text => 'Snaps',
            :icon => 'icon-images',
            :post_type => 'snaps'},
        :code => {
            :text => 'Code',
            :icon => 'icon-embed2',
            :post_type => 'code'},
        :links => {
            :text => 'Links',
            :icon => 'icon-link',
            :post_type => 'links'}
    }
  end

  def post_type_text(icon, text, drop_down = false)
    raw('<i class="' + icon + '"></i> ' + text + (drop_down ? ' <span class="chevron">&#9662;</span>' : ''))
  end

  def post_type_path(post_type)
    posts_path(:filter => params[:filter], :time => params[:time], :post_type => post_type)
  end

  def current_post_type(params)
    post_type = params[:post_type].present? ? params[:post_type].downcase.to_sym : :all
    if post_types.key?(post_type)
      link_to post_type_text(post_types[post_type][:icon], post_types[post_type][:text], true), post_type_path(post_types[post_type][:post_type])
    else
      link_to post_type_text(post_types[:all][:icon], post_types[:all][:text], true), post_type_path(post_types[:all][:post_type])
    end
  end

  def list_post_types(params)
    html = ''
    post_type = params[:post_type].present? ? params[:post_type].downcase.to_sym : :all
    exclude_all = post_types.key?(post_type) ? false : true
    post_types.each do |k, v|
      if exclude_all && k == :all
      else
        html += "<li>#{link_to post_type_text(v[:icon], v[:text]), post_type_path(v[:post_type])}</li>" if k != post_type
      end
    end
    html.html_safe
  end

end