0

Ok, this issue is getting me pull my hair out. I have this controller action, which creates user. But @user.create_session is never successful, even if @user.save was success.

def create
    @user = User.new(params[:user])
    @user.password_changed
    if @user.save
      session[:session] = @user.create_session
    end

The method in User model create_session is this

  def create_session
    if self.session.nil? or self.updated_at < 1.month.ago
        begin
            self.session = Crypto.new.salt(50)
        end while User.find_by_session(self.session).nil? == false
        self.save
      end
    return self.session
  end

Now if I do this, it creates session and everything works perfectly fine:

def create
    @user = User.new(params[:user])
    @user.password_changed
    session[:session] = @user.create_session

However I would prefer to generate session AFTER the registration, in case validation fails or Im doing excess sql request + have meaningless cookie.

In IRB it works fine either way:

1.9.3-p374 :046 > @user = User.last
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
 => #<User id: 19, name: "Jkfsdkh", username: "hkjfaskh", password: "$2a$10$jAXv.FAmlZDi7xT.yeP/keri1p9pVnYygaCl0z7YMdpH...", email: "so@fs.cm", email_confirmed: false, salt: "Ju_ILOlqJnAXfc-z6gvO1cJUAguHwhtwBWJCGPDtxRw", session: "Pw0xu1b-gZfn1GEESZM1r2PAjzM4y-B5FFJ2vHKlkokpiM6gkyK...", ip: "127.0.0.1", created_at: "2013-02-19 05:41:11", updated_at: "2013-02-19 05:41:48"> 
1.9.3-p374 :047 > @user.session = nil
 => nil 
1.9.3-p374 :048 > if @user.save
1.9.3-p374 :049?>   @user.create_session
1.9.3-p374 :050?>   end
   (0.1ms)  begin transaction
  User Exists (0.2ms)  SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'me@janbirsa.cm' AND "users"."id" != 19) LIMIT 1
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE ("users"."username" = 'hkjfaskh' AND "users"."id" != 19) LIMIT 1
   (0.3ms)  UPDATE "users" SET "session" = NULL, "updated_at" = '2013-02-19 05:43:09.960854' WHERE "users"."id" = 19
   (2.8ms)  commit transaction
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."session" = '1_BezpY-5b4oaFhAOiR4zRuKb1mLVbU1MxmZs07dPY9LCKJ_t1XOXR82d8uXkCGjb0Y' LIMIT 1
   (0.0ms)  begin transaction
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'me@janbirsa.cm' AND "users"."id" != 19) LIMIT 1
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE ("users"."username" = 'hkjfaskh' AND "users"."id" != 19) LIMIT 1
   (0.3ms)  UPDATE "users" SET "session" = '1_BezpY-5b4oaFhAOiR4zRuKb1mLVbU1MxmZs07dPY9LCKJ_t1XOXR82d8uXkCGjb0Y', "updated_at" = '2013-02-19 05:43:09.967159' WHERE "users"."id" = 19
   (0.8ms)  commit transaction
 => "1_BezpY-5b4oaFhAOiR4zRuKb1mLVbU1MxmZs07dPY9LCKJ_t1XOXR82d8uXkCGjb0Y" 
1.9.3-p374 :051 > @user.session
 => "1_BezpY-5b4oaFhAOiR4zRuKb1mLVbU1MxmZs07dPY9LCKJ_t1XOXR82d8uXkCGjb0Y" 
1.9.3-p374 :052 > 

Also when I am creating session from login controller it works fine too.

EDIT: Here, I re-created what controller does in irb.

1.9.3-p374 :001 > new = User.new
 => #<User id: nil, name: nil, username: nil, password: nil, email: nil, email_confirmed: false, salt: nil, session: nil, ip: nil, created_at: nil, updated_at: nil> 
1.9.3-p374 :002 > new.name = 'test'
 => "test" 
1.9.3-p374 :003 > new.username = 'test2'
 => "test2" 
1.9.3-p374 :004 > new.password = 'test123'
 => "test123" 
1.9.3-p374 :005 > new.email = 'test@t.cpm'
 => "test@t.cpm" 
1.9.3-p374 :006 > new.password_changed
 => true 
1.9.3-p374 :007 > if new.save
1.9.3-p374 :008?>   new.create_session
1.9.3-p374 :009?>   end
   (0.1ms)  begin transaction
  User Exists (0.2ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = 'test@t.cpm' LIMIT 1
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE "users"."username" = 'test2' LIMIT 1
Binary data inserted for `string` type on column `password`
  SQL (4.6ms)  INSERT INTO "users" ("created_at", "email", "email_confirmed", "ip", "name", "password", "salt", "session", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["created_at", Wed, 20 Feb 2013 01:32:45 UTC +00:00], ["email", "test@t.cpm"], ["email_confirmed", false], ["ip", nil], ["name", "test"], ["password", "$2a$10$nrWM/es2D/1hrjaBVnNj3esBOEvRm9nILmTNiRvBJG00fUTRuPXui"], ["salt", "WRxgy_hoPPXo5v2QtoN47khXso3ZFfkSdDDB9uvH3P8"], ["session", nil], ["updated_at", Wed, 20 Feb 2013 01:32:45 UTC +00:00], ["username", "test2"]]
   (3.8ms)  commit transaction
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."session" = 'KoBISJTarhdO1ZWFgn8HDk6zNts779QU0NUORIh84IRMFY4f6s4cV2w7BxgAa6pz3Ck' LIMIT 1
   (0.0ms)  begin transaction
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'test@t.cpm' AND "users"."id" != 22) LIMIT 1
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE ("users"."username" = 'test2' AND "users"."id" != 22) LIMIT 1
   (0.3ms)  UPDATE "users" SET "session" = 'KoBISJTarhdO1ZWFgn8HDk6zNts779QU0NUORIh84IRMFY4f6s4cV2w7BxgAa6pz3Ck', "salt" = 'Q-4E-D7xNADTp9_qnSmAg5NATpHv1dWcUtvGExeUll8', "password" = '$2a$10$/aM541saVBBG/mHizdK05OBNfcLFVsMu.3rpnThKs5M71SBdC6aJ.', "updated_at" = '2013-02-20 01:32:45.659951' WHERE "users"."id" = 22
   (2.4ms)  commit transaction
 => "KoBISJTarhdO1ZWFgn8HDk6zNts779QU0NUORIh84IRMFY4f6s4cV2w7BxgAa6pz3Ck" 
1.9.3-p374 :010 > new.session
 => "KoBISJTarhdO1ZWFgn8HDk6zNts779QU0NUORIh84IRMFY4f6s4cV2w7BxgAa6pz3Ck" 
1.9.3-p374 :011 > 

Now I still can't figure out, why irb does fine and controller not. Its making me go nuts.

4

1 回答 1

0

好吧,我已经将我的代码重构为更有意义的东西。我的注册控制器现在很简单:

  def create
    @user = User.new(params[:user])
    @user.password_changed

    if @user.save 
        session[:session] = @user.session
        redirect_to root_url, notice: 'User was successfully created.'
    else
        render action: "new"
    end
  end

会话生成与密码生成联系起来更有意义,因此我将它们合并为一种方法,即在保存之前调用。

 before_save :encrypt_password, if: :password_changed?

  def encrypt_password
    self.salt = Crypto.new.salt
    self.password = Crypto.new(self.salt).bcrypt(self.password)
    begin
        self.session = Crypto.new.salt(50)
    end while User.find_by_session(self.session)
  end
于 2013-02-20T02:00:08.543 回答