1

Как сохранить атрибут на основе условия между атрибутами одной и той же модели? Я не смог обновить запись, если состояние атрибута не остается истинным.Rails 4 - Не удается обновить атрибут модели

Я проверил эту тему раньше: 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» boolean, чтобы сообщить мне, что статус ip доступен или нет (который должен автоматически устанавливаться в зависимости от поля «status»).

Так вопрос, например,

Я доступ к модели, отредактировать запись, изменить: статус от: доступный: выделено, и нажмите «Сохранить», она катится назад, поднимает меня «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 (только дополнительные драгоценные камни, кроме тех, по умолчанию):

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

Спасибо за ваше время!

+0

Вы уверены, что ваш ip или hostname являются uniq? –

+0

Да, у меня есть только две записи для тестовых целей, они оба разные; Я также попытался прокомментировать проверки, и хотя он не отображает «Ip Exists», он все равно дает мне статус 406. –

ответ

4

Не уверен, что это вызывает проблему, но может быть. Если какой-либо метод, выполненный как before_save, возвращает false, вся транзакция прерывается.

Ваш метод:

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

вернет ложь или ноль. Первый случай отменяет транзакцию. Изменить этот метод:

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

Спасибо! Оно работало завораживающе! Также большое спасибо за быстрый ответ! –

1

Поскольку вы устанавливаете ложное значение внутри set_availability, ложное значение получает возвращается из обратного вызова и откатывается назад. A перед * обратным вызовом, который возвращает false, откатит все обновления в модели.

С Rails документы http://guides.rubyonrails.org/active_record_callbacks.html

6 Приостановление исполнения

Как начать регистрацию новых обратных вызовов для моделей, они будут в очередь на выполнение. Эта очередь будет включать все проверки вашей модели , зарегистрированные обратные вызовы и операцию базы данных до .

Вся цепочка обратного вызова завернута в транзакцию. Если какой-либо метод обратного вызова возвращает точно false или создает исключение, цепочка выполнения останавливается и выдается ROLLBACK; после обратных вызовов может быть достигнуто только путем создания исключения.

Что-то вроде этого может работать.

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

Спасибо! На самом деле это была проблема, но для документации! –

+1

Я столкнулся с той же проблемой некоторое время назад, это было ужасно. Парень выше бил меня к нему на несколько минут, поэтому мне пришлось редактировать в какой-то документации, чтобы различать ха-ха – CleoR

Смежные вопросы