开发者

Rails 3: Hash accessor in the model?

开发者 https://www.devze.com 2023-01-28 02:00 出处:网络
I\'m struggling to stretch my understanding of some basic Rails concepts beyond the tutorial examples I\'ve done.I can\'t find any Q&A/docs/walkthroughs doing what I\'m trying to do, so there\'s a

I'm struggling to stretch my understanding of some basic Rails concepts beyond the tutorial examples I've done. I can't find any Q&A/docs/walkthroughs doing what I'm trying to do, so there's a good chance I'm going about this the wrong way.

I have a Team object with many Tags. The Team table has a few normalized fields, but most of the characteristics of the team are stored as Tags, i.e the Team 'Virginia Cavaliers' has Tags

{[tag_name => 'Conference', tag_value => 'ACC'],
[tag_name => 'Division', tag_value =>'I']}

etc. The db design was meant to accommodate many types of teams in the same table, with the tag table facilitating search for teams by arbitrary criteria.

So far so good. What I can't figure out is how to best access the team attributes given the team.

cla开发者_如何学运维ss Team < ActiveRecord::Base
  belongs_to :sport
  has_many :team_subscriptions
  has_many :users, :through => :team_subscriptions
  has_many :tags
  def tagvalue
    #Set up a hash to retrieve tag value by name?
    @tagvalue = {}
    tags.each do |t|
      @tagvalue[t.tag_name] = t.tag_value
    end
    Rails.logger.info(@tagvalues.keys)
  end
end    

The hash is there but I can't access it in a view the way I'd like.

<%= @team.tagvalue["Conference"] %>

Is this sensible? possible? Thanks for your responses.

* Edited based on feedback (This site is awesome)*

The second suggestion is slick syntacticly, but has two hang ups I can see. I have to catch nulls as not all teams have all tags and sometimes they show up in the same list:

My clumsy implementation:

has_many :tags do 
  def [](key)
    set = where(:tag_name => key)
    if set.length > 0
      set.first[:tag_value]
    end
    nil
  end
end

The clean code thanks to edgerunner:

has_many :tags do 
  def [](key)
    where(:tag_name => key).first.try(:tag_value)
  end
end

And if I'm not wrong this method makes extra database calls every time I access a tag. The first method needs just one when the object is instantiated. Did I get both of those right?


There may be a different way to do the same. You can define an anonymous association extension and define the array accessor method for that to retrieve the tags with keys.

class Team < ActiveRecord::Base
  ...
  has_many :tags do 
    def [](key)
      where(:tag_name => key).first.try(:tag_value)
    end
  end
  ...
end

This will let you fetch only the required tags from the database instead of getting them all at once just to use one of them. It lets you do this:

<%= @team.tags["Conference"] %>
0

精彩评论

暂无评论...
验证码 换一张
取 消