Проблемы с сохранением объекта в массиве, проблемы с Ruby и Rails - PullRequest
23 голосов
/ 29 января 2011

Я пытаюсь добавить объект в мой массив, однако массив, кажется, всегда сбрасывается, а не добавляется.Что я делаю неправильно?Я думаю, что это связано с if(defined? libraryshelf) then, что я пытаюсь сделать здесь, это выяснить, существует ли массив или нет (если это первое добавление или нет) ..

def add_book
  @listofbooks ||= Array.new
  @listofbooks.push(params[:booktitle])
  @listofbooks
  respond_to do |format|
    format.html { redirect_to(:back) }
    format.js
  end
end

myфайл add_book.js.erb

alert('<%= @listofbooks %>');

@listofbooks показывает только название книги, которую я добавил в последний раз ..

Ответы [ 3 ]

34 голосов
/ 29 января 2011

TL; DR: Контроллеры не имеют состояния, они просто видят входящий запрос.Для того чтобы список пережил текущий запрос, необходимо сохранить список либо в сеансе, либо в базе данных, в зависимости от того, как долго вы хотите, чтобы он работал, и других соображений.

Существуют и другие проблемы..

Не использовал defined? для этого, на самом деле, не используйте defined? ни для чего.Он не имеет много законных применений на уровне приложений.В этом случае libraryshelf является локальной переменной, и при первой ссылке в методе она не всегда будет определена.

Работайте непосредственно с @listofbooks и просто отметьте @listofbooks or @listofbooks.nil?.

Вот несколько рабочих (я думаю) версий ...

def add_book name
  @listofbooks = [] unless @listofbooks
  @listofbooks << name
end

def add_book name
  @listofbooks ||= []
  @listofbooks << name
end

def add_book name
  @listofbooks = @listofbooks.to_a.push name # yes, works even if @listofbooks.nil?
end

Ага, ваш исправленный пост лучше ... как отмечено в TL; DR: поскольку Rails воссоздает объекты контроллера при каждом запросе,вам нужно будет сохранять все, что вы захотите, в следующий раз в своей сессии или базе данных.

Оригинальный пост обманул нас также забиванием @listofbooks каждый раз с помощью метода, поэтомуЯ подумал, что это действительно рубиновый вопрос.

6 голосов
/ 29 января 2011

, поскольку вы находитесь в функции, libraryshelf никогда не будет определяться как локальная переменная.И я предполагаю, что вы используете Ruby 1.8.7, поэтому вы создаете новый массив в области видимости (который вы не должны видеть) и назначаете его для @ listofbooks

Я предлагаю

def add_book
    @listofbooks ||= Array.new
    @listofbooks.push(name)
    @listofbooks # return the entire list, not the last thing pushed
end

Изменить, чтобы отразить обновленный вопрос

Это проблема жизненного цикла контроллера.Для каждого запроса создается новый объект контроллера, поэтому любые @variables очищаются между запросами.Вам нужно будет сохранить ваши переменные в что-то вроде session[:booklist] = @booklist, а затем получить их для следующего запроса.

1 голос
/ 29 января 2011

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

# Create an Empty Array, assign it to @listofbooks
@listofbooks ||= Array.new

# Add the name of a book from a request parameter
@listofbooks.push("Agile Development with Rails")

# At this point @listofbooks only contains 1 element; we started with 
# an empty array and added 1 element through the request parameter

Однако, похоже, вы хотите сделать следующее:

def add_book
   # Simply push the new book title on the array of old books
   @listofbooks << params[:booktitle] 
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...