In a standard rails form_for like below, it will return an html form where the action is /posts/1/comments. But including the post.id is not good for security, instead i want it to use the post.token for that record instead.
Rails form_for
<%= form_for([#post, Comment.new]) do |f| %>
<%= f.text_field :text %>
<% end %>
Html of form_for
<form class="new_comments" id="new_video_marker" action="/posts/1/comments" accept-charset="UTF-8" method="post">
<input type="text" name="comments[text]" id="comment_text">
</form>
You need to create a token.
$ rails generate migration AddTokenToPost post_token:string
Modify your post.rb :
# app/models/post.rb
class Post < ApplicationRecord
before_create :set_post_token
private
def set_post_token
self.post_token = generate_post_token
end
Try this for your form :
<%= form_for([#post, Comment.new]) do |f| %>
<%= f.hidden_field :token %>
<%= f.text_field :text %>
<% end %>
But including the post.id is not good for security
Who fooled you into thinking that?
This is a classic example of security by obscurity. Sure somebody can't just guess that the url is /posts/1/comments but if you're not authorizing the resource properly /posts/somereallylongtoken/comments is no more secure. If not UUID's would be magically more secure and there would be no one using auto-incrementing integers for PKs.
You can use single use tokens which are placed in the URL for stuff like user confirmations but thats only because you're sending a link in a email and you're limited to GET. Thats used as a nonce to authorize the user. Not just to obfuscate an ID.
Related
First: Enter a certain emp_no using the textfield.
Second: I am trying to render/show the lookup value from a table through .
Here's the view:
<div class="field">
<%= f.label :emp_no %><br />
<%= f.text_field :emp_no%>
</div>
<div class="field">
<%= f.label :emp_name %><br />
<div><label><%= #emp_name %></label></div>
</div>
Here's my controller:
before_filter :customer
def customer
#emp_name = where(Employee.params[:employee_code])
end
Any inputs are much appreciated! Thank you!
We've achieved something similar at http://firststopcosmeticshop.co.uk (try the search at the top)
Search
What you're looking for, simply, is a piece of functionality which helps you search your data.
This can be achieved relatively simply, but you have to make sure your syntax is correct:
#config/routes.rb
resources :employees do
get :search
end
#app/controllers/employees_controller.rb
class EmployeesController < ApplicationController
layout: Proc.new {|controller| controller.request.xhr? ? false : "application" }
def search
#emp_names = Employee.where code: params[:employee_code]
end
end
#app/views/employees/search.html.erb
<% #emp_names.each do |employee| %>
<%= employee.name %>
<% end %>
This setup will provide you with the ability to load the search items if you wanted to show them, allowing you both the ability to use ajax (detailed below), or just plain HTML / HTTP
Ajax
If you wanted to use Ajax to deliver "real time" results, you'll want to use the following details:
#app/assets/javascripts/application.js
$(document).on("ajax:success", "form", function(status, data, xhr){
$(this).append(data);
});
This should render the results wherever you want on your front-end (requesting) page. The trick lies in the controller's assertion of the layout depending on the type of request received (HTTP or XHR)
Form
Finally, your form needs to reflect the functionality you wish to define. Currently, you don't have any way to send the request to your emp_names method, and so you need to create a better way to manage it:
#view
<%= form_tag employees_search_path, remote: true do %>
<%= text_field_tag :input %>
<%= submit_tag %>
<% end %>
Of course, the form can change considerably, but it basically means that you will send a simple request to your employees_search_path, which will then give you the capacity to manage the response in the controller; either normally, or with Ajax
According to this rails guide it is acceptable to key params with the name you associate with the html values in your template,
"When the form is submitted, the name will be passed along with the form data, and will make its way to the params hash in the controller with the value entered by the user for that field. For example, if the form contains <%= text_field_tag(:query) %>, then you would be able to get the value of this field in the controller with params[:query]"
However, when I attempt to access a param I submitted it throws the following error:
I understand that there are other params besides :name but I am just trying to get this one handled for now before passing the others. I am just making this app to practice the fundamentals.
Also, how come my params are being passed in my URL? These are forms, shouldn't they be submitted as a POST request and thereby able to use strong params with? I think the reason i'm having so much trouble is because I am used to strong params, I am unfamiliar with this syntax. Any help is appreciated, thanks!
Here is my code:
Controller:
class OrdersController < ApplicationController
def create
Order.create(params[:name])
end
end
View
<h1> Input information </h1>
<%= form_tag("/order",method: "get") %>
<%= label_tag(:name, "Enter name") %>
<%= text_field_tag(:name) %>
<%= label_tag(:email, "enter email") %>
<%= text_field_tag(:email) %>
<h2> Select color </h2>
<%= label_tag(:red,"red") %>
<%= check_box_tag(:red) %>
<%= label_tag(:green,"green") %>
<%= check_box_tag(:green) %>
<%= label_tag(:indigo,"Indigo") %>
<%= check_box_tag(:indigo) %>
<%= submit_tag("submit") %>
You need to provide a hash argument to create. How will Order know that you are setting name? You are basically doing this:
Order.create('phoot')
You need to specify what phoot is:
Order.create(name: params[:name])
# ends up being Order.create(name: 'phoot')
I am working on a web application and what is bothering me is the fact that users can use firebug to manipulate the code.
<%= form_for([#journal, #news]) do |f| %>
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<%= f.hidden_field :journal %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
routes.rb
resources :journal do
resources: news
end
The url appears like so mysite.com/journal/1/news/3. Since the journal id is in the url how can I prevent a user from changing journal id value of 1 to something like 2 or 3.
<input id="news_journal_id" type="hidden" value="1" name="news[journal_id]">
You can't. NEVER trust input from anywhere. Implement a server-side validation/role-model/access-limitation of any kind.
You can't prevent users from sending you modified input. You can (and should) check that input on the server instead of blindly accepting it.
If a user can't read/write this journal, redirect him to a corresponding page, etc.
You should use current_user associations to fetch any record, to make your application secure.
For example:
journal = currect_user.journals.find(params[:news][:journal_id])
journal.news.create(params[:news].except(:journal_id))
I have some data associated with a model that is in a hash. The hash is generated in the controller: #hash.
What is the proper way to create a form for this data?
I came up with the following code for the view:
<% #hash.keys.each do |key| %>
<div class="field">
<%= f.label key %><br />
<%= text_field_tag "hash_" + key, #hash[key] %>
</div>
<% end %>
This generates the form, but it creates each hash item as a separate variable in the form. This doesn't seem to be the proper way to submit the data back. I would like to get the data back as a hash, and access it with params[:hash].
What is the best way to do this?
Working in Rails 3.07, Ruby 1.9.2.
Thanks.
EDIT: I should have made this clear. This code is inside of a form generated for a model. So, the form needs to submit all the fields for the model, plus the above hash.
Based on this article you should change the name in text_field_tag to
<% #hash.keys.each do |key| %>
<div class="field">
<%= f.label key %><br />
<%= text_field_tag "hash[" + key + "]", #hash[key] %>
</div>
<% end %>
My answer is not strictly on topic but I really recommend you to take a look at http://railscasts.com/episodes/219-active-model. You could use ActiveModel APIs to simulate a model object with Rails 3. Doing that you could simply do something like
<%= form_for(#object) %>
and leaving the populating of your object to Rails APIs.
When you use the helpers that end with _tag that's what happens.
Instead of text_field_tag ... use f.text_field ....
In order to get a hash like params => {:hash => {:field1 => "", :field2 => ""}} you have to pair up form_for with f.input_field_type instead of simply input_field_tag.
See the difference?
What is the difference between form_for and form_tag? Is anything different for form_remote_for and form_remote_tag?
You would use form_for for a specific model,
<% form_for #person do |f| %> # you can use f here
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
<% end %>
Form_tag create basic form,
<%= form_tag '/person' do -%>
<%= text_field_tag "person", "first_name" %>
<% end -%>
form_for prefers, as its first arg, an activerecord object; it allows to easily make a create or edit form (to use it in a "new" view you should create an empty instance in controller, like:
def new
#foo = Foo.new
end
It also passes a form variable to the block, so that you don't have to repeat the model name within the form itself. it's the preferred way to write a model related form.
form_tag just creates a form tag (and of course silently prepare an antiforgery hidden field, like form_for); it's best used for non-model forms (I actually only use it for simple search forms or the like).
Similarly, form_remote_for and form_remote_tag are suited for model related forms and not model related forms respectively but, instead of ending in a standard http method (GET, POST...), they call an ajax method.
All this and far more are available for you to enjoy in the FormHelper and PrototypeHelper reference pages.
EDIT 2012-07-13
Prototype has been removed from rails long ago, and remote forms have completely changed. Please refer to the first link, with reguard to the :remote option of both form_for and form_tag.
These should be similar:
<% form_for #person do |f| %>
<%= f.text_field :name %>
<% end %>
and:
<%= form_tag '/person' do %>
<%= text_field_tag "person[name]" %>
<% end %>
If you want to submit the same params to the controller, you would have to define this explicitly.