2

I'm having a very difficult rails problem and i thought to ask for some help. The situation is like this :

I'm using restful authentication for my User model. Now, user has a field named 'gold' that is a numeric value. There is another model named Book that has been created using scaffolding.

What i want to do is simple, yet i cannot see a way of doing it. I want to add some validation where if the user's gold is not, let's say 100, they cannot create a new book entry(from the scaffolding standard view).

Now the problem is that i need current_user information in order to validate this from my model. I need that in order to get the user id and therefore get their gold amount as well. I cannot find a good way (if any) to do that.

Another thought was doing that from a controller. However, the standard "if @book.save" block does not really allow me to insert my own error messages (inside scaffold create) :

if not User.has_the_needed_gold(current_user, 100)
  flash[:goldError] = 'You do not have the needed gold to create this book.'
#end


respond_to do |format|
  if @book.save
    flash[:notice] = 'Book was successfully created.'
    format.html { redirect_to(@book) }
    format.xml  { render :xml => @book, :status => :created, :location => @book }
  else
    format.html { render :action => "new" }
    format.xml  { render :xml => @book.errors, :status => :unprocessable_entity }
  end
end

Now, i cannot output that message and abort the save of the new book as well. I've tried adding my own error to base, but it was cleared out(after save i guess). I'm quite confused with the situation and i've been searching around for a couple of hours with no results.

If anybody can help with that, please do so, you would spare me lots of trouble :)

Thanx for reading !

Spyros
  • 105
  • 1
  • 7
  • How are you defining your models. Does book belong to user and user has_many books? – thenengah Nov 21 '10 at 01:27
  • Actually, it should be the opposite in my case. A user has a book but a book can belong to many users. Though i've not actually added the definitions just yet. This questions rings a bell though. Accessing the information via the relationship, was too dumb to think of that :/ I'll take a look – Spyros Nov 21 '10 at 01:49

2 Answers2

3

You could define a :user_gold virtual attribute for Book, set it in the controller where you have access to current_user and then incorporate that into your Book validation.

Outside_Box
  • 447
  • 1
  • 4
  • 16
monocle
  • 5,866
  • 2
  • 26
  • 22
  • 1
    This doesn't sound like a good idea... you're coupling the model and controller layers a bit tight, making the model depend on a variable being set in the controller to function properly. – Josiah Kiehl Nov 22 '10 at 21:01
  • Josian, i really cannot see any other way of doing that. – Spyros Nov 24 '10 at 23:41
2

Look the user up when validating. It's likely the user lookup will have been cached by ActiveRecord, so it's not a performance hit to do so. Try something like this:

class Book

  validate :check_gold

  def check_gold
    user = User.find(self.user_id)
    self.errors.add(:user_id => "#{user.name} doesn't have enough gold!") if user.nil? or (user.gold < 100)
  end
end
Josiah Kiehl
  • 3,593
  • 3
  • 26
  • 28
  • I actually got what i expected, an error on user_id (undefined method `user_id'). No matter how hard i try, i cannot get the current_user to the Book model. – Spyros Nov 21 '10 at 07:20
  • If user_id is not defined in the Book model, then you aren't using an association, as I thought you would be. Is there a field named "user_id" in your "books" table? Are users supposed to own books? – Josiah Kiehl Nov 22 '10 at 21:00