How to use send method to post, get, update route? - ruby-on-rails

I'm trying to DRY some request specs.
I need to pass to a shared example the following params:
method, action, params
shared_example:
shared_context "blah" do |method, action, params|
let(:url_path) { send("api_cars_path") }
end
How can I execute a route with send using the method that is being passed as parameter ? Something like this:
send(:get, "api_cars_path")
So I can can pass :get, :post, etc dynamically.

The route api_cars_path is really a method which returns a string like /api/cars. So you need to invoke the route helper and then pass it to the get method as the first argument.
send(:get, send(:api_cars_path))

Related

Add default params to named route helper in rails

I have this route
get "/articles/:id" => "articles#show", as: :article
Which generates the path helper article_path(article).
Is it possible to add some default parameters to this path helper, like /articles/123?token=123456? For example I use the article_path helper a dozens of times and it would be tedious to always do something like
<%= article_path(article, token: article.token) %>
I've played around with the defaults of a route, but this does not affect the URL generation, only the params object when I'm on this route
get "/articles/:id" => "articles#show", as: :article, defaults: { token: "my token" }
The only thing I can think of, is to overwrite / monkey patch the helper, but as I need this logic on other helpers too, I was wondering if there is a build in way to do this.
This logic does not really belong in the routing layer and query string parameters are for the most part completely transparent to the router.
Instead you can just create your own helper method:
def article_path(article_or_id, **opts)
if opts[:token].nil? && article_or_id.respond_to?(:token)
super(article_or_id, opts.merge(token: article.token))
else
super
end
end

Rails params not receiving variable passed from view

I have defined a CRUD resource called items, which I've added a collection route to called similar_items.
In the view/show, I have: link_to similar_items_items_path(), :similar_to => #item
In my similar_items controller method, what's the best way to get the item that was passed from link_to? The params hash does not contain similar_to which I've clearly passed as shown above. Why is it not being passed into params?
You should pass parameters inside the path helper:
link_to 'Your link label here', similar_items_items_path(:similar_to => #item)

Before and After Filters/Functions for Rails Routes

I have an idea and I am not sure if is is already done.Right now to make url search engine friendly developers customize to_param function of model class. Then they call to_s function to get the id of the elmenet.
What if I want to create url for not model but for string. Lets say I create link for post controller's search action. The only variable in the url is search_string. So how can i create seo link for this search page. I know how to create links etc etc. but my problem is that I want to call function on this string such as to_param or something like that to make seo string, also in the controller to perform a search I have to humanize this string again. So what I want is this:
In every view, I dont want to use urlizing method to make it se friendly
In every controller, I do not want to call any function to humanize string back again, this should done by router
In the router:
match 'search/:string' => 'Post#search', :as => :search, before => some_before_router_helper_function, after => some_after_router_helper_function
In these helper function what I will do is that i will parametrize any params I want, then I will humanize any params back again
example before/after router helpers:
def some_before_router_helper_function
string = string.underscore.dasherize
end
def some_after_router_helper_function
param[:string] = param[:string].undasherize.un_underscore
end
As Heikki pointed: https://github.com/svenfuchs/routing-filter

How to call a method and send new parameters in RoR?

Let's say I have methodA
def methodA
note = Note.find(params[:id])
note.link = params[:link]
note.linktype = params[:linktype]
note.save
redirect_to(notes_url)
end
When I call this method from a view like this, it works fine
<%= link_to image_tag(w.link, :border =>0), methodA_path(:linktype => w.linktype, :link => w.link, :id => #note.id) %>
But, if I call the method from another method in the same controller like this:
def methodB
...
methodA(:id => params[:id], :link => link, :linktype => "image")
end
I get this error:
wrong number of arguments (1 for 0)
The parameters that methodA is getting are still the same parameters that methodB got, not the ones that I'm sending from methodB. How do I get around this problem? Thank for reading.
Several things:
The Ruby, and therefore Ruby on Rails, naming convention is to use underscore notation rather than camelcase. So it should be method_a rather than methodA.
It looks like methodA is a controller action. If you look at your method signature, you're not actually defining any method parameters. That's a good thing: actions don't take any.
The params call in the methodA action is not accessing method parameters, but is access the Rails request params hash.
In your view, you're not actually calling the method. Rather, you're linking to the action, which, when clicked, initiate a request that is routed to that action. The actual method you're calling is methodA_path, which is generating the URL. This is a shortcut to url_for that automatically fills in some parameters for you (the other ones are in the hash you're passing). This method was automatically generated for you from your routes. Do a rake routes from the root of your app for a little more information.
If you wanted to call the action method from methodB, which is probably unwise, you don't need to pass it the parameters. Since methodB is also an action being called in its own request cycle, the params hash is still available to methodA, and it will find all of those things just fine. I'd suggest, however, extracting any common functionality into a third helper method and calling that from each action; calling actions from other actions feels like a code smell to me.
A bit of a summary: methodA and methodA_path are different methods. The former takes no parameters but accesses the Rails request parameters hash, while the latter takes parameters to pass to url_for.
This is all pretty basic, so I strongly suggest you read Agile Web Development with Rails (3rd edition for Rails 2, 4th for Rails 3).
A call to method_a_path and method_a are not the same.
The method_a does not take parameters. It accesses the parameters from the params hash set to the controller instance during action invocation.
The method_a_path does not invoke method_a, it just generates the URL for invoking the method. Actual invocation happens when the user clicks on the link and the rails server processes the request.
If you want to reuse the method in a diffrent context extract the code of the action to a new method as shown below:
class PostsController < ApplicationController
def add_media
add_media_with_para(params)
end
def action2
add_media_with_para(:id => params[:id], :link => link, :linktype => "image")
end
private
def add_media_with_para p = {}
note = Note.find(p[:id])
note.link = p[:link]
note.linktype = p[:linktype]
note.save
redirect_to(notes_url)
end
end
Now in your view you can obtain the path to add_media action as follows:
posts_add_media_path(:linktype => w.linktype, :link => w.link, :id => #note.id)
I assume by addMedia you mean methodA
Note, method methodA_path is not the same as methodA. First one is automatically generated because you have a route named methodA and returns url necessary to access that route. Thus, it returns string. While methodA usually renders html template.
If you want to delegate rendering to another action, you can do something like this: redirect_to :action => :methodA, :id => 1, :otherParam => 2

Identify GET and POST parameters in Ruby on Rails

What is the simplest way to identify and separate GET and POST parameters from a controller in Ruby on Rails, which will be equivalent to $_GET and $_POST variables in PHP?
You can use the request.get? and request.post? methods to distinguish between HTTP Gets and Posts.
See http://api.rubyonrails.org/classes/ActionDispatch/Request.html
I don't know of any convenience methods in Rails for this, but you can access the querystring directly to parse out parameters that are set there. Something like the following:
request.query_string.split(/&/).inject({}) do |hash, setting|
key, val = setting.split(/=/)
hash[key.to_sym] = val
hash
end
You can do it using:
request.POST
and
request.GET
There are three very-lightly-documented hash accessors on the request object for this:
request.query_parameters - sent as part of the query string, i.e. after a ?
request.path_parameters - decoded from the URL via routing, i.e. controller, action, id
request.request_parameters - All params, including above as well as any sent as part of the POST body
You can use Hash#reject to get to the POST-only params as needed.
Source: http://guides.rubyonrails.org/v2.3.8/action_controller_overview.html section 9.1.1
I looked in an old Rails 1.2.6 app and these accessors existed back then as well.
There is a difference between GET and POST params. A POST HTTP request can still have GET params.
GET parameters are URL query parameters.
POST parameters are parameters in the body of the HTTP request.
you can access these separately from the request.GET and request.POST hashes.
request.get? will return boolean true if it is GET method,
request.post? will return boolean true if it is POST method,
If you want to check the type of request in order to prevent doing anything when the wrong method is used, be aware that you can also specify it in your routes.rb file:
map.connect '/posts/:post_id', :controller => 'posts', :action => 'update', :conditions => {:method => :post}
or
map.resources :posts, :conditions => {:method => :post}
Your PostsController's update method will now only be called when you effectively had a post. Check out the doc for resources.
I think what you want to do isn't very "Rails", if you know what I mean. Your GET requests should be idempotent - you should be able to issue the same GET request many times and get the same result each time.
You don't need to know that level of detail in the controller. Your routes and forms will cause appropriate items to be added to the params hash. Then in the controller you just access say params[:foo] to get the foo parameter and do whatever you need to with it.
The mapping between GET and POST (and PUT and DELETE) and controller actions is set up in config/routes.rb in most modern Rails code.
I think what Jesse Reiss is talking about is a situation where in your routes.rb file you have
post 'ctrllr/:a/:b' => 'ctrllr#an_action'
and you POST to "/ctrllr/foo/bar?a=not_foo" POST values {'a' => 'still_not_foo'}, you will have three different values of 'a': 'foo', 'not_foo', and 'still_not_foo'
'params' in the controller will have 'a' set to 'foo'. To find 'a' set to 'not_foo' and 'still_not_foo', you need to examine request.GET and request.POST
I wrote a gem which distinguishes between these different key=>value pairs at https://github.com/pdxrod/routesfordummies.
if request.query_parameters().to_a.empty?

Resources