Rails Выберите логическое значение со значением NULL - PullRequest
3 голосов
/ 16 августа 2011

Первая среда:

Rails 2.1.0, Ruby 1.8.7, Mysql 5.1.54, Ubuntu 11.04

В моей таблице есть логическое поле, которое начинается с NULL, но я не могу найти хороший способ установить на NULL. (Это поле в основном является полем да / нет / без ответа, для которого true / false / null кажется подходящим. Клиент определенно сказал, что хотел бы, чтобы оно оставалось пустым (без ответа).)

Вот моя миграция (конкретные имена заменены):

class AddQuestionToClients < ActiveRecord::Migration
    def self.up
        add_column :clients, :question, :boolean
    end
    def self.down
        remove_column :clients, :question
    end
end

Мой контроллер использует базовый

@client = Client.find(params[:id])
@client.update_attributes(params[:client])

В моем представлении есть селектор (я думаю, что это вызывает проблему, он никогда не был великолепен с выборами помощника формы):

<%= f.select :question, [["Yes", true], ["No", false]], { :include_blank => true, :selected => @client.question } %>

При выборе да, true передается; нет, ложь пройдена; пусто, "" передается. Но, похоже, "" автоматически обновляется до false при обновлении базы данных.

Чтобы обойти это, я делаю это:

params[:client][:question] = (params[:client][:question] == "")? nil : params[:client][:question]

Но это не может быть правильным способом сделать это. Чего мне не хватает?

Ответы [ 6 ]

2 голосов
/ 31 октября 2014

Я просто столкнулся с той же проблемой и решил ее, превратив атрибут в пустое значение.В вашем случае я бы добавил метод к вашему классу модели.

class Client < ActiveRecord::Base
  def question=(value)
    value = nil if value == ''
    super(value)
  end
end

Это работает как для создания, так и для обновления.(Я использую Rails 2.0.5.)

1 голос
/ 10 марта 2013

У меня была та же проблема, мне нужно было нулевое значение по умолчанию, чтобы логическое значение представляло "неотвеченный"

В Rails 3.2, когда я передаю "" для логического значения (пустой параметр), задается для столбца значение NULL в дБ.

Итак, проблема решена с более новой версией рельсов:)

1 голос
/ 16 августа 2011
<%= f.select :question, options_for_select([["Yes", true], ["No", false]], :question) %>
0 голосов
/ 06 декабря 2017

Это не упоминалось в предыдущих постах, но в Rails 5 это должно работать, если вы хотите назвать nil-опцию

<%= f.select :question, [["Yes", true], ["No", false]], { :include_blank => 'Name this whatever you want, it will be nil when submitted', :selected => @client.question } %>

Протестировано на моем собственном проекте

0 голосов
/ 07 июня 2013

@ vdaubry Я бы только добавил, что это на самом деле не решается .. он замаскирован, потому что вы используете 'select' в вашем пользовательском интерфейсе.Если вы достаточно глупы, чтобы использовать чекбоксы, как я (в конце концов, они булевы, верно?), Тогда ваше симпатичное значение по умолчанию nil в БД, которое мы хотим обозначить как «неизвестный», преобразуется в «ложь», когда отображается вview и преобразуется в false в БД, даже если он не обновляется в представлении, так же, как было описано выше.Другими словами, немного хрупко продолжать полагаться на 3-е значение для «логического», чтобы быть последовательным.

Кроме того, если вы когда-либо сообщаете об этом атрибуте, ваш отчетный код не может легко определить значения в БД, если «неизвестно» является допустимым значением и скрыто.

Поэтому я решил провести рефакторингвсе мои логические значения делают их строками («да», «нет», «неизвестно») и используют переключатели в представлениях.Обратите внимание, что это имеет значение только для таких вещей, как пользовательский интерфейс для сбора данных, когда пользователь не может узнать правду, поэтому статистически это имеет большое значение, если он «неизвестен».

0 голосов
/ 16 августа 2011

Я думаю, что вы можете сделать это только на стороне сервера, потому что когда данные публикуются, они всегда не равны нулю. Так что ваше решение верное.

Если вы хотите избежать этого уродливого кода, вы можете сделать небольшую хитрость на стороне клиента, используя javascript. Фактически, если вы используете отключенный элемент вместо пустого значения, это значение не будет опубликовано, и вы получите nil на стороне сервера.

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

Чтобы отключить элемент с помощью jQuery, вы можете увидеть эту ссылку . Итак, если ваша форма имеет #form идентификатор, вы можете использовать этот код

$(function() {
  $('#form').submit(function () {
    if ($('question-selector').val() == "") {
      $('question-selector').attr('disabled', true);
    }
  })
});
...