Tintin81
Tintin81

Reputation: 10215

How to get a string into a where clause in Ruby on Rails 3?

I have this class method:

def self.default_column
  "created_at"
end

How can I rewrite the following function, so that I can make use of my default_column method?

def next
  User.where("created_at > ?", created_at).order('created_at ASC').first
end

I tried things like these...

def next
  User.where("#{default_column} > ?", default_column).order('#{default_column} ASC').first
end

... but I must be awfully wrong here because it doesn't work at all.

Thanks for any help.

Upvotes: 0

Views: 162

Answers (2)

Francesco Belladonna
Francesco Belladonna

Reputation: 11709

You can use:

def next
  User.where("#{User.default_column} > ?", self.send(User.default_column)).order("#{User.default_column} ASC").first
end

Or even better

def next
  klass = self.class # This is supposing you are inside User model
  # Otherwise just use klass = User
  klass.where("#{klass.default_column} > ?", self.send(klass.default_column))
       .order(klass.arel_table[klass.default_column].asc)
end

Notice that if you handle the method in this way, you cannot chain it: like User.where(name: 'something').next

If you want to achieve this, you have to move next to be def self.next and in that case, you have to pass an instance of the user to it, like this:

def self.next(user)
  klass = user.class
  klass.where("#{klass.default_column} > ?", user.send(klass.default_column))
       .order(klass.arel_table[klass.default_column].asc)
end

In this way you can write something like: User.where(name: 'test').next(@user). You can optionally chain .first to get directly the result, but in this way you will not be able to chain other things, like User.where(name: 'test').next(@user).where(email: '[email protected]')

Finally, if you want pure AREL (for portability)

def self.next(user)
  klass        = user.class
  arel         = klass.arel_table
  column       = klass.default_column # This helps cleaning up code
  column_value = user.send(column)

  klass.where(arel[column].gt(column_value))
       .order(arel[column].asc)
end

Upvotes: 4

sawa
sawa

Reputation: 168229

def next
  default_column = self.class.default_column
  User
  .where("#{default_column} > ?", send(default_column))
  .order("#{default_column} ASC")
  .first
end

Upvotes: 2

Related Questions