Rails 4 - 无法更新模型属性
Rails 4 - Can't update model attribute
如何根据同一模型的属性之间的条件保存属性?除非属性的状态保持为真,否则我无法更新记录。
我之前检查过这个线程: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
基本上我有一个 "Ips" 的列表,我想跟踪它,还有一个 "is_available" 布尔值告诉我 ip 的状态是否可用(应该自行设置自动,基于 "status" 字段)。
所以问题是,例如,
我访问模型,编辑记录,将 :status 从 :available 更改为 :allocated,然后点击 "Save",它回滚,提升我 "Ip failed to be updated",并在服务器上事务是“已完成 406 不可接受”
这是日志:
=============== 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)
这是我的 Gemfile(除了默认的之外只有额外的 gem):
# 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'
感谢您的宝贵时间!
不确定这是否是导致问题的原因,但可能是。如果任何方法执行为 before_save
returns false,整个事务将中止。
你的方法:
def set_availability
self.is_available = false unless self.status.available?
end
将 return 为假或为零。第一种情况将取消交易。将此方法更改为:
def set_availability
self.is_available = false unless self.status.available?
true
end
由于您在 set_availability 中设置了一个假值,回调会返回一个假值并回滚。 returns false 的 before* 回调将回滚模型上的所有更新。
来自 Rails 文档 http://guides.rubyonrails.org/active_record_callbacks.html
6 Halting Execution
As you start registering new callbacks for your models, they will be
queued for execution. This queue will include all your model's
validations, the registered callbacks, and the database operation to
be executed.
The whole callback chain is wrapped in a transaction. If any before
callback method returns exactly false or raises an exception, the
execution chain gets halted and a ROLLBACK is issued; after callbacks
can only accomplish that by raising an exception.
类似这样的方法可能有效。
def set_availability
self.is_available = false unless self.status.available?
true
end
如何根据同一模型的属性之间的条件保存属性?除非属性的状态保持为真,否则我无法更新记录。
我之前检查过这个线程: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
基本上我有一个 "Ips" 的列表,我想跟踪它,还有一个 "is_available" 布尔值告诉我 ip 的状态是否可用(应该自行设置自动,基于 "status" 字段)。
所以问题是,例如,
我访问模型,编辑记录,将 :status 从 :available 更改为 :allocated,然后点击 "Save",它回滚,提升我 "Ip failed to be updated",并在服务器上事务是“已完成 406 不可接受”
这是日志:
=============== 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)
这是我的 Gemfile(除了默认的之外只有额外的 gem):
# 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'
感谢您的宝贵时间!
不确定这是否是导致问题的原因,但可能是。如果任何方法执行为 before_save
returns false,整个事务将中止。
你的方法:
def set_availability
self.is_available = false unless self.status.available?
end
将 return 为假或为零。第一种情况将取消交易。将此方法更改为:
def set_availability
self.is_available = false unless self.status.available?
true
end
由于您在 set_availability 中设置了一个假值,回调会返回一个假值并回滚。 returns false 的 before* 回调将回滚模型上的所有更新。
来自 Rails 文档 http://guides.rubyonrails.org/active_record_callbacks.html
6 Halting Execution
As you start registering new callbacks for your models, they will be queued for execution. This queue will include all your model's validations, the registered callbacks, and the database operation to be executed.
The whole callback chain is wrapped in a transaction. If any before callback method returns exactly false or raises an exception, the execution chain gets halted and a ROLLBACK is issued; after callbacks can only accomplish that by raising an exception.
类似这样的方法可能有效。
def set_availability
self.is_available = false unless self.status.available?
true
end