Search code examples
ruby-on-railsactiverecorddeviserails-adminpaper-trail-gem

Rails 4 - Can't update model attribute


How can I save an attribute based on a condition between attributes of the same model? I've been unable to update a record unless the attribute's state remains the true.

I've checked this thread before: Rails. Update model attributes on save

This is the code I'm running:

class Ip < ActiveRecord::Base
  has_paper_trail
  has_and_belongs_to_many :users
  validates_uniqueness_of :ip_address, :hostname
  before_save :set_availability

  extend Enumerize
  enumerize :status, in: [:available, :allocated, :pending, :blocked], default: :available

  def ip_address_name
    self.ip_address
  end

  def set_availability
    self.is_available = false unless self.status.available?      
  end
end

Basically I have a list of "Ips" which I'd like to keep track of, and a "is_available" boolean to tell me wether the ip's status is available or not (which should set itself automatically, based on the "status" field).

So the issue is, for example,

I access the model, edit the record, change the :status from :available to :allocated, and hit "Save", it rolls back, raises me "Ip failed to be updated", and on the server the transaction is "Completed 406 Not Acceptable"

Here's the log:

=============== Phusion Passenger Standalone web server started ===============
PID file: /home/user/IP_Manager/tmp/pids/passenger.3000.pid
Log file: /home/user/IP_Manager/log/passenger.3000.log
Environment: development
Accessible via: http://0.0.0.0:3000/

You can stop Phusion Passenger Standalone by pressing Ctrl-C.
Problems? Check https://www.phusionpassenger.com/library/admin/standalone/troubleshooting/
===============================================================================
App 31353 stdout: 
App 31368 stdout: 


Started HEAD "/" for 127.0.0.1 at 2015-08-04 09:41:07 -0300
  ActiveRecord::SchemaMigration Load (0.2ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by HomeController#index as HTML
Redirected to http://0.0.0.0/users/sign_in
Completed 302 Found in 10ms (ActiveRecord: 0.0ms)


Started GET "/admin/ip/2/edit" for 127.0.0.1 at 2015-08-04 09:41:14 -0300
Processing by RailsAdmin::MainController#edit as HTML
  Parameters: {"model_name"=>"ip", "id"=>"2"}
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
  Ip Load (0.1ms)  SELECT  "ips".* FROM "ips" WHERE "ips"."id" = ?  ORDER BY "ips"."id" ASC LIMIT 1  [["id", 2]]
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_boolean.html.haml (2.4ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_field.html.haml (1.2ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_field.html.haml (0.2ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_enumeration.html.haml (2.7ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_text.html.haml (1.0ms)
  User Load (0.2ms)  SELECT "users".* FROM "users" INNER JOIN "ips_users" ON "users"."id" = "ips_users"."user_id" WHERE "ips_users"."ip_id" = ?  [["ip_id", 2]]
   (0.1ms)  SELECT COUNT(*) FROM "users"
  User Load (0.1ms)  SELECT "users".* FROM "users"  ORDER BY users.id desc
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_filtering_multiselect.html.haml (27.7ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_submit_buttons.html.haml (2.8ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/edit.html.haml within layouts/rails_admin/application (64.5ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/_secondary_navigation.html.haml (3.7ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/_navigation.html.haml (6.6ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/_sidebar_navigation.html.haml (4.1ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/pjax.html.haml (7.3ms)
Completed 200 OK in 611ms (Views: 484.5ms | ActiveRecord: 1.6ms)


Started PUT "/admin/ip/2/edit" for 127.0.0.1 at 2015-08-04 09:41:20 -0300
Processing by RailsAdmin::MainController#edit as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"OI5LqfNXeYLQm1wGglmnPvkrTL3sHTYsiE/uJGp7Uxuserk7ee8b8ozIXclBkUtYYcoIeKCjcNnyZ00siruQjEZQ==", "ip"=>{"is_available"=>"1", "ip_address"=>"192.168.0.2", "hostname"=>"localhost2", "status"=>"allocated", "details"=>"", "user_ids"=>["", "", "1"]}, "return_to"=>"", "_save"=>"", "model_name"=>"ip", "id"=>"2"}
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
  Ip Load (0.1ms)  SELECT  "ips".* FROM "ips" WHERE "ips"."id" = ?  ORDER BY "ips"."id" ASC LIMIT 1  [["id", 2]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  User Load (0.1ms)  SELECT "users".* FROM "users" INNER JOIN "ips_users" ON "users"."id" = "ips_users"."user_id" WHERE "ips_users"."ip_id" = ?  [["ip_id", 2]]
   (1.1ms)  begin transaction
  Ip Exists (0.2ms)  SELECT  1 AS one FROM "ips" WHERE ("ips"."ip_address" = '192.168.0.2' AND "ips"."id" != 2) LIMIT 1
  Ip Exists (0.2ms)  SELECT  1 AS one FROM "ips" WHERE ("ips"."hostname" = 'localhost2' AND "ips"."id" != 2) LIMIT 1
   (0.1ms)  rollback transaction
  PaperTrail::Version Load (0.3ms)  SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = ? AND "versions"."item_type" = ?  ORDER BY "versions"."created_at" ASC, "versions"."id" ASC  [["item_id", 2], ["item_type", "Ip"]]
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_boolean.html.haml (0.4ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_field.html.haml (0.4ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_field.html.haml (0.3ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_enumeration.html.haml (1.1ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_text.html.haml (0.5ms)
  User Load (0.2ms)  SELECT "users".* FROM "users"  ORDER BY users.id desc
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_form_filtering_multiselect.html.haml (5.0ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/_submit_buttons.html.haml (1.5ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/rails_admin/main/edit.html.haml within layouts/rails_admin/application (25.7ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/_secondary_navigation.html.haml (1.9ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/_navigation.html.haml (3.6ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/_sidebar_navigation.html.haml (2.6ms)
  Rendered /home/user/.rvm/gems/ruby-2.2.1/gems/rails_admin-0.6.8/app/views/layouts/rails_admin/pjax.html.haml (6.1ms)
Completed 406 Not Acceptable in 267ms (Views: 223.5ms | ActiveRecord: 2.9ms)

This is my Gemfile (only the extra gems besides the default ones):

# Administration Panel Gems
gem 'rails_admin'                    # Rails Administration Panel Gem
gem 'rails_admin_history_rollback'   # Enables users to visualise and revert history
gem 'rails_admin_import', "~> 1.0.0" # Enables importation
gem 'devise'                         # Authentication Gem
gem 'cancancan'                      # Authorization Gem
gem 'paper_trail', '~> 4.0.0.rc'     # Auditing Gem (History)
gem 'enumerize'                      # Gem for enumerizing attributes

# Server gem
gem 'passenger'

Thank you for your time!


Solution

  • Not sure if that's what is causing the issue, but it might. If any method executed as before_save returns false, the whole transaction is aborted.

    Your method:

    def set_availability
      self.is_available = false unless self.status.available?      
    end
    

    will return false or nil. First case will cancel transaction. Change this method to:

    def set_availability
      self.is_available = false unless self.status.available?
      true    
    end