Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails ActiveRecord保存错误未定义方法“[]';零级:零级_Ruby On Rails_Ruby_Activerecord_Save_Runtime Error - Fatal编程技术网

Ruby on rails Rails ActiveRecord保存错误未定义方法“[]';零级:零级

Ruby on rails Rails ActiveRecord保存错误未定义方法“[]';零级:零级,ruby-on-rails,ruby,activerecord,save,runtime-error,Ruby On Rails,Ruby,Activerecord,Save,Runtime Error,尝试在rails中保存模型对象时出错。我要说的是,我没有使用数据库迁移,而是在rails中使用预先存在的数据库。 这是我的模型课: require 'bcrypt' require 'securerandom' class Profile < ActiveRecord::Base include BCrypt self.table_name = 'profiles' self.primary_key = 'id' attr_accessor :id, :username

尝试在rails中保存模型对象时出错。我要说的是,我没有使用数据库迁移,而是在rails中使用预先存在的数据库。 这是我的模型课:

require 'bcrypt'
require 'securerandom'
class Profile < ActiveRecord::Base
  include BCrypt

  self.table_name = 'profiles'
  self.primary_key = 'id'

  attr_accessor :id, :username, :password_hash, :salt, :first_name, :last_name, :location, :status, :game_status

  def initialize(attributes = {}, options = {})
    @username = attributes[:username]
    @salt = SecureRandom.hex
    @password_hash = Password.create(attributes[:password] + @salt).to_s
    @first_name = attributes[first_name]
    @last_name = attributes[last_name]
    @location = attributes[location]
    @status = "Hi"
    @game_status = "Playing some game..."
  end

  def hash_rep
    hash = {}
    hash['id'] = @id
    hash['username'] = @username
    hash['password_hash'] = @password_hash
    hash['salt'] = @salt
    hash['location'] = @location
    hash['status'] = @status
    hash['game_status'] = @game_status
    return hash
  end

end
以下是我的控制器代码:

  def register
    profile = Profile.new(:id => params[:id],
                          :username => params[:username],
                          :password => params[:password],
                          :first_name => params[:first_name],
                          :last_name => params[:last_name],
                          :location => params[:location])
    profile.save
    render_profile(profile)
  end
“profile.save”方法出现错误。以下是相关的stacktrace:

activerecord (4.2.0) lib/active_record/transactions.rb:375:in `clear_transaction_record_state'
activerecord (4.2.0) lib/active_record/transactions.rb:306:in `ensure in rollback_active_record_state!'
activerecord (4.2.0) lib/active_record/transactions.rb:306:in `rollback_active_record_state!'
activerecord (4.2.0) lib/active_record/transactions.rb:285:in `save'
app/controllers/profile_controller.rb:52:in `register'
actionpack (4.2.0) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
actionpack (4.2.0) lib/abstract_controller/base.rb:198:in `process_action'

错误为:“nil:NilClass”的未定义方法“[]”

在新方法中,您应该将这些更改为符号,从:

@first_name = attributes[first_name]
@last_name = attributes[last_name]
@location = attributes[location]
致:

另外,您不需要传入选项哈希?因为你不用它

require 'bcrypt'
require 'securerandom'
class Profile < ActiveRecord::Base
  include BCrypt

  self.table_name = 'profiles'
  self.primary_key = 'id'

  def hash_rep
    hash = {}
    hash['id'] = id
    hash['username'] = username
    hash['password_hash'] = password_hash
    hash['salt'] = salt
    hash['location'] = location
    hash['status'] = status
    hash['game_status'] = game_status
    hash
  end

  def self.build(args)
    new_profile = Profile.new
    new_profile.username = args[:username]
    salt = SecureRandom.hex
    new_profile.password_hash = Password.create(args[:password] + salt).to_s
    new_profile.first_name = args[:first_name]
    new_profile.last_name = args[:last_name]
    new_profile.location = args[:location]
    new_profile.status = "Hi"
    new_profile.game_status = "Playing some game..."
    new_profile
  end
end
顺便说一句,您的hash_rep方法没有那么有用,请尝试:

profile = Profile.build({ username: 'foo' })
profile.attributes
旁注:

  • 由于您遵循约定,因此不需要添加这些行,只需删除它们:
    self.table\u name='profiles'
    self.primary\u key='id'

  • 当心散列,似乎你不在乎字符串或符号键,但它们是不一样的

  • 有更优雅的方法来编写方法,但我一直保持简单,因为在这个阶段没有必要详细说明


    • 在rails中设置默认属性的更好方法是通过回调:

      require 'bcrypt'
      require 'securerandom'
      class Profile < ActiveRecord::Base
        include BCrypt
      
        attr_accessor :password # is a virtual attribute
      
        after_initialize do
          if new_record?
            # values will be available for new record forms.
            self.status = status || "Hi"
            self.game_status = game_status || "Playing some game..."
          end
        end
      
        before_validation(on: :create) do
          self.salt = SecureRandom.hex
          self.password_hash = Password.create(password + salt).to_s
        end
      
          # Yuck. use http://apidock.com/rails/ActiveModel/Serialization/serializable_hash
        def hash_rep
          serializable_hash( only: [:id, :username, :password_hash, :salt, :location, :status, :game_status] )
        end
      
      end
      

      寄存器中没有名为
      params
      的局部变量。也就是说,局部变量
      params
      在第一次出现时被初始化为
      nil
      params[:id]
      在此等同于导致错误的
      nil[:id]
      。在控制台中逐步执行此操作:通过从日志中复制来设置params,并逐行执行代码。你应该能够看到什么是不对的。哎哟,你做了很多错误的事情:当涉及表列时,不需要attr_访问器,永远不要重新定义初始化我不同意,回调是一种瘟疫。如果您在构建某些内容时需要默认值,则只需使用生成器。这是众所周知的和使用过的设计模式的一部分,将大量挂在各处的样板文件分配代码听起来是一个非常好的主意-不是这样,有更好的方法,但你是在回答一个初学者。所以现在没必要把他弄糊涂。顺便说一句,他不能使用你的代码而不得到一个例外:
      密码不是一个属性
      编辑以添加密码的访问者。但实际上,他应该使用,而不是试图从头开始做密码摘要。这太容易搞砸了。:)一旦你对这些工具感到满意,就可以一步一步地进行抽象。。。。
      Profile.build({ username: 'foo' })
      
      profile = Profile.build({ username: 'foo' })
      profile.attributes
      
      require 'bcrypt'
      require 'securerandom'
      class Profile < ActiveRecord::Base
        include BCrypt
      
        attr_accessor :password # is a virtual attribute
      
        after_initialize do
          if new_record?
            # values will be available for new record forms.
            self.status = status || "Hi"
            self.game_status = game_status || "Playing some game..."
          end
        end
      
        before_validation(on: :create) do
          self.salt = SecureRandom.hex
          self.password_hash = Password.create(password + salt).to_s
        end
      
          # Yuck. use http://apidock.com/rails/ActiveModel/Serialization/serializable_hash
        def hash_rep
          serializable_hash( only: [:id, :username, :password_hash, :salt, :location, :status, :game_status] )
        end
      
      end
      
      class ProfileController < ApplicationController 
      
        def new
          @profile = Profile.new
        end
      
        def register
          @profile = Profile.new(create_params)
          if @profile.save
            redirect_to @profile 
          else 
            render action: :new
          end
        end
      
        private
        def create_params
          params.require(:profile).allow(:username, :password, : first_name :last_name :location)
        end
      end