ActiveRecord find() with negated condition - ruby-on-rails

I can't seem to find a solution to what seems to me like a simple problem.
Sitemap.find(:all, :conditions => { :controller => 'sample', :action => '!index' })
Now obviously the ! in 'index' doesn't belong there, but I put it there to illustrate that I want any result EXCEPT 'index'. I've tried something like the line below but I've gotten server errors whenever I try it.
Sitemap.find(:all, :conditions => { :controller => 'sample', "action <> 'index'" })

Use the array syntax for this:
Sitemap.all(:conditions => ["controller = ? AND action <> ?", 'sample', 'index']
Hash syntax is only useful if you're checking for equality.

Related

params.merge instead of :overwrite_params gives different URLs

In my old Rails 2.3 application I had something like:
link_to 'Portuguese', url_for(:overwrite_params => { :lang => 'pt' })
which was returning me URLs formatted as:
.../pt
Now that I've upgraded to Rails 3.0 :overwrite_params doesn't work any more, they say params.merge can be used instead to have the same result.
This is true, the page I land to is the same, yet
link_to 'Portuguese', params.merge(:lang => 'pt')
gives me URLs the kind of:
.../?lang=pt
How could I maintain the same URLs as before?
you can use a match statement. In routes.rb file you need to mention something like
get "sign_up/:lang" => "users#new"
I tried this in console
1.9.3-p429 :001 > include Rails.application.routes.url_helpers
1.9.3-p429 :011 > url_for(:only_path => true, :controller => 'users', :action = 'new' , :lang=>'pt')
=> "/sign_up/pt"
In this manner you will pass the parameter lang as '/pt' and not '/?lang=pt'
I had this horrible-looking workaround working:
after defining a matching route
match '(/:lang)', to: 'home#index', as: :home
I create the link to it as:
link_to "Portuguese", URI(request.referer).path + "pt"

Generate the URL for a generic path with possible options in Rails

I'm creating a customisable nav menu for our site and have run into the following problem.
I need to generate a URL to any controller and action on the site and optionally pass it parameters. I was able to do the former by simply saying:
url_for(:controller => nav[:controller_name], :action => nav[:action_name])
which is great for sending you to {controller}/{action}. eg. news/articles
Throwing options in suddenly changes the game. Now I need to send you to something like:
{controller}/{action}/{category}/{slug}/{id}
eg. news/articles/world-domination/montana-max-vows-revenge/12345
the helper for the above would be something along the lines of:
news_article_path('world-domination', 'montana-max-vows-revenge', '12345')
and I haven't been able to replicate that in a vanilla url_for due to the arguments.
What I have done, and I don't really like is:
url_for(send("#{nav[:controller_name]}_#{nav[:action_name]}_path", *nav[:options]))
which generates the helper using send and then passes it a kwargs list. I'm sure there's a better way to do that surely?
You can do this cleanly if you are able to name the options (split here over lines for legibility):
url_for({
:controller => nav[:controller_name],
:action => nav[:action_name]
}.merge(nav[:options] || {}))
where
nav = {
:controller_name => 'news',
:action_name => 'articles',
:options => {
:category => 'world-domination',
:slug => 'montana-max-vows-revenge',
:id => '12345'
}
}

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

Rails Routes :requirements

I want to set a route :requirements on an array that verifies a particular parameter is included in an array:
atypes = [:culture, :personality, :communication]
map.with_options(:path_prefix => ':atype',
:requirements => {:atype => atypes.include?(:atype)}) do |assessment|
...
end
I haven't been able to find any documentation on how to accomplish this. Any help would be appreciated.
:requirements option expects regular expression. Something like /(culture|presonality|communication)/. You can also construct one from the array:
atypes = [:culture, :personality, :communication]
map.with_options(:path_prefix => ':atype',
:requirements => /(#{atypes.join('|')})/ ) do |assessment|
...
end

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