【问题标题】:Why can't I save data into the database using Sinatra and PostgreSQL?为什么我不能使用 Sinatra 和 PostgreSQL 将数据保存到数据库中?
【发布时间】:2016-05-07 14:44:37
【问题描述】:

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

这是我的代码:

我的布局:

<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)

有人知道为什么会这样吗?

【问题讨论】:

  • 在传递给User.create(user_hash)之前尝试打印出user_hash的内容
  • 欢迎来到 Stack Overflow。我强烈建议您阅读tinyurl.com/stack-hints 和catb.org/esr/faqs/smart-questions.html。语法和拼写很重要。另外,不要使用图像来显示错误;图像很难阅读和重用。将文本复制并粘贴到您的问题中,以便我们阅读,如果需要搜索,请将信息复制/粘贴到我们的浏览器中。此外,指向任何非现场内容的链接往往会腐烂和破坏,这使得它们在未来对于寻找类似答案的其他人来说毫无用处。
  • @MartinKonecny 我把它打印出来检查,似乎没问题。
  • 请在错误页面展开backtrace,并在此处发布
  • @MartinKonecny 已经更新回溯

标签: ruby postgresql activerecord sinatra


【解决方案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 方法。

【讨论】:

    【解决方案2】:

    是否有理由(除了不熟悉)不使用 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 支持的密码列,则需要显式公开密码属性才能使其正常工作。您基本上已经通过代码中的 @password 实例变量解决了这个问题。

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

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

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 1970-01-01
      • 2012-07-05
      • 2021-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-29
      • 1970-01-01
      相关资源
      最近更新 更多