validate uniqueness in rails4 and case sensitivity fails - ruby-on-rails-4

validates :name, uniqueness: true
The above validates name with case sensitive uniqueness. Any other default validators/options exists to include to case-insensitive checking.
Please help.
Thanks in advance.

I found this code here: https://stackoverflow.com/a/6987482/2754188
You can use this line:
validates :name, uniqueness: { case_sensitive: false }

If you're using a text-column, then the following should easily work:
validates_uniqueness_of :name
The default setting for case_sensitivity is :true and you can even add the following to your validation:
validates_uniqueness_of :name, :case_sensitive => false
This setting is however ignored by non-text columns.

If you are working on uniqueness of a record in Rails app, then please be reminded about this Rails article which says that Rails uniqueness is not fool proof. Scroll down to the bottom of this article Rails - Concurrency and integrity issues to know in detail.
In short, duplicates can still occur during concurrent operations.
I have faced these issue of duplicates in Rails app during concurrency and I had to apply a database level unique index on the table.

Related

Rails 4: ActiveAdmin clears out an array field upon update

I have an ActiveAdmin model registered as such:
ActiveAdmin.register MyModel do
permit_params :name, :synonyms
filter :name
index do
selectable_column
column :name
actions
end
end
I noticed that when I update an object from the ActiveAdmin interface, the synonyms are getting cleared out. Synonyms are an array field defined as such in the PostgreSQL database:
synonyms text[] DEFAULT '{}'::text[]
I tried putting the following in app/admin/my_model.rb:
controller do
def update
permitted_params[:my_model][:synonyms] = JSON.parse permitted_params[:my_model][:synonyms]
super
end
end
and I also tried it with params instead of permitted_params but that doesn't work either. Not sure why ActiveAdmin would be discarding this field. Am I doing something incorrectly? The project I'm working with uses ActiveAdmin 1.0.0.pre4 (I realize this is a dated version).
Any advice would be much appreciated. Thanks in advance!
Notes: Seems this might be a common issue?
I'm not sure if this is applicable to string arrays and I don't know about that specific version of Activeadmin, but I encountered this issue in a slightly different context.
I had a model where the array data types were decimals & integers. I had to explicitly state the type of form input to be used when editing / updating the record or nothing was passed back from the field with the update parameters. Activeadmin chose a number input by default, but it needed to be processed as a string.
form do |f|
f.inputs do
f.input :ages, as :string, :input_html => {:maxlength => '100'}
end
end
I had to set maxlength manually because for some reason it was automatically being set very short. In the model, the string then has to be converted into an actual array before being saved.
def ages= items
if items.is_a? String
items = items.split(' ')
items.each do |i|
i.to_i
end
end
super items
end

Activerecord uniqueness validation ruby on rails 4.2

I just started trying my hands on Ruby on rails . i have created a mode states and want that every state name must remain unique so i used
uniqueness: true
as per http://guides.rubyonrails.org/active_record_validations.html .
As the above document says that the validation is invoked automatically when object.save is called. but When i try to save the objects with same state_name value , no exception is thrown and the record is saved. Can one please help where i am doing it wrong.
Model code
class State < ActiveRecord::Base
acts_as_paranoid
validates_presence_of :state_name ,uniqueness: true
end
Controller code
def create
#stateName = params[:stateName];
#state = State.new();
#state.state_name=#stateName;
if(#state.save())
resp = { :message => "success" }
else
resp = { :message => "fail" }
end
respond_to do |format|
format.json { render :json => resp }
end
end
Thanks in advance for helping!
If you want uniqueness check, change
validates_presence_of :state_name ,uniqueness: true
to
validates :state_name, uniqueness: true
If you want uniqueness and presence check both, use
validates :state_name, uniqueness: true, presence: true
An alternate syntax is shown below, however, syntax shown above should be preferred
validates_uniqueness_of :fname
validates_presence_of :fname
Also, as per documentation, please note following with respect to usage of uniqueness: true
It does not create a uniqueness constraint in the database, so it may
happen that two different database connections create two records with
the same value for a column that you intend to be unique. To avoid
that, you must create a unique index on both columns in your database.
The validation happens by performing an SQL query into the model's
table, searching for an existing record with the same value in that
attribute.
What this means is that it is possible that if multiple users are trying to save records concurrently, there is a possibility records with duplicate state_name can get created as each save is happening on different thread

Rolify and Rails 4 role management

I am trying to implement a role based access system in my rails 4 app, and I want the end user (super_admin) to have the ability to edit role assignments via the UI.
I have achieved some success but can't help feeling that there has to be a better way (Since I'm new to rails). Here is my code:
users_roles_controller.rb
# GET /user_roles/new/:id
def new
#roles = Role.all
end
# POST /user_roles/new/:id
def create
populated = params[:roles][:name].reject(&:empty?)
populated.each do |key|
#user.add_role Role.find(key).name
end
redirect_to users_path
end
And in my Form (HAML and simple_form):
= simple_form_for :roles, :url => create_user_roles_path(#user.id), :method => "post" do |f|
= f.input :name, :collection => #roles, as: :check_boxes
= f.button :submit
I'm struggling with the following:
How do I validate form entries, since there is no model?
Should I be using strong parameters and if so how do I implement on a form without a model
How do I create something similar, but with Current roles already checked? (True role management)
UPDATE
I have looked at using the reform Gem as suggested by the comments. This seems like a great solution. I am however having issues with the implementation on this case.
Let me map it out:
I have 3 tables in the database:
users
users_roles (Mapping Table with 2 Attributes : user_id & role_id {Join Table -> HABTM})
roles
I want to construct a form with all the values in the Roles model as checkboxes.The checkboxes should dictate what values are fed into the users_roles table (With relation to a specific user). What I want reform to do is validate the input of this form. This form will always display all of the values in Roles, but some/all of the boxes might be unchecked.
I have created a form folder in my app and started with the following code:
class UserRoleForm < Reform::Form
property :user__id, on: :user
property :role_id, on: :role
validates :user__id, presence: true
validates :role__id, presence: true
end
Am I going in the right direction?
Thanks for the help.
You need two things to build your form: a user's roles and the possible roles.
If I recall correctly, rolify gives your model associations ad should just let you do something like some_user.roles to return all the roles applied to some_user.
To get possible roles, try Role.all.
To combine both, try
user_roles = some_user.roles.pluck(:name) # suppose this returns ["admin"]
Role.pluck(:name).map { |r| [r, user_roles.include?(r)] }
You now have an array like this that you can use to build your form checkboxes with an each loop.
[["customer", false], ["admin", true], ["editor", false]]
Define your reform object's sync or save method to handle what to do with the submitted input, however you are handling it. You can (SHOULD) make a custom validation to verify if the submitted roles are valid roles.

Rails 4 validates presence conditional "style"

I'm trying to DRY this up a bit, but can't figure out what the syntax might be. I have two fields that I want to conditionally validate presence of: link and text. Each should require presence if the other is not #present?, but require absence if the other is #present?
This is as short as I can get it and it feels icky having to have each field broken into two parts.
validates :link,
presence: true,
unless: "text.present?",
validates_absence_of :link, if: "text.present?"
validates :text,
presence: true,
unless: "link.present?"
validates_absence_of :text, if: "link.present?"
Can anyone else help a n00b make it cleaner?
Thanks in advance.
Found Solution
I ended up going with the below solution with help from here.
validate :either_or
private
def either_or
if !(link.blank? ^ text.blank?)
errors[:base] << "Specify a link or text, but not both."
end
end
Answering my own question ;)
I ended up going with the below solution with help from here.
validate :either_or
private
def either_or
if !(link.blank? ^ text.blank?)
errors[:base] << "Specify a link or text, but not both."
end
end

Rails 4 - unit test failing to create model object

I want to unit test an application using shoulda.
In the test i'm doing
User.create!(name: "James")
When i run the test i'm getting the following error:
ActiveRecord::StatementInvalid: Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `users` (`created_at`, `updated_at`, `id`) VALUES ('2014-04-07 12:03:07', '2014-04-07 12:03:07', 980190962)
Has this something to do with rails 4 strong parameters?
How can i solve this?
Check if you have invalid fixtures laying around. Try deleting/fixing test/fixtures/users.yml
Note: You should get full stacktraces in the unit tests by disabling the backtrace silencers in config/initializers/backtrace_silencers.rb.
Has this something to do with rails 4 strong parameters?
No, Strong Parameters have nothing to do with this because you are creating your object directly from a hash and not from any ActionController::Parameters.
The issue comes from somewhere else (probably your database).
As I can see from this article, a solution to your problem could be to migrate your field like that:
change_column :users, :name, :string, :limit => 255, :null => false, :default => ''
I got similar issue while running unit tests. This may happen if your mysql DB connection is in strict mode. Disable strict mode by adding setting in database.yml as below and try.
test:
database:
host: localhost
name: test_db
username: username
password: password
strict: false