Rails 4 - 无法更新模型属性

时间:2015-08-04 12:50:35

标签: ruby-on-rails activerecord devise rails-admin paper-trail-gem

如何根据同一模型的属性之间的条件保存属性?除非属性的状态仍为真,否则我无法更新记录。

我之前检查过这个帖子:Rails. Update model attributes on save

这是我正在运行的代码:

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

基本上我有一个&#34; Ips&#34;我想跟踪它,并且&#34; is_available&#34;布尔告诉我ip的状态是否可用(应该根据&#34; status&#34;字段自动设置)。

所以问题是,例如,

我访问模型,编辑记录,更改:状态从:可用到:已分配,然后点击&#34;保存&#34;,它回滚,引发我&#34; Ip未能更新&#34 34;,并且在服务器上交易是&#34; 已完成406不可接受&#34;

这是日志:

&#13;
&#13;
=============== 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)
&#13;
&#13;
&#13;

这是我的Gemfile(除了默认宝石之外只有额外的宝石):

# 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'

感谢您的时间!

2 个答案:

答案 0 :(得分:4)

不确定是否是导致问题的原因,但可能是。如果以before_save执行的任何方法返回false,则整个事务将中止。

你的方法:

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

将返回false或nil。第一种情况将取消交易。将此方法更改为:

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

答案 1 :(得分:1)

由于您在set_availability中设置了false值,因此从回调中返回false值并回滚。返回false的before *回调将回滚模型上的所有更新。

来自Rails文档http://guides.rubyonrails.org/active_record_callbacks.html

  

6停止执行

     

当您开始为模型注册新的回调时,它们将是   排队等待执行。此队列将包含您的所有模型   验证,已注册的回调和数据库操作   被执行。

     

整个回调链包含在一个事务中。如果有的话   回调方法返回完全错误或引发异常,   执行链停止并发出ROLLBACK;回调后   只能通过提出例外来实现这一点。

这样的事情可能有用。

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