0

So, this is driving me crazy and I find myself unable to answer the question neither by myself nor by reading other questions and answers.

When I try to update a record in my db which was created through the webapp, I am not able to alter the values of the record. In this case, there is a form that a user fills in and afterwards the app should update several fields in different models.

First, the form:

<%= form_for(@game) do |g| %>
  <%= g.label :player_1 %>
  <%= g.text_field :player_1 %>

  <%= g.label :player_2 %>
  <%= g.text_field :player_2 %>

  <%= g.label :faction_1 %>
  <%= g.text_field :faction_1 %>

  <%= g.label :faction_2 %>
  <%= g.text_field :faction_2 %>

  <%= g.label :caster_1 %>
  <%= g.text_field :caster_1 %>

  <%= g.label :caster_2 %>
  <%= g.text_field :caster_2 %>

  <%= g.label :point_level %>
  <%= g.text_field :point_level %>

  <%= g.label :winner %>
  <%= g.text_field :winner %>

  <%= g.submit "eintragen", class: "btn btn-large btn-primary" %>
<% end %>

In the Games controller, I have a create method

def create
    @game = Game.new(params[:game])
    if @game.save
      flash[:success] = "Spiel erfolgreich eingereicht"
      @player_1 = User.find_by_name(@game.player_1)
      @player_1.update_attributes(:games_played => @player_1.games_played + 1)
      redirect_to @game
    else
      render 'new'
    end
 end

Needless to say, it's not working as I would have expected. What bugs me is the following: If i try to alter the record in the console, the following happens:

user = User.find_by_name("Example User")
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."name" = 'Example User' LIMIT 1
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2012-09-28 11:48:10", updated_at: "2012-09-28 11:48:10", password_digest: "$2a$10$3GQnsHGAfp09v1v.csb6Ce8pCPwfY0Hl1nG2a09BvOo8...", remember_token: "MsRfXle0N67ws9otkeDP_w", admin: true, elo_rating: 1000, games_played: 0> 


user.valid?
  User Exists (0.2ms)  SELECT 1 AS one FROM "users" WHERE (LOWER("users"."name") = LOWER('Example User') AND "users"."id" != 1) LIMIT 1
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('example@railstutorial.org') AND "users"."id" != 1) LIMIT 1
=> false 

I can not understand, why the User should not be valid. All tests pass (formulated in the manner of the railstutorial). My User model:

# == Schema Information
#
# Table name: users
#
#  id              :integer          not null, primary key
#  name            :string(255)
#  email           :string(255)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#  password_digest :string(255)
#  remember_token  :string(255)
#  admin           :boolean          default(FALSE)
#  elo_rating      :integer          default(1000)
#  games_played    :integer          default(0)
#

class User < ActiveRecord::Base
  attr_accessible :name, :email, :password, :password_confirmation, :games_played, :elo_rating
  has_secure_password

  before_save { |user| user.email = email.downcase }
  before_save :create_remember_token
  validates :name,  presence: true, 
                    uniqueness: true, 
                    length: { :maximum => 50 }

  # regex take from railstutorial by Michael Hartl (http://ruby.railstutorial.org)
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, 
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }

  validates :password, presence: true, length: { minimum: 6 }
  validates :password_confirmation, presence: true
  validates :games_played, presence: true
  validates_numericality_of :games_played, greater_than_or_equal_to: 0
  validates_numericality_of :elo_rating, greater_than_or_equal_to: 0

  private

    def create_remember_token
      self.remember_token = SecureRandom.urlsafe_base64
    end
end

I'm really stuck here, because this functionality is essential and I have to do many more of these record updates through forms. I really can't figure out why my records become invalid. Furthermore, I'm sure there is a better way to update those records and maybe even to avoid this issue completely?

Thanks in advance

neshtea
  • 68
  • 1
  • 8

4 Answers4

1

whenever their is update_attributes itt tries to update the password also which will make the record invalid just do

validates :password, presence: true, length: { minimum: 6 }, :if => :password
validates :password_confirmation, presence: true, :if => :password_confirmation

now try it

Aayush Khandelwal
  • 1,071
  • 7
  • 11
0

Maybe it's not valid because of poor data in your DB (some users has the same email or name). If this is the case, reload your database

Denis Tataurov
  • 193
  • 2
  • 12
0

Based on your user.errors, you don't want to validate the :password and :password_confirmation each time you save your user; only if you're actually creating a user or allowing a user to update those values explicitly, say from their account edit page.

Your user model validation logic may work if you make a change like this:

class User < ActiveRecord::Base
  validates :password, presence: {if: :password_required?}, length: { minimum: 6, allow_blank: true }
  validates :password_confirmation, presence: { if: :password_required? }

  private

  def password_required?
    !persisted? || !password.nil? || !password_confirmation.nil?
  end
end
rossta
  • 11,394
  • 1
  • 43
  • 47
  • Thanks for this, unfortunately, when I use this piece of code, I get the following error if I visit a page: `undefined method `password_required?' for #`. What am I missing? `Extracted source (around line #1):` `1: <% if signed_in? %> 2:

    3: Willkommen zurueck bei dicedown 4:

    `
    – neshtea Sep 28 '12 at 13:55
  • Looks like I mistyped one of the validates lines; I meant `:password_required?` within both :presence options. Just edited the sample – rossta Sep 28 '12 at 13:59
0

Another way to write it.

with_options if: :password do |user|
  user.validates :password, presence: true, length: { minimum: 6 }
  user.validates :password_confirmation, presence: true
end
foloinfo
  • 631
  • 8
  • 19