Ruby (Rails) манипулирование строками при создании - PullRequest
2 голосов
/ 28 декабря 2011

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

in_reply_to - это идентификатор пользователя, помеченного в Micropost.

Это в моем Micropost_controller.rb

@reply_regex = /(\A@[^@ ]+(@)\w+(\.[a-z]{2,3}){1,2}.*\z)/i
def create
  @micropost = current_user.microposts.build(params[:micropost])
  if @micropost.content =~ @reply_regex
    email = @micropost.content.scan(/([^@ ]+(@)\w+(\.[a-z]{2,3}){1,2})/i).first.first
    @micropost.in_reply_to = User.find_by_email(email).id
  end
  if @micropost.save 
    flash[:success] = "Micropost created!"
    redirect_to root_path

Когда я запускаю часть для извлечения электронной почты настрока в консоли работает отлично и возвращает электронное письмо.Но когда я создаю новые микросообщения, in_reply_to всегда остается равным нулю.

1 Ответ

1 голос
/ 28 декабря 2011

Примерно так:

class C
  @a = 11
end

делает не создание переменной экземпляра с именем @a для экземпляров C.Когда вы нажмете @a = 11, self будет сам класс, поэтому @a будет переменной экземпляра для объекта C.Если вы поместите вышеупомянутое в irb и посмотрите на C.instance_variables, вы увидите это:

>> C.instance_variables
=> [:a]

, но когда вы посмотрите на экземпляр C:

>> C.new.instance_variables
=> []

Кроме того, переменные экземпляра автоматически создаются при первом использовании и инициализируются как nil.

Объединение вышесказанного говорит нам о том, что в имеется переменная экземпляра @reply_regex.класс объект MicropostController но не в экземплярах.Ваш def create является методом экземпляра, поэтому он будет использовать переменную экземпляра @reply_regex;но у вас нет @reply_regex в качестве переменной экземпляра для MicropostController объектов, поэтому она будет создана и инициализирована как nil внутри вашего оператора if.В результате ваш if в конечном итоге будет иметь следующий вид:

if @micropost.content =~ nil

и @micropost.content =~ nil оценятся в nil и, поскольку nil ложно в логическом контексте, блок ifникогда не вводится и @micropost.in_reply_to никогда не присваивается значение.

Вы можете использовать переменную класса для своего регулярного выражения:

@@reply_regex = /(\A@[^@ ]+(@)\w+(\.[a-z]{2,3}){1,2}.*\z)/i
def create
  @micropost = current_user.microposts.build(params[:micropost])
  if @micropost.content =~ @@reply_regex
    #...

, поскольку переменные класса видимы для методов экземпляра или, лучше,просто используйте константу:

REPLY_REGEX = /(\A@[^@ ]+(@)\w+(\.[a-z]{2,3}){1,2}.*\z)/i
def create
  @micropost = current_user.microposts.build(params[:micropost])
  if @micropost.content =~ REPLY_REGEX
    #...

В качестве отступления, я думаю, вам следует перенести проверку ответа на вашу модель.Вы можете использовать обратный вызов before_validation, чтобы убрать любые начальные и конечные пробелы в content, извлечь и сохранить ответ на:

class Micropost < ActiveRecord::Base
  before_validate :process_content, :if => :content_changed?
  #...
  private
  def process_content
    # Strip leading/trailing whitespace from self.content
    # Extract the reply-to from self.content and save it in self.in_reply_to
  end
end

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...