2011-12-27 12 views
2

私は練習のためにツイッターのようなアプリで作業しています。ユーザーは投稿を作成し、ユーザーが自分の投稿の先頭にタグを付けるユーザーの@emailを置くことで、ユーザーが投稿の他のユーザーにタグを付けることができるように機能を追加しています。作成時のRuby(Rails)文字列操作

in_reply_toは、Micropostでタグ付けされるユーザーのIDです。私はそれが完璧に動作し、電子メールを返すコンソール内の文字列上の電子メール抽出部を実行すると

これは私のMicropost_controller.rb

@reply_regex = /(\[email protected][^@ ]+(@)\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は常にゼロにとどまります。このような

+0

どのようなテストフレームワークを使用していますか? –

+0

ユーザーは投稿をどのように入力していますか?リッチエディターの場合は、パラメーターをHTMLにする可能性が高くなります。 @ micropost.contentに何が含まれているかを確認するためにログに記録してみてください。初めのちょうど1つのスペースが今のようにあなたのロジックを台無しにするでしょう。 – froderik

+0

@froderik: '@ micropost.content'が何を含んでいるかは関係ありません。' @ reply_regex'は 'nil'、' x =〜nil'はfalseになります。 –

答えて

1

何か:

class C 
    @a = 11 
end 

Cのインスタンスの@aという名前のインスタンス変数を作成しませありません。 @a = 11を押すと、がクラスそのものになるので、@aはオブジェクトCのインスタンス変数になります。あなたはirbに上記入れるとC.instance_variablesを見れば、あなたはこの表示されます。

>> C.instance_variables 
=> [:a] 

をしかし、あなたはCのインスタンスを見ると:また

>> C.new.instance_variables 
=> [] 

、インスタンス変数は、自動的に最初に作成され使用し、nilに初期化されます。

上記を組み合わせると、クラスオブジェクトMicropostControllerには@reply_regexインスタンス変数があり、インスタンスには含まれていないことがわかります。 def createはインスタンスメソッドなので、@reply_regexインスタンス変数を使用します。 MicropostControllerオブジェクトのインスタンス変数として@reply_regexがないため、ifステートメント内にnilという名前で作成され、初期化されます。

if @micropost.content =~ nil 

@micropost.content =~ nilnilはブールコンテキストではfalseで、ifブロックが入力されることはありませんし、@micropost.in_reply_toに値が割り当てられることはありませんから、nilに評価します:結果は、あなたのifが、このされて終わるということです。

あなたの正規表現のためのクラス変数を使用することができます。私は、脇として

REPLY_REGEX = /(\[email protected][^@ ]+(@)\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 = /(\[email protected][^@ ]+(@)\w+(\.[a-z]{2,3}){1,2}.*\z)/i 
def create 
    @micropost = current_user.microposts.build(params[:micropost]) 
    if @micropost.content =~ @@reply_regex 
    #... 

が良く、ちょうど定数を使用して、インスタンスメソッドに表示されていますか返信先チェックをモデルに移すべきだと思います。あなたはcontent内の任意の先頭と末尾の空白を取り除くためにbefore_validationコールバックを使用して抽出し、返信先を救うことができる:

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コンソール、ユーザーに何かを通知しているシステムタスクなど)でも、すべての作業は完了です。