2009-05-21 4 views
1

私はその地獄のために何かを掃除しようとしており、それについてもっと良い方法を模索しています。私のルールで文字列を解析するための正規表現を使うのではなく、ルート構文 "something /:searchitem/somethingelse"に近いものを使いたいと思っています。 "/ something/FOUNDIT/somethingelse "あなたは結果" FOUNDIT "を得るでしょう。ルビーの文字列からトークンをパースするための明確な方法

私がリファクタリングしている例は次のとおりです。 入力文字列を指定すると、「http://claimid.com/myusername」と表示されます。私は可能性のある一致の数に対してこの文字列を実行し、 "myusername"を返すことができます。それを実行するための

データは次のようになります。

PROVIDERS = [ 
    "http://openid.aol.com/:username", 
    "http://:username.myopenid.com", 
    "http://claimid.com/:username", 
    "http://:username.livejournal.com"] 

    something_here("http://claimid.com/myusername") # => "myusername" 

このリストにhttp://claimid.com/myusernameのような文字列をマッチングし、結果の意味を作る何かいい方法は?またはこれのような何かを簡単にするテクニックですか?私はこのようなことをしているので、配線コードを調べていましたが、これは一番簡単なコードではありません。


今私は正規表現でこれをやっているが、上記の方法は、文字列include?またはindexについて

PROVIDERS = [ 
    /http:\/\/openid.aol.com\/(\w+)/, 
    /http:\/\/(\w+).myopenid.com/, 
    /http:\/\/(\w+).livejournal.com/, 
    /http:\/\/flickr.com\/photos\/(\w+)/, 
    /http:\/\/technorati.com\/people\/technorati\/(\w+)/, 
    /http:\/\/(\w+).wordpress.com/, 
    /http:\/\/(\w+).blogspot.com/, 
    /http:\/\/(\w+).pip.verisignlabs.com/, 
    /http:\/\/(\w+).myvidoop.com/, 
    /http:\/\/(\w+).pip.verisignlabs.com/, 
    /http:\/\/claimid.com\/(\w+)/] 

url = "http://claimid.com/myusername" 
username = PROVIDERS.collect { |provider| 
    url[provider, 1] 
}.compact.first 

答えて

4

Elazarがこれまでに提案したように、正規表現を生成することをお勧めします。そして、このような何かが働くだろう:(ユーザー名):あなただけの一つのフィールドに一致している場合

PROVIDERS = [ 
    "http://openid.aol.com/:username/", 
    "http://:username.myopenid.com/", 
    "http://:username.livejournal.com/", 
    "http://flickr.com/photos/:username/", 
    "http://technorati.com/people/technorati/:username/", 
    "http://:username.wordpress.com/", 
    "http://:username.blogspot.com/", 
    "http://:username.pip.verisignlabs.com/", 
    "http://:username.myvidoop.com/", 
    "http://:username.pip.verisignlabs.com/", 
    "http://claimid.com/:username/" 
] 

MATCHERS = PROVIDERS.collect do |provider| 
    parts = provider.split(":username") 
    Regexp.new(Regexp.escape(parts[0]) + '(.*)' + Regexp.escape(parts[1] || "")) 
end 

def extract_username(url) 
    MATCHERS.collect {|rx| url[rx, 1]}.compact.first 
end 

それは、独自のコードと非常によく似ています、プロバイダーのリストだけは、それが簡単に維持し、追加すること、非常にクリーンであります必要に応じて新しいプロバイダ。

+0

素晴らしいです。ロットの少ないコードで読みやすい。 – AdamFortuna

2

方法を読み取ることがはるかに容易になるように思えますか?

url.include? "myuserid" 

または、ポジティブなものが欲しいですか?その場合は、splitのURLを使用できます。

はい:第3の考え:入力フォームを:usernameと一緒に使用して、このような文字列ごとにRegexpを構築してコンパイルし、Regexp#matchを使用してMatchDataを返します。 Regexpのペアと:usernameフィールドのインデックスを保持していれば、直接行うことができます。

+0

この場合、通常の古いインクルードは使用できません。私は "http://claimid.com/myusername"と入力し、それから出力 "myusername"が必要です。問題は、入力が "http://myusername.blogspot.com"のような何かになる可能性があり、私は依然として出力 "myusername"を望むということです。基本的にopenid URLのユーザ名部分を見つける。 openid URLは何でもかまいませんが、見つからない可能性があります。 「第3の思考」のように聞こえるのは、私が下の例でもやっていることです。すべての潜在的な文字列を実行し、それぞれの "username"部分を取得し、nilsをクリアして最初の文字列を返します。 – AdamFortuna

1

私はまだ正規表現が解決策になると思います。しかし、ルーティングのような文字列から正規表現を作成するコードを書く必要があります。コード例:

class Router 
    def initialize(routing_word) 
     @routes = routing_word.scan /:\w+/ 
     @regex = routing_word 
     @regex.gsub!('/','\\/') 
     @regex = Regexp.escape(@regex) 
     @regex.gsub!(/:\w+/,'(\w+)') 
      @regex = '^'[email protected]+'$' 
     @regex = Regexp.new(@regex) 
    end 
    def match(url) 
     matches = url.match @regex 
     ar = matches.to_a[1..-1] 
     h = {} 
     @routes.zip(ar).each {|k,v| h[k] = v} 
     return h 
    end 
end 

r = Router.new('|:as|:sa') 
puts r.match('|a|b').map {|k,v| "#{k} => #{v}\n"} 

ルーティング文字列ごとにルータを使用します。これは、URLコロン文字列を実際のURLコンポーネントに一致させる素敵なハッシュテーブルを返すべきです。

指定されたURLを認識するためには、すべてのルーターを通過し、どのURLが指定されているかを確認する必要があります。

class OpenIDRoutes 
    def initialize() 
     routes = [ 
      "http://openid.aol.com/:username/", 
      "http://:username.myopenid.com/", 
      "http://:username.livejournal.com/", 
      "http://flickr.com/photos/:username/", 
      "http://technorati.com/people/technorati/:username/", 
      "http://:username.wordpress.com/", 
      "http://:username.blogspot.com/", 
      "http://:username.pip.verisignlabs.com/", 
      "http://:username.myvidoop.com/", 
      "http://:username.pip.verisignlabs.com/", 
      "http://claimid.com/:username/" 
     ].map {|x| Router.new x} 
    end 

    #given a URL find out which route does it fit 
    def route(url) 
     for r in routes 
      res = r.match url 
      if res then return res 
     end 
    end 

r = OpenIDRoutes.new 
puts r.route("http://claimid.com/myusername") 

私はこれがレールのルーティングの大部分をうまく簡単に実装していると思います。

1

URIは少しですが、標準ライブラリにはURIがあります。split():

require 'uri' 

URI.split("http://claimid.com/myusername")[5] # => "/myusername" 

何とかそれを使用できるかもしれません。

C.J.

関連する問題