RubyNewbie
RubyNewbie

Reputation: 29

Building a Method In the Model

I have a Model Quote which persists to a database quotes with columns :quote, :author. My issue is in trying to create a custom display in my Controller.

I have built the follow method and tried many varations. I am trying to get a list of all the authors assigned to various quotes.

class Quote < ActiveRecord::Base
  has_paper_trail
  acts_as_taggable

  belongs_to :source

  scope :with_source_id, lambda { |id| where("source_id = ?", "#{id}") }

  def quote_authors
    authors = []
    Quote.all.each do |quote|
      authors << quote.author
    end
    authors.uniq!
  end

end

Ive tried various versions of self and such, however I can't seem to figure it out. I tried this too

def quote_authors(quote_list)
  authors = []
  quote_list.each do |quote|
    authors << quote.author
  end
  authors.uniq!
end

Upvotes: 1

Views: 70

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

Method

I think you'll benefit from looking into class methods vs instance methods - one of the main issues I can see is you're calling quote_authors as an instance method, which, although correct in definition, is not right in application

The problem you have is if you're calling instance methods - it has to be on an instance of an object:

@user = User.find params[:id] #-> creates instance of object
@user.instance_method #-> calls instance method with data of object

If you're using an instance method, it really has to manipulate the instantiated data in your object. Currently, you're not doing this; which would suggest you need to use a class method:

#app/models/quote.rb
Class Quote < ActiveRecord::Base
   def self.quote_authors
        Quote.all.each do |quote|
            #...
        end
   end
end

--

System

As bratsche has pointed out - if you are trying to load author names for your quotes, you'll be much more suited to using the ActiveRecord associations system inside Rails:

#app/models/quote.rb
Class Quote < ActiveRecord::Base
    belongs_to :author
    delegate :name, to: :author, prefix: true
end 

#app/models/author.rb
Class Author < ActiveRecord::Base
    has_many :quotes
end

This setup will allow you to call:

@quote = Quote.find params[:id]
@quote.author_name

Upvotes: 1

bratsche
bratsche

Reputation: 2674

It sounds like your column author is just a string column on your Quote model? If that's the case, I'd recommend changing things a little.

Create two models:

rails g model author name:string
rails g model quote text:string author:references

app/models/quote.rb:

class Quote < ActiveRecord::Base
  belongs_to :author
end

And app/models/author.rb:

class Author < ActiveRecord::Base
  has_many :quotes
  validates_uniqueness_of :name
end

Now you've got two models. Let's say you're creating a new quote, and you have the text and the name of the author:

quote_text = 'Rails is okayish'
author_name = 'bratsche'

author = Author.find_or_create_by_name(author_name)
author.quotes.create(text: quote_text)

And to get to your original question, how do you get a list of unique users?

Author.all

You're (mostly) guaranteed that these will be unique, and you don't need to resort to iterating through a list of all quotes, building a new list with names, and then calling #uniq! on them. This way you do it entirely in the database.

Upvotes: 1

Related Questions