为什么我不能使用Sinatra和PostgreSQL将数据保存到数据库中?

时间:2016-01-29 18:42:10

标签: ruby postgresql activerecord sinatra

我在PostgreSQL中创建了我的数据库并进行了迁移。当我尝试将新数据保存到其中时,我收到了这个错误:

I wrote this refactoring tool.

这是我的代码:

我的布局:

<form method="post" action="/signup">
                    <div class="form-group">
                        <label>Username</label>
                        <input type="text" class="form-control" placeholder="Name" name="user[username]">
                    </div>
                    <div class="form-group">
                        <label>Email address</label>
                        <input type="email" class="form-control" placeholder="Email" name="user[email]">
                    </div>
                    <div class="form-group">
                        <label>Password</label>
                        <input type="password" class="form-control" placeholder="Password" name="user[password]">
                    </div>
                    <div class="form-group">
                        <label>Confirm Password</label>
                        <input type="password" class="form-control" placeholder="Confirm Password" name="user[confirm_password]">
                    </div>
                    <button type="submit" class="btn btn-info">Sign up</button>
                </form>

我的控制器:

post '/signup' do
    user = User.new(params[:user])
    user.create_user

end

我的模特:

require 'bcrypt'

class User < ActiveRecord::Base
    include BCrypt
    # This is Sinatra! Remember to create a migration!
    validates :email, :format => { :with => /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i ,
    :message => "Email wrong format" }
    validates :email, uniqueness: true

    def initialize(signup)
        #@signup = signup
        @username = signup["username"]
        @email = signup["email"]
        @password = signup["password"]
    end

    def test
        p @signup
    end

    def create_user
        p_p = Password.create(@password)
        p_h ||= Password.new(p_p)
        user_hash = {:username => @username,:email => @email, :encrypted_password => p_h}

        User.create(user_hash)

    end

end

完整回溯

/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb in clear_transaction_record_state
      @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb in ensure in rollback_active_record_state!
      clear_transaction_record_state
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb in rollback_active_record_state!
      clear_transaction_record_state
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb in save
      rollback_active_record_state! do
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5.1/lib/active_record/persistence.rb in create
          object.save
/Sites/nextAcademy/quora_clone/code/app/models/user.rb in create_user
        return User.create(user_hash)
/Sites/nextAcademy/quora_clone/code/app/controllers/static.rb in block in <top (required)>
    "#{user.create_user}"
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call
          proc { |a,p| unbound_method.bind(a).call }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in compile!
          proc { |a,p| unbound_method.bind(a).call }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in []
            route_eval { block[*args] }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block (3 levels) in route!
            route_eval { block[*args] }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in route_eval
      throw :halt, yield
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block (2 levels) in route!
            route_eval { block[*args] }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in process_route
        block ? block[self, values] : yield(self, values)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in catch
      catch(:pass) do
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in process_route
      catch(:pass) do
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in route!
          returned_pass_block = process_route(pattern, keys, conditions) do |*args|
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in each
        routes.each do |pattern, keys, conditions, block|
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in route!
        routes.each do |pattern, keys, conditions, block|
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in dispatch!
        route!
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in invoke
      res = catch(:halt) { yield }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in catch
      res = catch(:halt) { yield }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in invoke
      res = catch(:halt) { yield }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in dispatch!
      invoke do
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in call!
      invoke { dispatch! }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in invoke
      res = catch(:halt) { yield }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in catch
      res = catch(:halt) { yield }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in invoke
      res = catch(:halt) { yield }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call!
      invoke { dispatch! }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call
      dup.call!(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb in context
          status, headers, body = app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb in call
          context(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb in call
        status, headers, body = @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-protection-1.5.3/lib/rack/protection/path_traversal.rb in call
        app.call env
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb in call
        status, headers, body = app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb in call
        result or app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb in call
        result or app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb in call
        status, headers, body        = @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/logger.rb in call
      @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call
      env['sinatra.commonlogger'] ? @app.call(env) : super
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/head.rb in call
    status, headers, body = @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/methodoverride.rb in call
      @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/show_exceptions.rb in call
      @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call
      result, callback = app.call(env), env['async.callback']
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call
      @stack.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in block in call
        synchronize { prototype.call(env) }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in synchronize
          yield
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call
        synchronize { prototype.call(env) }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/lint.rb in _call
      status, headers, @body = @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/lint.rb in call
      dup._call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/showexceptions.rb in call
      @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/commonlogger.rb in call
      status, header, body = @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sinatra-1.4.6/lib/sinatra/base.rb in call
        call_without_check(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/shotgun-0.9.1/lib/shotgun/loader.rb in proceed_as_child
      status, headers, body = assemble_app.call(@env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/shotgun-0.9.1/lib/shotgun/loader.rb in call!
        proceed_as_child
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/shotgun-0.9.1/lib/shotgun/loader.rb in call
      dup.call!(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/shotgun-0.9.1/lib/shotgun/favicon.rb in call
        app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/shotgun-0.9.1/lib/shotgun/static.rb in call
        @app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/urlmap.rb in block in call
        return app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/urlmap.rb in each
      @mapping.each do |host, location, match, app|
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/urlmap.rb in call
      @mapping.each do |host, location, match, app|
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/builder.rb in call
      to_app.call(env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/thin-1.6.4/lib/thin/connection.rb in block in pre_process
        response = @app.call(@request.env)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/thin-1.6.4/lib/thin/connection.rb in catch
      catch(:async) do
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/thin-1.6.4/lib/thin/connection.rb in pre_process
      catch(:async) do
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/thin-1.6.4/lib/thin/connection.rb in process
        post_process(pre_process)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/thin-1.6.4/lib/thin/connection.rb in receive_data
      process if @request.parse(data)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb in run_machine
          run_machine
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb in run
          run_machine
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/thin-1.6.4/lib/thin/backends/base.rb in start
          EventMachine.run(&starter)
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/thin-1.6.4/lib/thin/server.rb in start
      @backend.start { setup_signals if @setup_signals }
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/thin.rb in run
        server.start
/Users/manjarb/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/shotgun-0.9.1/bin/shotgun in <top (required)>
server.run app, options do |inst|
/Users/manjarb/.rbenv/versions/2.2.3/bin/shotgun in load
load Gem.bin_path('shotgun', 'shotgun', version)
/Users/manjarb/.rbenv/versions/2.2.3/bin/shotgun in <main>
load Gem.bin_path('shotgun', 'shotgun', version)

有谁知道为什么会发生这种情况?

2 个答案:

答案 0 :(得分:1)

是否有理由(除了缺乏熟悉程度)不使用ActiveRecord回调?我认为如果你让ActiveRecord做的话,你的解决方案可能会相当简单......

class User < ActiveRecord::Base
  attr_accessor :password

  validates :username, presence: true, uniqueness: true
  validates :email, format: { with: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i, message: 'Invalid email format' },
                    uniqueness: true,
                    presence: true
  validates :encrypted_password, presence: true

  before :validation, :encrypt_password, if: :password_present?

  private

  def password_present?
    !password.nil? && !password.length.zero?
  end

  def encrypt_password
    self.encrypted_password = Password.new(password)
  end
end

在上面的示例中,“before:validation”行告诉活动记录在执行验证之前调用encrypt_password方法,但前提是密码已经提供。在这种情况下,它将根据调用者提供的“密码”值为encrypted_pa​​ssword属性分配一个新密码。

请注意,代码假定密码未持久保存到数据库(仅保存encrypted_pa​​ssword)。如果没有db-backed密码列,则需要显式公开密码属性才能使其生效。您基本上通过代码中的@password实例变量解决了这个问题。

使用类似建议的类,您的控制器将成为

post '/signup' do
  user = User.create(params[:user])
end

答案 1 :(得分:1)

你的问题是你正在扩展ActiveRecord::Base类,并覆盖它的构造函数。因此,ActiveRecord::Base所依赖的几个属性未初始化。尝试将super()添加到构造函数中,如下所示:

def initialize(signup)
    super()
    #@signup = signup
    @username = signup["username"]
    @email = signup["email"]
    @password = signup["password"]
end

或者,完全删除构造函数并将signup哈希值传入create_user方法。