2014-10-03 6 views
0

У меня есть URL строка:Извлечение несколько моделей из URL строки

http://localhost:3000/user/event?profile_id=2&profile_type=UserProfile 

Я хочу, чтобы извлечь «2» и «UserProfile», где они могут измениться.

Я пытался использовать оба match и scan но ни возвращает результаты:

url = "http://localhost:3000/user/event?profile_id=2&profile_type=UserProfile" 
m = /http(s)?:\/\/(.)+\/user\/event?profile_id=(\d)&profile_type=(\w)/.match(url) 
=> nil 

url.scan /http(s)?:\/\/(.)+\/user\/event?profile_id=(\d)&profile_type=(\w)/ 
=> [] 

Любая идея, что я могу делать неправильно?

+0

В вашем конкретном регулярном выражении, вам нужно бежать? между событием и profile_id, так что это event \? profile_id, и у вас будет фактический объект MatchData. Теперь вам нужно удалить круглые скобки из (s) и (.) И добавить + в (\ w), чтобы он (\ w +), и вы получите желаемые результаты. – daremkd

+0

Не используйте для этого регулярное выражение. Они слишком хрупкие, чтобы обрабатывать URL-адреса, которые могут изменить порядок. –

ответ

2

Не используйте шаблон, чтобы попытаться это сделать. параметры запроса могут измениться, и не положение зависит, что будет мгновенно разорвать шаблон

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

require 'uri' 

uri = URI.parse('http://localhost:3000/user/event?profile_id=2&profile_type=UserProfile') 

Hash[URI::decode_www_form(uri.query)].values_at('profile_id', 'profile_type') 
# => ["2", "UserProfile"] 

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

profile_id, profile_type = Hash[URI::decode_www_form(uri.query)].values_at('profile_id', 'profile_type') 

Вот промежуточные шаги, так что вы можете увидеть, что происходит:

uri.query # => "profile_id=2&profile_type=UserProfile" 
URI::decode_www_form(uri.query) # => [["profile_id", "2"], ["profile_type", "UserProfile"]] 
Hash[URI::decode_www_form(uri.query)] # => {"profile_id"=>"2", "profile_type"=>"UserProfile"} 
1
match = url.match(/https?:\/\/.+?\/user\/event\?profile_id=(\d)&profile_type=(\w+)/) 
p match.captures[0] #=> '2' 
p match.captures[1] #=> 'UserProfile' 

В вашем выражении:

/http(s)?:\/\/(.)+\/user\/event?profile_id=(\d)&profile_type=(\w)/ 

ВСЕ вы поместите внутрь() захватывается в регулярном выражении. Нет необходимости вставлять s в круглые скобки, потому что? будет действовать только на предыдущем символе. Кроме того, нет необходимости в (.), Потому что, опять же, + будет действовать только на предыдущем символе. Кроме того, (\ w) должен быть (\ w +), который в основном говорит: Один или несколько символов (и 'UserProfile' - 1 или более символов.

+0

Так что же я пропустил только вторую группу, не снимающую пленку? – Donato

+0

см. Мой обновленный ответ. – daremkd

+0

«ВСЕ, что вы положили внутрь(), захватывается в Ruby». Это не Ruby, это верно для регулярных выражений. Как только вы увидите '(? ...)' скобки становятся не захватывающими. –