Is there anyway to pull the current url inside a controller? - ruby-on-rails

I'm doing some serious hacking. And at a certain point in my row of methods, all my params are lost, and there's no way for me to differentiate between two objects innapropriately sharing the same controller.
I thought I could do it by calling something like params[:foo] == "bar" , but at this point in the series of methods, there are no params available. That is because it is a method called before create.
create.before :create_before
However! They would have different URL's! So if I can just find a way to pull the params of the current url, I can solve this problem.
Any takers?
This is Rails 2.3.5

If you're actually in the controller, you can call request.path, which will return the currently requested path. However, given that params is not available, you may not actually be in a controller at that point. You have any code you can share?

Related

params appearing in params[:format] when passing to _path route helper

I have a function which calls a _path helper function with several parameters:
v2_specific_path(user, filter_params)
This works great, and in the controller method that handles this path I see both user and filter_params and their values.
In fact if I try to print out params they don't show up, but if I print out either one of them then they print out fine. filter_params has a helper function which builds a hash from several params[:keys] so that might be the reason.
What I'm trying to do is add another set of parameters to the function call:
v2_specific_path(user, new_params, filter_params)
Since I'm trying to add some functionality which requires passing some information to the underlying controller that resolves this request.
The problem is that this doesn't work and seems to screw things over:
If I put them in the middle: v2_specific_path(user, new_params, filter_params), then all the other params work great, but new_params actually appear inside params[:format] as: params[:format]="param1=4&param2=hi
If I put them at the end: v2_specific_path(user, filter_params, new_params) then filter_params doesn't get parsed at all and appears in params[:format] but new_format does appear to be parsed and appear in params correctly
I can't seem to figure out why this is happening. I've made sure I have correct params.require/params.permit values in the controller.
Any help is appreciated, if anyone has any other alternatives to passing values from application_helper to a controller (via _path, or some shared variable) that would also help immensely
Thank you!
For anyone seeking a solution to this:
I fixed this by doing two things:
1) created proper new routes which suited my implementation (I tried to do something a bit too clever and decided to just create new relevant routes instead of doing something too dynamic
2) I added the params I needed in to the routes: /something/:param1/whatever/:param2 etc.
This worked for me

ERB scope: instance variable vs locals

Suppose I have a controller with an index action and I would like to pass some data into the action's view (index.html.erb).
Typically, the rails way is to do: #some_var = some_value.
Does the above add to the global scope in a sense that #some_var is now available everywhere (helpers, etc...)? If so, is it better to do something like locals: {some_var: some_value} instead?
What are the tradeoffs if any?
Yes, #some_var is "global" in the sense that it added to the view context that is shared by views and helpers. So your controller, view, partials, and helpers can all access the same #some_var.
Using instance variables like this is the Rails convention: they just appear "like magic" in your views and helpers with no additional code. For simplicity, I would recommend it for most projects, especially as you are starting out.
However as your Rails app grows, here are some other best practices to keep in mind:
Try to limit your controller to assigning only one instance variable. If you find yourself assigning many instance variables in a single controller action, that is usually a sign that your controller is trying to do too much.
Avoid using instance variables in helpers. This makes your helper methods harder to reuse in other contexts, because they depend on instance variables being set "just right" by the controller. This can be a source of bugs.
Yes, I think you've got it. I prefer local arguments like that too, even though you're right Rails suggests you use instance variables.
I think instance variables may be okay when they are in a full template (never in a partial), and especially when you only have one of them that has the same name as the controller or whatever.
But in general, I agree with you. There is no downside to doing it with locals, unless you consider it confusing code, perhaps it would confuse someone who expects it to be the 'ordinary' Rails way.
I guess someone could argue that Rails templates are inherently tightly coupled to the controller, are meant to be that way, so it's no big deal to use instance variables -- the main negative of which is that it tightly couples your template to a particular controller implementation, but, they'd say, that's fine. I guess that's an opinion, apparently it is Rails' opinion! Certainly plenty of apps are written that way, and it's fine.
But there isn't really anything that's going to get in your way from going against the typical Rails way of doing things, and using local template arguments instead of instance variables. It works fine. I've done it.
I think you are right to be willing to question Rails -- sometimes Rails has made some odd choices. And also right to be cautious about going ahead doing something differently than Rails seems to wants you to, sometimes it does cause problems. In this case, I don't expect it will.
Nope, if you add #some_var = some_value to the index action then it will only be applied to that action. If you want to create a global action then you can apply it to the application.rb.
I highly recommend reading http://guides.rubyonrails.org/action_controller_overview.html
but something that might interest you in specific is this:
4.4 default_url_options You can set global default parameters for URL generation by defining a method called default_url_options in your
controller. Such a method must return a hash with the desired
defaults, whose keys must be symbols:
class ApplicationController < ActionController::Base def
default_url_options
{ locale: I18n.locale }
end end
These options will be used as a starting point when generating URLs,
so it's possible they'll be overridden by the options passed in
url_for calls.
If you define default_url_options in ApplicationController, as in the
example above, it would be used for all URL generation. The method can
also be defined in one specific controller, in which case it only
affects URLs generated there.

A way to make use of form automagic for a controller without a model

I have a controller without a model that handles a very cyclical task.
The user is basically filling out a form, sending it up to the server for some minor analysis, and then the server regurgitates nearly the same thing back to the user.
The user makes some adjustments, and the process starts over again.
There is nothing to save or store from this process, so it doesn't have a model.
The form i am working with has a large number of fields to deal with. Is there a way I can pass the params hash back into the view with the least amount of mess getting the fields repopulated?
Basically, I would want to tweak a couple of values in the params hash, but more or less pass the hash back so that it can repopulate the view nearly exactly how it was when it was submitted.
The old way of using OpenStruct seemed ideal.
Will this help?
In controller action, just initialize a variable like #params (or some thing like this), so that can be able to use all the values in the params can be available in that view page.
Maybe an ActiveForm is good for your application. It use to manage (new/create/validate/...) forms with no or several models.
https://github.com/realityforge/rails-active-form

Using parameter[:user_id] ,params[:user_id], params["userid"] in Rails?

While studying a Rails application I saw statements like:
parameter[:user_id]
params[:user_id]
params["userid"]
Can anyone tell me if there any major difference between them? Or, are all
fetching parameters only and can I use them interchangeably?
parameter[:user_id]
I don't think this is something official. However there's a parameters method on the current request object. See request.parameters in a controller action.
params[:user_id]
Using the params[:user_id] is the same as calling request.parameters[:user_id]. Also params[:user_id] is the same as params["user_id"]. See HashWithIndifferentAccess.
I am not sure if that's just a typo on your part, but params[:user_id] and params["userid"] are not the same, even with HashWithIndifferentAccess. The _ won't just go away so they can hold different values.
No, you need to look at the context in which each one is used. params is the normal parameter hash made available to methods in your controllers. It contains the parameters passed in as part of the request as GET or POST params.
So, given the following URL:
http://www.testsite.org/some_resource?user_id=13
The params[:user_id] would contain the value 13.
If the URL instead was:
http://www.testsite.org/some_resource?userid=13
You would need to use params[:userid] to get the value. So it all comes down to the way the URLs are made for the different controllers.
There's a third way, where you can map parts of the URL itself to params in the routes into your application. See config/routes.rb in your application. For instance with the following route:
match '/user/:user_id' => 'users#show'
You could pass in an URL like this:
http://www.testsite.org/user/13
And in your UsersController.show method you could access the user id by using params[:user_id] like normal.
The parameter hash is most likely a local copy of or reference to the params hash in a helper method or something.
params and parameters are the same. They return both GET and POST parameters in a single hash.
There is no such a thing as parameter.
ref: rails api

How do you handle current user and a list of users?

i'm having a situation (pretty standard for everybody i guess), where i have to do two things :
If a user asks for /user path, i have to present his/her personal information.
If a user asks for /user/:id path, i have to present information about that particular user, or the current user information if :id matches the current_user id.
There are definitely many ways to do that, but what is the best approach ? Should i have 2 different routes like /show/:id and /show_current, handled by different actions, or just have a /show/:id and do the handling in that action ?
Bear in mind that if this is the current view, i need to render a different more detailed view than the one about another view. I think the latter is probably the better way,but what do you think ?
If the current user is, say, 42 then /user/42 and /user would display the same information but /user/23 would display a stripped down public version of 23's data. So, the handler for /user/:id will have to know about the special case of :id being the current user; the handler for /user will also have to know about this special case as that's all it does.
If you use two routes then you'll either be duplicating code, wrapping the real code in an extra layer, or some other bit of busy work. I'd just send them both to the same controller method and that could start with something like this:
user = params['id'] ? User.find(params['id']) : current_user
And then later on you handle the special case of the requested user being the current user in just one place with something simple:
if(user == current_user)
# show the full blob of information
else
# show just the limited public information
end
You could, of course, slice it up into a bunch of little methods, such as show_current_user_info and show_other_user_info, inside the controller. The handler for /user could just be a call to show_current_user_info; the /user/:id handler could call show_current_user_info or show_other_user_info depending on what :id is. This approach smells like pointless layering to me.
In RESTful routing, you've described users_path and user_path(some_id). These map to User#index and User#show. The index method is normally a list of users, but if you are wanting index to show the current_user personal information, you can certainly do that. If you also need a list method, just add it to your controller and create a route to it.

Resources