How to enable :tsearch dictionary for pg_search multi-search? - ruby-on-rails

I'm adding pg_search into a Rails app. I'm following the instructions on github and this railscast, but I've run into a problem.
I'm setting up a multi model search, and I have a basic implementation working. But I want to extend pg_seach to use its English dictionary.
I already have an initializer:
PgSearch.multisearch_options = {
:using => [:tsearch,:trigram],
:ignoring => :accents
}
So, from what I've read, it looks like adding the dictioary should be as simple as
PgSearch.multisearch_options = {
:using => [:tsearch => [:dictionary => "english"],:trigram],
:ignoring => :accents
}
But when I start my server
...config/initializers/pg_search.rb:2: syntax error, unexpected ']', expecting tASSOC (SyntaxError)
:using => [:tsearch => [:dictionary => "english"],:trigram],
I've tried swapping square for curly brackets, and all the other syntax permutations I can think of, but no luck.
What is the correct syntax here? And why aren't my attempts valid, as I've followed the syntax for scoped searches?

What you posted is not valid Ruby syntax.
You want something like this:
PgSearch.multisearch_options = {
:using => {
:tsearch => {
:dictionary => "english"
},
:trigram => {}
},
:ignoring => :accents
}
The reason is that you must use a Hash if you want to have key-value pairs. So essentially, pg_search allows 2 syntaxes:
:using => someArray # such as [:tsearch, :trigram]
which means "use tsearch and trigram, both with the default options"
or
:using => someHash # such as {:tsearch => optionsHash1, :trigram => optionsHash2}
which means "use tsearch with some options from optionsHash1, and use trigram with some options from OptionsHash2"
Let me know if there's anything I can do to clarify. It's pretty basic Ruby syntax, but I understand that the fact that pg_search accepts both formats can be confusing to those who aren't as familiar.

Related

Rails route not working - not sure why

Having a routing issue, should be really simple but seems straightforward and just not working:
match '/api/get-locations-by-distance/:latitude/:longitude' => 'api#get_locations_by_distance'
with this call:
http://localhost:3000/api/get-locations-by-distance/34.035645/-118.233434
thx for any ideas
edit #1
If I update it to the following:
match '/api/get-locations-by-distance/:latitude/:longitude/:stub' => 'api#get_locations_by_distance'
and
http://localhost:3000/api/get-locations-by-distance/34.035645/-118.233434/stub
It still doesn't work.
edit #2
I tried adding the :format => false but this doens't seem to help either.
match '/api/get-locations-by-distance/:latitude/:longitude' => 'api#get_locations_by_distance', :format => false
with
http://localhost:3000/api/get-locations-by-distance/34.035645/-118.233434
It thinks that .233434 is format
It's like Mik_Die said - the . is the delimiter for the format in Rails.
Here is a work-around: you can specify your own segmentation constraint.
match '/api/get-locations-by-distance/:latitude/:longitude' => 'api#get_locations_by_distance' ,
:constraints => { :latitude => /\d+\.\d+/ , :longitude => /\d+\.\d+/ }
See also:
http://x3ro.de/rails-3-routing-parameters-dots/

Should I escape the condition for my rails find?

OK so i have this condition
conditions = {}
conditions[:state] = params[:state] if params[:state]
#apps = current.apps.paginate(:include => :user, :conditions => conditions, :order => "users.first_name, users.last_name")
and my routes file has
map.apps_wishlist '/apps/wishlist', :controller => 'apps', :action => 'index', :state => 'wishlist'
Since i am sending in the string should i escape the sql somehow for security reasons and if so how is the best way to do that
Someone suggested they think the params[:state] should be escaped when put into the SQL query for security reasons
They don't know what they're talking about. As long as you do either
SomeModel.where(:conditions => {:state => params[:state]})
#or
SomeModel.find(:conditions => {:state => params[:state]})
#or
SomeModel.where("state = ?", params[:state])
ActiveRecord will handle all the escaping itself, so the code you've given above is fine/ The only case it doesn't cover is if you were building up the sql entirely on your own, i.e. don't do
SomeModel.where("state = #{params[:state]}")
If you're using find_by_sql, execute and so on then you are also responsible for escaping. Don't just take my word for it though - try it! You might also want to look at the rails security guide

How to Detect an Integer in Rails 3 Routes?

I would like to do just a little bit of extra logic in rotues.rb, that probably doesn't belong there, but it seems to make the most sense to me.
I have two conflicting routes. To be primitive:
match '/videos/:browseby' => 'videos#browse', :as => "browse_by"
Where :browseby is looking for a string, such as "Tags", to browse videos by tags.
However, (and most probably saw this coming) I also have my basic show resource (again in primitive form):
match '/videos/:id' => 'videos#show', :as => "video"
Where :id is looking for the integer for the video ID.
Is there a way to add a small bit of logic such as...
match '/videos/:id' => 'videos#show', :as => "video", :format(:id) => :integer
(Which is my hypothetical rails syntax, to help show what I'm looking for.)
I know I can munch this in the Controller level, but it makes more sense to me to handle it at the route level.
You could try using :constraints and a regex:
match '/videos/:id' => 'videos#show', :as => "video", :constraints => { :id => /\d/ }
match '/videos/:browseby' => 'videos#browse', :as => "browse_by"
You'll also want to make sure the looser :browseby version comes after the :id version. Note that regex constraints are implicitly anchored at the beginning so that would work as long as your :browseby values didn't start with a number.
If you have tags that do start with numbers then you could use an object for the constraint and then you could include anchors in your regex:
class VideoIdsOnly
def matches?(request)
request.path =~ %r{\A/videos/\d+\z}
end
end
match '/videos/:id' => 'video#show', :as => "video", :constraints => VideoIdsOnly.new
match '/videos/:browseby' => 'videos#browse', :as => "browse_by"

Rails 3 routing constraints don't seem to be matching the regex properly

I am using Rails 3.0.5 and I have setup a route using a regex constraint. It used to work on Rails 2.3.5, but it's not working in Rails 3. The route looks like this:
get '/:version_id' => 'pastes#show', :constraints => { :version_id => /[\d\w]{40}/ }
It doesn't work at all. However, the following work:
get '/:version_id' => 'pastes#show', :constraints => { :version_id => /.{40}/ }
get '/:version_id' => 'pastes#show', :constraints => { :version_id => /\w{40}/ }
get '/:version_id' => 'pastes#show'
Is there something wrong with the way Rails handles [ ] matching? or am I doing something wrong?
version_id usually looks something like this:
816616001d7ce848944a9e0d71a5a22d3b546943
I don't have a solution as to why one may not work over the other.
However, according to the PickAxe book, \w is actually a superset of \d.
\w [A-Za-z0-9\_] ASCII word character
\d [0-9] ASCII decimal digit character
Therefore, [\d\w]{40} is no different from \w{40}, which works for you.

map.resource, parameter restrictions

I've a controller :platform here.
I'm trying to do something like:
/:platform_name/ to redirect to its show, with the parameter. Here is what I've got:
map.resource :platform,
:as => ':platform_name',
:platform_name => /pc|ps2|ps3|wii|ds|psp|xbox-360/
It's working fine. I've other neasted resources to it, and all them are accessing. But.
The problem is, I've only those platform names, but when it doesnt fine another route, it aways fall on this.
if I try /whatever/, it will look for the platform_name => whatever.
I was expecting it to fall into the map.connect ':controller/:action/:id' rule.
When I did :platform_name => /pc|ps2|ps3|wii|ds|psp|xbox-360/, wasnt expected that this rule only apply when the regular expression is fit?
how could i restrict this?
Try changing:
/pc|ps2|ps3|wii|ds|psp|xbox-360/
to
/^(pc|ps2|ps3|wii|ds|psp|xbox-360)$/
Maybe you could try
:requirements => { :platform_name => /pc|ps2|ps3|wii|ds|psp|xbox-360/ }
or
:conditions => { ... }
ActionController::Resources#resources

Resources