Rails 3: Hash accessor in the model?

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.

class 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?

Answers


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"] %>

Need Your Help

Is it possible to return mutiple values with @depends?

phpunit

The @depends annotation allows to express dependencies between tests:

Display JSON Data in HTML using Laravel 4

php ajax json laravel-4

Please help me with my problem in displaying JSON data into my view..

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.