When to use a virtual attribute or pass data in a hash in Rails 3
Asked Answered
T

3

5

In my application, I have a Widget model, a Feature model with a has_many through association by WidgetFeature table.

As per the requirements, when I am sending a WidgetFeature object, I should append the feature_name to it as well, for the given feature associated.
There are two ways of going at it:

  1. While sending the object, do this:
widget_feature_object[:feature_name] = feature_name_value

and then I can access it in my controller or view, by widget_feature_object[:feature_name] because an object has (key, value) pairs, so I can add another too.

2 . Make feature_name a Virtual Attribute in WidgetFeature model, and then create getter and setter methods for it.

From what I know, that you should use virtual attributes when you want to create a different view different from the fields actually present in the model (e.g Full name = First name + Last name).
Does the same thing fits in here too?

Also, does Rails do some caching on objects, that might get in useful when you use virtual attributes and not when I use the first approach?

What are the pros and cons of each approach and which one suits the best as per my requirements? Thanks a lot.

Twombly answered 24/6, 2011 at 14:51 Comment(0)
I
6

I would propose an alternative approach: use delegate (documentation).

In the WidgetFeature I would write:

class WidgetFeature

  belongs_to :feature

  delegate :name, :to => :feature, :prefix => true
end

then you will be able to write

f = WidgetFeature.first

f.feature_name #will return f.feature.name

Hope this helps.

Infuse answered 5/7, 2011 at 8:38 Comment(0)
N
2

Use attr_accessor when you want to be able to set a method. Otherwise just use general functions.

If you want to cache, look into memoization

Ninepins answered 3/7, 2011 at 18:44 Comment(1)
I know what attr_accessor does, and memoization is of no use here, if you look closely at the question asked.Twombly
K
0

I'm not sure why you insist on using the [] notation to access your attributes, but one path to follow is this one:

def [](attr)
  if attr == :feature
    feature    # Return the associated feature object
  else
    super      # Call ActiveRecord::Base#[]
  end
end

Of course you could nice it up with some metaprogramming to automatically detect valid associations.

I personally don't really like monkeypatching in this fashion, but since [] is a simple method you're probably safe. The upside is that this allows you to widget_feature[:feature][:name] and even widget_feature[:feature][:name]=

You get all the ActiveRecord functionality that you would with calling widget_feature.feature.

Kleinstein answered 29/6, 2011 at 12:35 Comment(1)
@Martjin: I understand what you are saying. But the question is about a choice between choosing virtual attributes or simply passing the necessary data in a hash. It's only about the data sending, which is the main concern, if caching does something extra with virtual attributes. Could you answer the problems in a better way nowVillain

© 2022 - 2024 — McMap. All rights reserved.