thank_you
thank_you

Reputation: 11107

Handling PostgreSQL Creating Tables, Associations, and Rails

Long story short I decided to wipe out my database on my localhost and experiment with posgreSQL and pgAdmin with my Rails app. I first deleted any servers I had via pgAdmin. I then ran db:create:all, db:migrate, and finally db:test:prepare. Now whenever I run my previous spec tests before I did all this database experimentation the majority of my tests fails giving me this error..

 Failure/Error: @user = FactoryGirl.create(:user)
 NoMethodError:
   undefined method `password_reset_sent_at' for #<User:0xb48a55c>

or

 Failure/Error: @user.save
 NoMethodError:
   undefined method `password_reset_sent_at' for #<User:0xaa9c040>

I thought I may have not allowed password_reset_sent_at as a non-accessible attribute but it is accessible and my user model has the has_one :user_reset_password, :dependent => :destroy.

My database.yml looks like...

development:
  adapter: postgresql
  encoding: unicode
  database: template_development
  host: localhost
  pool: 5
  username: jason
  password: password

test:
  adapter: postgresql
  encoding: unicode
  database: template_test
  host: localhost
  pool: 5
  username: jason
  password: password

When I run the application and I create a new user I get this error.

undefined method `password_reset_sent_at' for #<User:0xa6fb184>

app/models/user.rb:78:in `empty_password_reset_token'
app/controllers/users_controller.rb:25:in `create'

The empty_password_reset_token method is

def empty_password_reset_token
  if self.password_digest_changed?
    if self.password_reset_sent_at && self.password_reset_sent_at < 2.hours.ago
      false
    else
      self.password_reset_token = ""
      self.password_reset_sent_at = ""
    end
  end
end

My schema file

ActiveRecord::Schema.define(:version => 20130124193639) do

  create_table "user_login_failures", :force => true do |t|
    t.integer  "user_id"
    t.integer  "login_failure_attempts"
    t.datetime "created_at",             :null => false
    t.datetime "updated_at",             :null => false
  end

  create_table "user_reset_passwords", :force => true do |t|
    t.integer  "user_id"
    t.string   "password_reset_token"
    t.datetime "password_reset_sent_at"
    t.datetime "created_at",             :null => false
    t.datetime "updated_at",             :null => false
  end

  create_table "users", :force => true do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at",      :null => false
    t.datetime "updated_at",      :null => false
    t.string   "password_digest"
  end

  add_index "users", ["email"], :name => "index_users_on_email", :unique => true

end

I really have no idea why this is not working. The tables all have the appropriate columns and nothing is missing. Any help would be appreciated.

Upvotes: 1

Views: 740

Answers (3)

thaJeztah
thaJeztah

Reputation: 28987

This may be completely unrelated (I have NO Ruby experience), but I see a lot of 'backticks' (`) in your question.

In various languages, the back tick operator will try to execute a executable on the command line.

MySQL uses backticks for quoting column-names so if you're migrating from MySQL they may be leftovers from MySQL SQL statements

Therefore Ruby may try to execute

`password_reset_sent_at' 

As a system command

[update] According to this answer, Ruby on Rails seems to use backticks for system access as well: Getting output of system() calls in Ruby

Please ignore if this is not the case, just trying to help out :)

Upvotes: 0

jvnill
jvnill

Reputation: 29599

Since the columns you're using in the user mode is in another model, you have to call that model first, you have to change password_reset_token to

def empty_password_reset_token
  if self.password_digest_changed?
    build_user_reset_password unless user_reset_password
    if user_reset_password.password_reset_sent_at && user_reset_password.password_reset_sent_at < 2.hours.ago
      false
    else
      user_reset_password.password_reset_token = ""
      user_reset_password.password_reset_sent_at = ""
    end
  end
end

or you can use delegate and keep the method as is

delegate :password_reset_sent_at, :password_reset_token, to: :user_reset_password

Upvotes: 0

cddr
cddr

Reputation: 300

I'd have a look at db/schema.rb. Each time you run your tests, the DB is torn down and rebuilt based on the contents of that file. I suspect that according to db/schema.rb, your "users" table does not have a "password_reset_sent_at" column

Upvotes: 1

Related Questions