Rails - добавить атрибуты не в модель и обновить атрибут модели - PullRequest
7 голосов
/ 21 февраля 2012

У меня есть 3 поля в моей форме, которых нет в моей базе данных: открытие_типа, открытие_часов, открытие_минут. Я хочу обновить основной атрибут «открытие» (в базе данных) этими 3 полями.

Я перепробовал много вещей, которые не работают.

На самом деле у меня есть:

  attr_accessor :opening_type, :opening_hours, :opening_minutes

  def opening_type=(opening_type)
  end
  def opening_type
    opening_type = opening.split("-")[0] if !opening.blank?
  end

  def opening_hours=(opening_hours)
  end
  def opening_hours
    opening_hours = opening.split("-")[1] if !opening.blank?
  end  

  def opening_minutes=(opening_minutes)
  end
  def opening_minutes
    opening_minutes = opening.split("-")[2] if !opening.blank?    
  end

Я пытался добавить что-то вроде:

  def opening=(opening)
    logger.info "WRITE"

    if !opening_type.blank? and !opening_hours.blank? and opening_minutes.blank?
      opening = ""
      opening << opening_type if !opening_type.blank?
      opening << "-" 
      opening << opening_hours if !opening_hours.blank?
      opening << "-" 
      opening << opening_minutes if !opening_minutes.blank?
    end
    write_attribute(:opening, opening)
  end

  def opening
    read_attribute(:opening)
  end

Но методы доступа не вызываются, и я думаю, что открытие_типа, открытие_часа, открытие_минуты тоже были пустыми, если методы доступа были вызваны ...

Я думаю, что мне не нужен обратный вызов before_save, и я должен сделать это, переписав методы доступа.

Примечания: - Rails 3.0.5, - Открытие_типа,: открытие_часов,: открытие_минут может быть пустым

РЕДАКТИРОВАТЬ: я обновил свой код

Ответы [ 2 ]

16 голосов
/ 21 февраля 2012

Обратите внимание, что attr_reader, attr_writer и attr_accessor - это просто макросы для определения ваших собственных методов.

# attr_reader(:foo) is the same as:
def foo
  @foo
end

# attr_writer(:foo) is the same as:
def foo=(new_value)
  @foo = new_value
end

# attr_accessor(:foo) is the same as:
attr_reader(:foo)
attr_writer(:foo)

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

Другая ваша проблема в том, что ваш opening= метод никогда не вызывается, и это имеет смысл, потому что в вашем коде нет места для его вызова.То, что вы действительно хотите, чтобы ваше открытие было установлено после того, как все отдельные части были установлены.Теперь нет тривиального способа сделать это, но у Rails есть обратный вызов before_validation, куда вы можете поместить код, который запускается после того, как были установлены значения, но до запуска проверки:

class Shop < ActiveRecord::Base

  attr_accessor :opening_type, :opening_hours, :opening_minutes

  before_validation :set_opening

  private
  def set_opening
    return unless opening_type && opening_hours && opening_minutes
    self.opening = opening_type + "-" + opening_hours + "-" + opening_minutes
  end
end
0 голосов
/ 21 февраля 2012

вместо

attr_reader :opening_type, :opening_hours, :opening_minutes

вам нужно

attr_accessor :opening_type, :opening_hours, :opening_minutes
attr_reader :opening_type, :opening_hours, :opening_minutes

ВЧ ...

// Являются ли: открытие_типа,: открытие_часов,: открытие_минуты реальными полями? Если да, то вам просто нужно это?

attr_accessor: открытие attr_reader: открытие

...