rails: passing additional parameter with Model.save? - ruby-on-rails

I'm working with an internal API application. When I use my front-end app to request information, i can pass an additional parameter with the request like this:
Model.find(id, :params => {:locale => I8n.locale})
or
Model.get(:custom_api_call, :locale => I18n.locale)
Is there a place to do that with Model.save or Model.update_attributes? For instance, this doesn't work:
Model.save(:params => {:locale => I18n.locale})
Model.save(:locale => I18n.locale)
Model.update_attributes(:locale => I18n.locale)
Model.update_attributes(:params => {:locale => I18n.locale})
As you can imagine, those simply add :locale to the attributes sent to my API.
Better yet! If someone knows how to pass :locale => I18n.locale as a parameter with every communication, that would let me dry up a lot of my code.
Thank you for your time

Related

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'
}
}

Pass arguments to ruby function in this context

disclaimer I am pretty new to Ruby / Rails
I am using RPH::Navigation for creating my navigation menus. What I am trying to do now is add some sub-nav items and I am doing so like this:
suboptions.each do |group|
def relpath
link(group[:link], group[:args]).
end
sub_menu.item group[:name], :path => :relpath
end
link is just a method that returns "#{link}?#{query_string}" where query_string is built from the args hash.
What I was originally trying to do was something like
sub_menu.item group[:name], :path => link(group[:link], group[:args])
but that put the return value in, and later it is called, returning a method not found error.
My current approach has the problem that group is not in scope within relpath. I tried also using Proc.new and lambda, but since those are not called like normal functions it chokes on them as well.
What can I do to correct this? What is the proper way?
EDIT
If I do
suboptions.each do |group|
def relpath(group)
link(group[:link], group[:args]).
end
sub_menu.item group[:name], :path => relpath(group)
end
Then the error I get is:
undefined method `mylink?myarg=1' for #<#<Class:0x007fd8068acd58>:0x007fd8068b07f0>
EDIT 2
Here is more extensive example of the code.
menu.item MyTestsController, :text => 'Test', :if => Proc.new { |view| view.can? :read, MyTest } do |sub_menu|
suboptions = [{:link => "tests", :name => "All Systems", :args => {:system_id => 0}},
{:link => "tests", :name => "System A", :args => {:system_id => 1}}]
suboptions.each do |group|
def relpath(group)
link(group[:link], group[:args]).
end
sub_menu.item group[:name], :path => relpath(group)
end
end
I have no experience with the navigation library in question, but looking at the documentation at https://github.com/rpheath/navigation it seems you are expected to give the name of a Rails named route helper as the path argument - not an actual URL route. The "undefined method" is simply generated because RPH::Navigation tries to call a helper method by the name that is defined in :path argument, and in this case Rails cannot find a named route helper method called "mylink?myarg=1". So basically, what you would need to do is to create a named route, and use that as the path.

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"

Handle rails route with GPS parameter

I'd like to create a route in my rails app to handle a gps-coordinate parameter. The intention is to find restaurants near the given position.
This is were I started:
match "/restaurants/near/:lat/:lng(/:range)", :to => "restaurants#near", :as => "near", :constraints => {:range => /\d+/}
It seems the router has problems with float parameters, an url like /restaurants/near/53.0123/10.5678 isn't recognized. Do you have a solution or best practice for handling GPS coordinates in rails urls?
Thank you!
The problem is caused because Rails try to use the "dots" for search for the format (.:format)
So, you can add some constraints to fix it, for example:
match "/restaurants/near/:lat/:lng(/:range)", :to => "restaurants#near", :as => "near", :constraints => {:lat => /\-?\d+(.\d+)?/, :lng => /\-?\d+(.\d+)?/ , :range => /\d+/}

Resources