Ruby on rails - access model data within another model

TripleAMAC picture TripleAMAC · Aug 5, 2014 · Viewed 14.5k times · Source

I want to access a column from OtherModel.rb to MyModel.rb. Is that possible?

this is what it looks like if the data that I want to access is located within the model it self. and this works just fine

//MyModel.rb

def to_param
  self.name
end

but I don't know how to access data from other model. Here is an example of what I want:

//MyModel.rb

def to_param
  OtherModel.name
end

Answer

Richard Peck picture Richard Peck · Aug 5, 2014

Model-ception!!


Objects

The best way to describe the issue you have is to outline that Ruby (& Rails by virtue of being built on top of the Ruby language) is object-orientated.

Contrary to popular belief, object-oriented is more than just a buzzword - it means that every element of your application should be constructed around objects. Objects are essentially "variables" which have a collection of attributes & other data attached to them:

enter image description here

In Rails, an object is created as an instance of a model (class)


Fix

When you're calling OtherModel.name, you're not initializing an instance of the relevant class, hence meaning you will not be able to display any of the attributes it has

To ensure this issue can be remedied, you need to ensure you load an instance of your OtherModel object, to ensure you're able to call the relevant data:

#app/models/my_model.rb
Class MyModel < ActiveRecord::Base
   def to_param
      return OtherModel.first.name #-> returns first instance of `OtherModel` & then displays "name"
   end
end

Associations

A better option is to harness ActiveRecord Associations:

#app/models/my_model.rb
Class MyModel < ActiveRecord::Base
   has_many :other_models
end

#app/models/other_model.rb
Class OtherModel < ActiveRecord::Base
   belongs_to :my_model
end

This means you'll be able to call the following:

@my_model = MyModel.find 1
@my_model.other_models.each do |other|
   puts other.name
end

See how the ActiveRecord associations creates an instance of the associated model? This allows you to call it from the instance of your "parent" model without having to re-initialize it

--

Delegate

You may also be able to use the delegate method depending on your association setup:

#app/models/my_model.rb
Class MyModel < ActiveRecord::Base
    belongs_to :other_model
    delegate :name, to: :other_model, prefix: true
end

#app/models/other_model.rb
Class OtherModel < ActiveRecord::Base
    has_many :my_models
end

This will allow you to call:

@my_model = MyModel.find 1
@my_model.other_model_name

It must be noted the delegate method only works with belongs_to relationships