1

同じモデルの属性間の条件に基づいて属性を保存するにはどうすればよいですか? 属性の状態が true のままでない限り、レコードを更新できませんでした。

以前にこのスレッドをチェックしました: Rails. 保存時にモデル属性を更新

これは私が実行しているコードです:

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」のリストと、IPのステータスが利用可能かどうかを示す「is_available」ブール値があります(「ステータス」フィールドに基づいて自動的に設定されます) )。

問題は、たとえば、

モデルにアクセスし、レコードを編集し、:status を :available から :allocated に変更し、[保存] をクリックすると、ロールバックし、「IP を更新できませんでした」というメッセージが表示され、サーバー上でのトランザクションは「完了 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'

お時間をいただきありがとうございます!

4

2 に答える 2

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
于 2015-08-04T13:12:26.217 に答える
1

set_availability 内で false の値を設定しているため、コールバックから false の値が返され、ロールバックされます。false を返す before* コールバックは、モデルのすべての更新をロールバックします。

Rails ドキュメントからhttp://guides.rubyonrails.org/active_record_callbacks.html

6 実行停止

モデルの新しいコールバックの登録を開始すると、それらは実行のためにキューに入れられます。このキューには、モデルのすべての検証、登録されたコールバック、および実行されるデータベース操作が含まれます。

コールバック チェーン全体がトランザクションにラップされます。before コールバック メソッドが正確に false を返すか、例外を発生させた場合、実行チェーンは停止し、ROLLBACK が発行されます。コールバックの後は、例外を発生させることによってのみそれを達成できます。

このようなものがうまくいくかもしれません。

def set_availability
  self.is_available = false unless self.status.available?
  true      
end
于 2015-08-04T13:15:20.913 に答える