class UsersController < ApplicationController
def newpass
#somevariable = {
"a-var" => params[:token_id],
"b-var" => params[:client_id],
"c-var" => params[:user_id]}
end
def setpass
#I need to access this hash values without params getting reset
end
end
I have an action newpass with a corresponding view which calls setpass. I access URL's params in newpass action. I want to use these param values in setpass but the values get reset.
Using a link:
You need to send those values when your request hits setpass action in UsersController. You can create a button, or a link_to to send along those params values. Here is how:
<%= link_to "Go to", setpass_path(token_id: params[:token_id]) %>
You can pass params in _path method, and you will receive all those values inside the respective method in controller.
Using a form:
If you are using a form, and you would like to send those values along, hidden_field_tag is the best option here. You can do something like this:
<%= hidden_field_tag :token_id, params[:token_id] # this line must exist inside your form element %>
Related
I have this link_to helper passing an :email_sequence instance and an extra :set_active params.
I then try to update the :email_sequence instance in the controller using strong params but I'm getting an error saying:
param is missing or the value is empty: email_sequence
link_to:
<%= link_to "Activate", admin_email_sequence_path(base_email.email_sequence, set_active: :true), method: :patch %>
Controller:
class Admin::EmailSequencesController < AdminController
before_action :set_email_sequence
def update
if #email_sequence.update(active: email_sequence_params[:set_active])
flash[:success] = "Sequence updated succesfully"
redirect_to_forwarder_or(params[:forwarding_uri], admin_account_emails_path)
end
end
private
def set_email_sequence
#email_sequence = current_account.email_sequences.find(params[:id])
end
def email_sequence_params
params.require(:email_sequence).permit(:set_active)
end
end
This is what gets sent in the params:
{"_method"=>"patch", "authenticity_token"=>"[FILTERED]", "set_active"=>"false", "id"=>"1"}
Can anybody tell me what am I doing wrong?
By params.require(:email_sequence).permit(:set_active) you expect parameters to be { email_sequence: {set_active: "ANY SCALAR VALUE HERE"} } but you pass only set_active you can fix it by permitting the only one parameter
params.permit(:set_active)
You don't need strong parameters here in the first place. Contrary to popular belief strong parameters does not magically sanitize the parameters. It just prevent mass assignment vulnerabilities by requiring that you whitelist the parameters when passing a hash of parameters. Since you are only using a single parameter there is no mass assignment vulnerability:
class Admin::EmailSequencesController < AdminController
before_action :set_email_sequence
def update
if #email_sequence.update(active: params[:set_active])
flash[:success] = "Sequence updated succesfully"
redirect_to_forwarder_or(params[:forwarding_uri], admin_account_emails_path)
else
# provide an error response!
end
end
private
def set_email_sequence
#email_sequence = current_account.email_sequences.find(params[:id])
end
end
If you later want to use multiple parameters nested in a hash the use of link_to is pretty questionable even if it can be done.
<%= link_to "Activate",
admin_email_sequence_path(
base_email.email_sequence,
"email_sequence[set_active]" => true,
"email_sequence[foo]" => "bar"
),
method: :patch
%>
Use button_to or form_with/form_for to create a form element and style the button to look the way you want instead as this places the parameters in request body instead of the query string.
what is the new way in Rails 5 to merge actual page query strings to link with a new one?
Let's assume I have page http://localhost:3000?type=a and I want to add another query param to the link on page:
<%= link_to root_path(params.merge(tech: "b")) do %>
but I get: unable to convert unpermitted parameters to hash.
Where I should permit the params?
I tried to do it in before_action filter, but it seems to be too late.
Thanks
EDIT:
My controller:
class HomeController < ApplicationController
before_action :permit_params
...
private
def permit_params
params.permit(:tech, :type)
end
end
You just need to whitelist the params you want to merge with
<%= link_to 'Home', root_path(params.permit(:type, :tech).merge(tech: 'b')) %>
and get /?tech=b&type=a. If you really want all parameters, you can use permit!
<% params.permit! %>
<%= link_to 'Home', root_path(params.merge(tech: 'b')) %>
which will give you /?action=index&controller=home&tech=b&type=a, which while those keys don't seem to be messing anything up, is very likely not desired (and controller and action will be overridden and not passed into your controller action). NOTE: The controller/action are set that way because I'm on my HomeController index action, not because that's what root_path is pointing to
I just don't think I can recommend doing this, however (seems iffy, imo)...stick with whitelisting.
I have a button from Users index view to Friendship controller.
But I can't figure out how to correctly pass the hash, which is required by the strong parameters.
Users index view:
<% #users.each do |user| %>
<tr>
<td><%= button_to 'Add friend', friendships_path(:friend_id => user.id), method: :post %></td>
</tr>
<% end %>
Friendship controller
def user_params
params.require(:user).permit(:friend_id)
end
How can I pass the ':user' hash along with the ':friend_id' ?
Thanks in advance.
You'll probably best with the following:
def user_params
params.permit(:friend_id)
end
Params
The params part of the system basically works by taking the params hash and "permitting" the relevant values based on it, as per the following...
When you submit a form_for (as this is built around an ActiveRecord object), you'll receive a params hash like this:
params => {
"[Model]" => {
"param_1" => "value",
"param_2" => "value",
"param_3" => "value"
}
}
In this instance, you'll use the require tag in strong_params:
def strong_params
params.require(:model).permit(:param_1, :param_2, :param_3)
end
--
The situation you have is that you want to use use a single "level" of params hash:
params => {
"friendly_id" => "value"
}
In this case, you'll want to use the following:
def strong_params
params.permit(:friendly_id)
end
Logs
The best way to get this working is to observe the params hash that you're dealing with.
You can view the logs and see the Params hash outputted each time you make a request to Rails - I would look at that, and determine the structure of your params hash in order to ascertain the type of strong_params method you should call
Is it possible to fire up an custom action when user clicks 'Search' button on search form?
There is an mechanism in our app to save every URL the app has hit. In our search form, when clicking 'Search' button, there will bring up the search result page. The problem is that the URL for the search result form was not saved. The Back button brings back the search page (for setup search params) instead of the search result page (because its URL was not saved).
Here is the search form for model configs:
<h4>Search Form></h4>
<%= simple_form_for #config, :method => :get, :url => search_result_configs_path do |f| %>
<%=render :partial => 'search_params', :locals => {f: f} %>
<%= f.button :submit, t('Search') %>
<% end %>
The URL for the search result looks like this (with the search params set by user) after user clicks Search button:
http://localhost:3000/configs/search_results?utf8=%E2%9C%93&engine_config[start_date_s]=&engine_config[end_date_s]=&engine_config[engine_id_s]=1&engine_config[argument_name_s]=&engine_config[commissioned_s]=&commit=%E6%90%9C%E7%B4%A2
This is the URL we would like the app to remember. We figure we need custom action triggered when a user clicks 'Search' button. Is it possible?
Route
Firstly, calling a custom application is actually quite a simple process - you just need to call its route:
#config/routes.rb
resources :search do
collection do
get :custom_action
end
end
This will allow you to use the likes of form_tag to call the custom route:
#app/views/your_controller/view.html.erb
<%= form_tag search_custom_action_path, method: :get do %>
...
<% end %>
--
Form
Secondly, you're using simple_form for your search form.
This is completely fine, but the problem you have here is that when you use this, it has to have a ActiveRecord object to populate the form with. This is probably where you're getting confused, as to do this, you need ot make sure #config is available every time you load that form, which I imagine can be a lot.
We've created a search form here:
Although in Rails 4, we used a form_tag for this form, as it allowed us to create & display the form where-ever we need in the app. This allows us to pass the required params through the form & access them on the other side
--
Params
You mention you want to "save the URL" - what do you mean by this?
Surely you'd prefer to save the params?
If this is true, the way to do this is actually relatively simple - you'll get access to the params hash in your controller when you send the request through:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
def custom_action
params[:your_param] #-> this is accessible here
end
end
The bottom line is if you wanted to save the query strings, you'll have to create a model called Search or similar, allowing you to pass the params through when you process the custom action in your controller, just like you would any other ActiveRecord object
I would like to pass a parameter through a link_to method in Rails. I know there is a way to do it via the URL but I really don't want to do that. Is there any way to pass a param via a link without adding it to the link itself?
I know in PHP you can post and then retrieve that value by using the post variable. Is there something similar in Rails?
link_to signature looks as follows:
link_to(body, url_options = {}, html_options = {})
So, POST would look like (lets say you want to POST user's data):
link_to "Link text", some_path(:foo => "bar", :baz => "quux"), user: #user, :method => :post
User's data can be retrieved in the controller using params[:user]
Here's how you can pass a parameter around via the link_to method in order to, say, create a new object with the passed parameter. This strategy would allow you to pass variables among actions in your controller and create objects with predefined attributes:
Say in your show view, you have a variable called #foo that you want to pass to your new controller action. In which case, in your show view, you can have
<%= link_to "Link Text", new_widget_path(:foo => #foo) %>
which would store #foo in params[:foo], allowing you to use params[:foo] in your controller. Which controller action you get directed to depends upon *new_widget_path*. In this case, you get directed to the new action in WidgetController.
Clicking on Link Text will direct Rails to the new action of your WidgetController. You can have
def new
#widget = Widget.new(:foo => params[:foo])
end
Then, in your new.html.erb view file, you can allow the user to create a new Widget object with this pre-defined foo attribute already filled out via a hidden form field:
<%= form_for(#widget) do |f| %>
<%= f.label :other_attribute %><br />
<%= f.text_field :other_attribute %>
<%= f.hidden_field :foo %>
<%= f.submit %>
<% end %>
Allowing the user to create a new widget with the foo attribute already filled out!
Passing information through a web request can be done either by the URL: http://example.com/foo?bar=blah in a GET request which is what link_to does, or through a POST operation which usually requires a form. The form could have hidden elements if you just want a submit button:
<form method="POST" action="http://example.com/foo">
<input type="hidden" name="bar" value="blah">
<input type="submit">
</form>
There are various rails helpers to help build the form if needed.
Lastly, if you really want a link, you could either CSS style that button, or you could use javascript to observe a link and then POST the info. (the method Simon Bagreev posted does this with javascript)
What sort of parameter? If it's a key for a GET request, convention would dictate using the url (e.g. params[:id] or a an active record path variable). If you want to POST something, you should be using a form. Otherwise, you could write a helper method to set a session variable or something, but think about your architecture and what you're semantically trying to do, and I'm sure someone here can help you out.