Rails renaming the routing - ruby-on-rails

I am trying to rename the routing of my email inputs for my rails app. Currently, when someone inputs their email, it routes them to /:controller/:id
I want to do it such that once they input their email, it won't show their id so they cannot change the id number and see other people's emails.

I think, use a permalink with some alphanumeric give secure email from another. for Assumes you have people model.
You only need to add one attribute to people, attribute name is permalink
try run
rails g migration add_permalink_to_peoples permalink:string
rake db:migrate
On people.rb , play with before_save
class People < ActiveRecord::Base
attr_accessible :email, :permalink
before_save :make_it_permalink
def make_it_permalink
# this can create permalink with random 8 digit alphanumeric
self.permalink = SecureRandom.base64(8)
end
end
And your routes.rb
match "/people/:permalink" => 'peoples#show', :as => "show_people"
on peoples_controller.rb
def show
#people = People.find_by_permalink(params[:permalink])
end
Run rails server and add one people.
People have a unique permalink with random 8 digit alphanumeric (e.g /people/:permalink)
example : http://localhost:3000/people/9sd98asj

EDIT:
i was trying my self and this dosn't works if its an email, but if you try it with a username with no special carracters it will work fine !
try something like this:
routes:
match "/controller/:username" => "controller#show"
controller:
def show
#user = find_by_username(params[:username])
end

Related

Setting default username in Rails

I am using devise gem for user management. So, I have a User model.
What I want to be able to do is have a username column in the User model. By default, I want to be able to set the default username for users as 'user'+id where id is unique for every user and a column in User model.
I want to be able to do something like:
class AddColsToUser < ActiveRecord::Migration[6.1]
def change
add_column :users, :username, :string, default: 'user'+id
end
end
Is that possible? Thanks for reading :))
I would recommend using a before_validation callback to create a new username. You can expand this a bit to keep retrying in case of failure, but this should hopefully help you get started.
Make sure to add a unique constraint or validation as well!
before_validation :set_username
private
def set_username
return if user.blank?
username = "{user}_#{rand(100)}"
end
Another option if you just want a prettier parameter in your url's is to override the to_param method in your user model. This will give you a friendly url like "1-my-name", but when parsed to an integer will just be "1" so rails will still find it when doing lookups.
def to_param
[id, name.parameterize].join("-")
end

Is there a way to generate a unique integer permalink?

I am trying to create a unique numeric permalink in rails. My problem is that I need to make sure it is unique, has between 5 and 7 numbers and is randomly generated (so not simply counting up). I did look at FriendlyID but I am not sure if this can deliver what I need - the url for my permalink should eventually look like this:
www.kreelu.com/4325677
Is there a build in feature or a gem that can provide this?
Thanks!
after_validation :set_permalink
def rand_permalink #you can find a better way to exclude loop db-searches
r = rand.to_s[2..8] # 7-digit random, you can make [2..11] for 10-digits and so on
while find_by_permalink(r).present?
r = rand.to_s[2..8]
end
r
end
def set_permalink
permalink = rand_permalink unless permalink.presence
end
Assuming you want to create the unique permalink on create, you want to store it in your database and the class is named Post:
validate :permalink, :uniqueness => true
before_create :create_permalink
private
def create_permalink
loop do
self.permalink = Array(1..7).map{ rand(10).to_s }.join
return if Posts.where(permalink: permalink).blank?
end
end

Friendly ID Random Url

I am using friendly for my site, and at the moment I have it displaying the title in the url
ie: /articles/hello-world
but say when i create the page, it generates a random number, to avoid duplication
so
ie: /articles/75475848
I know if i get rid of friendly id it will display numbers but
it will be
/articles/1
/articles/2
etc...
Basically how do i get it to show /articles/23456789(random number) instead of /articles/hello-world
Thanks
It seems that generating a UUID (Universally Unique Identifier) for each article might be a good solution for you.
The Ruby standard library gives us a UUID-generating method, so all you need to do is create a database field and then use a before_save callback to give each article its own UUID. Like this:
class Article < ActiveRecord::Base
before_save :set_uuid
def set_uuid
self.uuid = SecureRandom.uuid if self.uuid.nil?
end
end
Edit: No need for external dependencies as per #olleolleolle's comment!
From the FriendlyID docs:
class Person < ActiveRecord::Base
friendly_id :name_and_location
def name_and_location
"#{name} from #{location}"
end
end
bob = Person.create! :name => "Bob Smith", :location => "New York City"
bob.friendly_id #=> "bob-smith-from-new-york-city"
So, if you provide a method for friendly_id that generates a random number that method will be used to generate the slug instead.

Handling permalink user update when permalink is already taken Rails 3.2

I wanted some advice about how to handle to_param in regards to permalinks
Basically this is what happens.
Create a new company
The company :name is then parameterized and saved as a :permalink in the db
Updating an existing company enables you to change the :permalink
There are validations to ensure user updated :permalink is unique
The problem I'm having is occurring when updating the company's :permalink to something that already exists. The uniqueness validation works which is great, but it changes the params[:id] to the invalid permalink instead of reseting and using the existing params[:id]
When I try to edit the permalink to something else I get a flash validation error of "Name already taken" because it thinks I'm editing the company of the already existing :permalink (company). The URL reflects the change in permalink since my companies_controller.rb is using #company = Company.find_by_permalink[:id])
I wanted to know the best way to handle this issue?
class Companies < ActiveRecord::Base
before_create :set_permalink
before_update :update_permalink
attr_accessible :name, :permalink
validates :name, :permalink, uniqueness: { message: 'already taken' }
def to_param
permalink
end
private
def set_permalink_url
self.permalink = name.parameterize
end
def update_permalink_url
self.permalink = permalink.parameterize
end
end
Apologies if I'm not making too much sense.
Thanks in advance.
you could try to handle this with an after_rollback callback.
after_rollback :restore_permalink
def restore_permalink
self.permalink = permalink_was if permalink_changed?
end
here's how it works : every update / destroy in Rails is wrapped in a transaction. If the save fails, the transaction rollbacks and triggers the callback.
The callback then restores the old value (permalink_was) if it was changed since the record has been loaded.
See ActiveModel::Dirty and ActiveRecord::Transactions for more info.
EDIT
On the other hand, there may be another solution (untested) - just define your accessor like this :
def permalink=( value )
permalink_will_change! unless #permalink == value
#permalink = value
end
This way, the permalink will not be marked as dirty if the new value is identical to the old one, and so AR will not try to update the column.
Explanation:
i don't know on which version of rails it was implemented (it is relatively recent), but here's how "dirtyness" works :
your "standard" (automagically generated) attribute setters basicly call
#{your_attribute}_will_change! before setting the associated
instance variable (even if you set the exact same value than before)
when you call save, ActiveRecords looks for attributes that have changed ("dirty") and builds the SQL UPDATE query using ONLY these attributes (for performance reasons, mostly)
so if you want to avoid your permalink to appear in the query when it is unchanged, i think you have to override the standard setter - or avoid mass-assignment and only set permalink if it has changed

Rails 3.1 attr_accessible verification receives an array of roles

I would like to use rails new dynamic attr_accessible feature. However each of my user has many roles (i am using declarative authorization). So i have the following in my model:
class Student < ActiveRecord::Base
attr_accessible :first_name, :as=> :admin
end
and i pass this in my controller:
#student.update_attributes(params[:student], :as => user_roles)
user_roles is an array of symbols:
user_roles = [:admin, :employee]
I would like my model to check if one of the symbols in the array matches with the declared attr_accessible. Therefore I avoid any duplication.
For example, given that user_roles =[:admin, :employee]. This works:
#student.update_attributes(params[:student], :as => user_roles.first)
but it is useless if I can only verify one role or symbol because all my users have many roles.
Any help would be greatly appreciated
***************UPDATE************************
You can download an example app here:
https://github.com/jalagrange/roles_test_app
There are 2 examples in this app: Students in which y cannot update any attributes, despite the fact that 'user_roles = [:admin, :student]'; And People in which I can change only the first name because i am using "user_roles.first" in the controller update action. Hope this helps. Im sure somebody else must have this issue.
You can monkey-patch ActiveModel's mass assignment module as follows:
# in config/initializers/mass_assignment_security.rb
module ActiveModel::MassAssignmentSecurity::ClassMethods
def accessible_attributes(roles = :default)
whitelist = ActiveModel::MassAssignmentSecurity::WhiteList.new
Array.wrap(roles).inject(whitelist) do |allowed_attrs, role|
allowed_attrs + accessible_attributes_configs[role].to_a
end
end
end
That way, you can pass an array as the :as option to update_attributes
Note that this probably breaks if accessible_attrs_configs contains a BlackList (from using attr_protected)

Resources