Generating unique token on the fly with Rails
The cleanest solution I found:
@seller.user_info_token = loop do
token = SecureRandom.urlsafe_base64
break token unless User.exists?(user_info_token: token)
end
And something very clean but with potential duplicates (very few though):
@seller.user_info_token = SecureRandom.uuid
Random UUID probability of duplicates
Edit: of course, add a unique index to your :user_info_token
. It will be much quicker to search for a user with the same token and it will raise an exception if by chance, 2 users are saved at the exact same moment with the exact same token!
Generating a unique, but apparently random, identifier without loop+retry
Run a cronjob every few hours which repopulates a Redis collection with unused identifiers. Let it run in the background so when you need one, just pop it off the Redis collection.
Generating a unique URL with tokens in Rails 4 for an external form response
Add a token field to the feedback model with an index and add a callback to populate it on create e.g.
feedback.rb
before_create :add_token
private
def add_token
begin
self.token = SecureRandom.hex[0,10].upcase
end while self.class.exists?(token: token)
end
now add a new route for the providers feedback
resources :feedbacks do
get 'provider'
put 'provider_update' # you might not need this one, if you are happy to use update
end
In your controller make sure they don't get rejected by devise
before_filter :authenticate_user!, except: [:provider, :provider_update]
...
def provider
@feedback = Feedback.find_by token: params[:token]
end
then in the app/views/feedback/provider.html.haml you can use url in simple_form to send it to the correct update location and only provide the input that they should see.
f.inputs :p_comment
Now update your mailer.
@url = provider_feedback_url(@feedback, token: @feedback.token)
You could do something similar to this using friendly id but you would still need to create some sort of unique slug and then use Feedback.friendly.find instead. I think you would want to combine it with a token to ensure it's still the provider giving the feedback - so the only benefit would really be hiding the true id/count. I think you should update p_* fields to provider_* so that the next dev knows what's in it - it's not the 90s!
Does SecureRandom generates a unique string or do I have to check?
Nothing is completely random in a computer generated string. Technically, there is a very low, remote possibility that two strings may be the same.
This is even more true in a highly concurrent system. If that's not the case, what you can do is to simply add an unique constraint (aka an unique index) at the database level. In this way, in the remote event that two strings will be equal, the database will reject the second one.
It's likely you will have an index on that field in any case if you need to use it for a query, therefore it should not add any unreasonable overhead.
As a side note, SecureRandom
is a Ruby library, not a Rails library.
How to generate a secure random token for remember me functionality?
TL; DR
Use a well-maintained gem for generating login tokens when you can rather than rolling your own. However, understanding how to evaluate the relative strength of such tokens depends on the size of the numerical range and the entropy inherent in the generation of the tokens.
Understanding Space and Entropy
"A suffiently large space" is using the term in the mathematical or cryptographic sense. If a chosen random number can only vary between whole numbers from 1..10, you have a very small space. If your number can vary over 128 bits or more, then you have a much larger space from which to choose. This avoids the likelihood of collisions. Mathematically speaking, the amount of entropy and the seed value used to generate a pseudo-random value will also have a significant impact on the overall security and collision-resistance of the generated number.
What constitutes a sufficiently large space depends on your problem domain. In many cases, UUIDv4 as generated by Ruby's SecureRandom#uuid method is sufficiently random to be considered a universally unique identifier that is sufficiently random to avoid collisions. Because it is (pragmatically speaking) "universally unique," the utility value of salting it or hashing it with other information is probably unnecessary. However, it is still important to associate the UUID with a user ID or other unique attribute of a user so that the value can be used in a cookie, form data, or query parameter to associate it with an existing login, or with whatever other data it is that you're trying to persist.
Rather than doing this yourself, it is generally better to use a well-designed and well-maintained authentication mechanism like Devise to manage your Rails logins. The same is true for authorization, where other gems like CanCan may be useful. In either case, under the hood avoidance of collisions in authentication tokens are being handled for you.
If you are rolling your own, then understanding statistics, entropy, and the risks of deliberate or accidental collisions are extremely important. While a short answer here simply cannot do justice to the complexity of the underlying question, it should give you enough to get started and help you select the amount of randomness or uniqueness your current problem requires.
how to generate AuthenticityToken on rails
There is a view helper called form_authenticity_token
that returns the current session's authenticity token.
In your view.html.erb:
<form action="/blah" method="POST">
<input name="authenticity_token" value="<%= form_authenticity_token %>" type="hidden">
<input name="first_name" type="text">
</form>
Generate unique identifier in rails helper
Your view rendering was done within a second! hence the reason you are seeing the same id
value for all inputs
.
The statement below will have the same value for 60 seconds.
st = Time.now.strftime("%I%M%S%p")
As it appears you want the slider to be on each input, I would recommend using either a data attribute or simply a css class. An example using css class would be:
<div class="row">
<div class="col-xs-12">
<%= answerf.text_field :scale, class: 'has-slider', type: 'text',
data: {'slider-id' => 'scale',
'slider-min' => '0',
'slider-max' => '10',
'slider-step' => '1',
'slider-value' => '5' } %>
</div>
</div>
Say we assign class has-slider
, we could then use this class selector and execute slider()
on the matched elements in javascript as:
# app/assets/javascripts/input_slider.js.coffee
$ ->
# Execute slider on all inputs with has-slider css class
$('input.has-slider').slider()
And, you seem to know why you have slider only on the first input; This is because all your inputs have same id
value and DOM selection retrieves the first match. id
s need to be unique within a document.
Update:
As you're adding input elements within the dom after page load, the $('input.has-slider').slider()
call made on app/assets/javscripts/input_slider.js.coffee
would not work. It would only work for elements already present in the DOM. In order to make it work for elements added after DOM load, you can use jQuery on()
method.
You could trigger some custom event and call slider()
method as follows:
# app/assets/javascripts/projects.js.coffee
$(document).on 'click', 'form .add_fields', (event) ->
...
$(this).before($(this).data('fields').replace(regexp, time)).trigger('show-slider')
..
Then you will listen on the show-slider
event and call slider()
as:
# app/assets/javascripts/input_slider.js.coffee
$ ->
# Execute slider on all inputs with has-slider css class
$('input.has-slider').slider()
$(document).on 'show-slider', (event) ->
$(input.has-slider').slider()
Hope this clears any confusion.
form_for - generate unique ids
You can use Object#object_id
:
... Returns an integer identifier for obj. The same number will be
returned on all calls to id for a given object, and no two active
objects will share an id.
<% object = @document || Document.new %>
<%= form_for object, :html => { multipart: true, id: object.object_id.to_s } do |f| %>
This can be hard to declare own object
for each form_for
, i recommend create array with 5 objects and iterate through it.
Related Topics
How to Log the Entire Trace Back of a Ruby Exception Using the Default Rails Logger
Rails: Logging for Code in the Lib Directory
How to Declare a Variable Shared Between Examples in Rspec
Creating Categories on Jekyll Driven Site
No Database Connection in Rails Console
Ruby on Rails and JSON Parser from Url
How to Generate the First N Prime Numbers
Unicorn Unable to Write Pid File
Installing Gem Fails with Permissions Error
Getting Attribute's Value in Nokogiri to Extract Link Urls
How to Force Ruby to Show a Full Stack Trace
How Are Symbols Used to Identify Arguments in Ruby Methods
Why Are Constants from Extended Module Not Available in Class Methods Declared with Self
What Is the Second Parameter/Argument to CSV.Open( ) in Ruby