Как будут выглядеть геттер и сеттер по умолчанию в рельсах?

Я знаю, что могу написать attr_accessor :tag_list, чтобы создать виртуальный атрибут tag_list для объекта в Rails. Это позволяет использовать атрибут tag_list в формах для объекта.

Если я использую attr_accessor :tag_list, я могу в модели выполнять действия над tag_list для извлечения данных из формы и управления ими.

Что я хочу знать, так это то, что вместо того, чтобы писать attr_accessor, как мне написать геттер и сеттер, которые бы полностью воспроизводили функциональность attr_accessor по умолчанию. НАПРИМЕР:

def tag_list
    #what goes here
end

К вашему сведению, я пробовал

 def tag_list
     @tag_list
 end

Это не работает.


person jay    schedule 08.01.2012    source источник
comment
приведенный ниже ответ правильный. def tag_list — это метод доступа, он должен возвращать tag_list, поэтому возвращайте @tag_list. Поскольку ruby ​​всегда возвращает последний оператор, вы можете пропустить возврат и просто сказать \@tag_list, чтобы вернуть \@tag_list.   -  person daniel    schedule 08.01.2012
comment
Вы нашли свое решение? У меня есть аналогичная проблема в stackoverflow.com/questions/19198679/, где мой сеттер никогда не запускается.   -  person thomasb    schedule 21.12.2013


Ответы (2)


attr_accessor — это встроенный метод Ruby, не имеющий особого значения в контексте ActiveRecord. attr_accessor :tag_list в основном эквивалентен этому коду:

# getter
def tag_list
  @tag_list
end

# setter
def tag_list=(val)
  @tag_list = val
end

Однако в моделях ActiveRecord может потребоваться что-то вроде этого:

def tag_list
  self[:tag_list]
end

def tag_list=(val)
  self[:tag_list] = val
end

Есть небольшая разница: в первом методе obj[:tag_list] не использует то же хранилище, что и ваш геттер и сеттер. С последним так и есть.

Объяснение концепции геттера/сеттера

В Ruby следующие две строки кода эквивалентны

thing.blabla
thing.blabla()

Оба вызывают метод blabla объекта thing и оценивают последнее выражение, вычисленное в этом методе. Это означает, что вам также не нужен оператор return в случае вышеуказанного метода получения, потому что метод просто возвращает последнее выражение в методе (@tag_list, значение переменной экземпляра).

Кроме того, эти две строки кода эквивалентны:

thing.blabla=("abc")
thing.blabla = "abc"

Оба вызывают метод blabla= объекта thing. Специальное имя с символом = можно использовать как любое другое имя метода.

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

def price_in_dollar
  @price_in_euro * 0.78597815
end

def price_in_dollar=(val)
  @price_in_euro = val / 0.78597815
end
person Niklas B.    schedule 08.01.2012
comment
какая разница, что я пишу в качестве аргумента в сеттере? или это просто def tag_list=(что угодно); @tag_list = что угодно; конец ? - person jay; 08.01.2012
comment
@jay: Нет, это не имеет значения. Кроме того, это не специфично для Rails, это вещь Ruby. Я отредактировал ваш вопрос, чтобы отразить это. - person Niklas B.; 08.01.2012
comment
@jay: я обновил ответ, добавив дополнительную информацию, ПОЧЕМУ это работает. - person Niklas B.; 08.01.2012
comment
Никлас, извините, если я не понял - мне действительно нужно, чтобы это работало в контексте рельсов. это html-форма, которая отправляется, и я не могу получить значения из атрибута tag_list. Этот ответ не работает. Мне бы очень хотелось, чтобы tag_list принимался из params[:object][:tag_list] - person jay; 08.01.2012
comment
Я думаю, что ваши правки - правильный путь... но я все еще не могу получить доступ к section_list из других методов в моей модели. Возможно ли, что отсутствует что-то еще, что устанавливает атрибут rails attr_accessor? - person jay; 08.01.2012
comment
@jay: Нет, на самом деле attr_accessor не переопределяется Rails (так что это будет эквивалентно моему первому примеру кода). Вы говорите, что attr_accessor работает нормально, но не тот первый пример кода? - person Niklas B.; 08.01.2012
comment
да, это так.. attr_accessor работает, ваш код нет - tag_list равен нулю в случае попытки использовать ваш код - person jay; 08.01.2012
comment
@jay: я с трудом могу в это поверить. Вы пытаетесь получить доступ к атрибуту с помощью obj[:tag_list]? Это не будет работать ни с attr_accessor, ни с предоставленным мной геттером и сеттером (я только что проверил его в консоли Rails, чтобы быть уверенным). Можете ли вы вставить некоторый (пожалуйста, только соответствующий) код на pasteie.org, чтобы показать мне проблему? - person Niklas B.; 08.01.2012
comment
Привет, Никлас, пожалуйста, знай, что я очень благодарен тебе за помощь в этом. Большое Вам спасибо. Я стараюсь быть как можно более сговорчивым. Не знаю каким кодом поделиться. Я пишу точно тот же код, что и вы, в моей модели, и у меня есть проверка, подтверждающая :tag_list, :presence =› true. Эта проверка не пройдена, что указывает на то, что tag_list никогда не читается контроллером при отправке формы. - person jay; 08.01.2012
comment
@jay: я не могу это воспроизвести, это должно работать. См. рабочий пример для Rails 3.1.3 на pastie.org/3146488. Извините, но уже поздно, я не думаю, что смогу тратить на это больше времени, поэтому не могли бы вы принять этот ответ? Если у вас есть еще проблемы, вы, вероятно, захотите открыть новый вопрос с каким-то реальным кодом, который вызывает у вас проблемы. - person Niklas B.; 08.01.2012
comment
На самом деле есть еще одна вещь, которая пришла мне на ум: если вы используете подобные виртуальные атрибуты, их значения, конечно, не будут сохранены в базе данных, так как нет соответствующего столбца БД. Возможно, вы устанавливаете значение, сохраняете, а затем загружаете запись из какого-то другого места. Это означает, что значение виртуального атрибута будет потеряно. Спокойной ночи. - person Niklas B.; 08.01.2012

При использовании ActiveRecord это эквивалентные версии геттера и сеттера:

def tag_list
  read_attribute(:tag_list)
end

def tag_list=(val)
  write_attribute(:tag_list, val)
end

Это то, что ты искал?

person leonardoborges    schedule 08.01.2012
comment
да - это своего рода, и я почти уверен, что это часть пути. Это почти работает, за исключением того, что по какой-то причине tag_list не может быть доступен другими методами в моей модели. Есть ли что-то еще, что attr_accessor делает, чего здесь не хватает? - person jay; 08.01.2012
comment
Вы делаете tag_list = whatever? Потому что если это так, вы не вызываете сеттер, вы инициализируете локальную переменную. Вместо этого вы бы сделали self.tag_list = whatever. В качестве альтернативы, если у вас возникли трудности с чтением значений из формы, проверьте, предотвращаете ли вы его массовое присвоение, не добавляя его в список attr_accessible .... - person Joshua Cheek; 08.01.2012
comment
Следует отметить, что у меня была проблема с минитестом, из-за которой я не мог записать неизвестный атрибут... ошибки при использовании методов установки, определенных следующим образом (с write_attribute). Когда я только что переключил установщик на установку переменной экземпляра, названной в честь виртуального атрибута, и тесты, и мое веб-приложение работали нормально. stackoverflow.com/questions/31999460/ - person Todd; 17.08.2015