Search code examples
rubysequelramaze

Why won't Sequel write my database table?


controller/makenew.rb

class MakeController < Controller

  map '/makenew'
  #require 'model/debate'

  def debate
    if request.post? #this line is potentially dangerous!
      #---> 1/3 fetch postdata
      data = request.subset(:question, :type, :category, :assertion)
      data['user_id'] = user.id #id = request.params['id']
      #---> 2/3 check permissions
      if user.points < 40
        flash[:error] = 'You don\'t have enough points to make a debate.'
        redirect_referrer
      else
        debate = Debate.new
      end
      #---> 3/3 modify database
      begin
        debate.save(data)
        flash[:success] = success
        flash[:form_data] = debate
        redirect 'debates'
      rescue => e
        Ramaze::Log.error(e)
        #flash[:form_errors]   = debate.errors
        #flash[:error] = data
        flash[:error] = e
        #flash[:error] = 'Failure whilst saving. Contact technical support!'
        redirect 'debates' #redirect_referrer
      end
     #| 
    end #closes posting conditional
  end #closes makesave 
end

The error I get is.

SQLite3::ConstraintException: debates.question may not be NULL

I have checked the postdata for data.question and it is not null.

What is going on?


Solution

  • You need to pass 'data' to #update. Thus:

    debate.save(data)
    

    is wrong, you have to do:

    debate.update(data)
    debate.save
    

    If you don't do this, your debate object has no member assigned and thus its question member is nil, violating your DB constraints.

    See the differences between #save and #update here:

    In a nutshell: #save will save the current model instance to the database, while #update will change a bunch of instance attributes in one operation.

    But you have to remember that changing a model instance's attributes DOES NOT write them to the database. You always have to call #save explicitly.