Rails Validate Uniqueness Isn't Working - ruby-on-rails

Model Code (Attempting to require uniqueness for embed_code)
https://gist.github.com/1427851:
class Link < ActiveRecord::Base
validates :embed_code,
:format => {:with => /^<object type|^<embed src|^<object width|^<iframe src|^<object height|^<iframe width|^<embed id|^<embed width|^<object data|^<div|^<object id/i, :message => "Invalid Input"},
:uniqueness => true
attr_accessible :title, :embed_code, :score
after_initialize :calculate_score, :favs_count
attr_accessor :score, :fav_count
validates :title, :length => { :in => 4..45, :message => "Must be between 4 & 45 characters"}
before_save :resize
has_many :favorites
has_many :favorited, :through => :favorites, :source => :user
belongs_to :user
I've tried validates_uniqueness_of :embed_code and disabling (commenting out) non-critical components of the model such as :before_save :resize

Related

Translating Database Models to Models on Ruby On Rails

I am beginning Ruby On Rails through a purchase/resale platform project at school. I'm having an issue with my models when I try to translate them from my relational model.
Firstly, I've modelled my database. Here is simplified the entity-relationship model :
I've then translated it in a relational model :
Finally, I've implemented it in Ruby On Rails.
I've implemented a model Client :
class Client < ApplicationRecord
attr_accessor :name
validates :name, :presence => true
has_many :purchasings, :dependent => :destroy
has_many :sellers, :through => :purchasings
has_many :articles, :through => :purchasings
end
I've implemented a model Seller :
class Seller < ApplicationRecord
attr_accessor :name
validates :name, :presence => true
has_many :purchasings, :dependent => :destroy
has_many :sellers, :through => :purchasings
has_many :articles, :through => :purchasings
end
I've implemented a model Article
class Article < ApplicationRecord
attr_accessor :quantity
validates :quantity, :presence => true
has_one :purchasing, :dependent => :destroy
has_one :client, :through => :purchasings
has_one :seller, :through => :purchasings
end
I've implemented a model Purchasing :
class Purchasing < ApplicationRecord
attr_accessor :client_id, :seller_id, :article_id
belongs_to :client, :class_name => "Client"
belongs_to :seller, :class_name => "Seller"
belongs_to :article, :class_name => "Article"
validates :client_id, :presence => true
validates :seller_id, :presence => true
validates :article_id, :presence => true
end
I've modified the Purchasing database migration :
class CreatePurchasing < ActiveRecord::Migration[5.1]
def change
[...]
add_index :purchasings, :client_id
add_index :purchasings, :seller_id
add_index :purchasings, :article_id
add_index :purchasings, [:client_id, :seller_id], :unique => true
end
def down
[...]
end
end
I know this is incorrect because when I execute the following code on the Rails console :
cl1 = Client.create(:name => "John")
cl2 = Client.create(:name => "James")
sel1 = Seller.create(:nom => "Jack")
sel2 = Seller.create(:nom => "Jil")
a1 = Article.create(:quantity => 5)
p1 = Purchasing.new(:client => cl1, :client_id => cl1.id, :seller => sel1, :seller_id => sel1.id, :article => a1, :article_id => a1.id)
p1.save
p2 = Purchasing.new(:client => cl2, :client_id => cl2.id, :seller => sel1, :seller_id => sel1.id, :article => a1, :article_id => a1.id)
p2.save
p2.save returns true whereas an article can't be sold by a same seller and bought by two clients different.
You are adding the index on incorrect columns on purchasings table. As per the requirement, the article_id and seller_id should not get repeated ideally. So you actually need is a uniqueness constraint on seller_id, and article_id column. You can do so by creating an unique index on the composition of two columns seller_id, and article id on the database layer. You should also add the application layer validation on the purchasing model.
class Purchasing < ApplicationRecord
attr_accessor :client_id, :seller_id, :article_id
belongs_to :client, :class_name => "Client"
belongs_to :seller, :class_name => "Seller"
belongs_to :article, :class_name => "Article"
validates :client_id, :presence => true
validates :seller_id, :presence => true
validates :article_id, :presence => true
validates :article_id, uniqueness: {scope: :seller_id}
end
Now you should also write a database migration to add the unique index on these two columns.
class AddUniquenessConstraintInPurshasing < ActiveRecord::Migration
def change
add_index :purchasings, [:article_id, :seller_id], :unique => true
end
end

Scopes doesn't work with STI

I want to do STI in Rails.
class AbstractUser < ActiveRecord::Base
self.table_name = 'users'
belongs_to :organization, :inverse_of => :users
# reporter user
has_many :requests, :dependent => :destroy
# startup user
has_many :responses, :dependent => :destroy
has_many :startup_requests, :through => :responses, :source => :request
scope :reporters, where(:type => 'Reporter')
scope :startup_employees, where(:type => 'Startup')
scope :on_waitlist, where(:waitlist => true)
scope :not_on_waitlist, where(:waitlist => false)
end
require 'rfc822'
class User < AbstractUser
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :confirmable
validates :name, :presence => true
validates :surname, :presence => true
validates :title, :presence => true
validates :password, :presence => true, :length => { :minimum => 8 }
validates :email, :presence => true, :format => { :with => RFC822::EMAIL_REGEXP_WHOLE }
attr_accessible :name, :surname, :title, :organization,
:email, :password, :fullname
end
require 'rfc822'
class UserForAdmin < AbstractUser
validates :email, :presence => true, :format => { :with => RFC822::EMAIL_REGEXP_WHOLE }
validates :organization_id, :presence => true
attr_accessible :name, :surname, :title, :organization, :email,
:password, :fullname, :password_confirmation, :type,
:organization_id, :waitlist, :invitation_token
end
And there is some problem with these scopes.
Couldn't find UserForAdmin with id=7 [WHERE "users"."type" IN ('UserForAdmin') AND "users"."waitlist" = 'f']
I also tried to put these scopes in UserForAdmin instead of AbstractUser with the same result. I (probably) need scopes instead of custom methods, because I use them in ActiveAdmin. How can I solve this?
If you don't want to receive all users, you need to query with the base class. In a simpler example:
class Animal < ActiveRecord::Base
end
class Dog < Animal
end
class Cat < Animal
end
Dog.create
Cat.create
Animal.all
=> [dog, cat]
Dog.all
=> [dog]
Cat.all
=> [cat]
So, in your case, you'd want to:
AbstractUser.not_on_waitlist.find(params[:id])
If this user is a UserForAdmin you'll receive an object of class UserForAdmin. If it's just a user, you'll receive an object of class User

rails counter cache and foreign key test

This is my favorite designer model
favorite_designer.rb
class FavoriteDesigner < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :designer, :class_name => "User", :foreign_key => :designer_id
validates_presence_of :user_id
validates_presence_of :designer_id
validates_numericality_of :user_id, :unless => Proc.new{|f| f.user_id.blank?}
validates_numericality_of :designer_id, :unless => Proc.new{|f| f.designer_id.blank?}
end
How can I test :counter_cache => true and :foreign_key => :designer_id in rspec with shoulda?
You can use counter_cache and with_foreign_key shoulda matchers :
it { should belong_to(:organization).counter_cache(true) }
it { should have_many(:worries).with_foreign_key('worrier_id') }
For full doc and examples look at :
Counter cache doc
Foreign key doc

Validate presence in this belongs_to

I have products and brands
products model:
class Product < ActiveRecord::Base
attr_accessible :brand_id, :title
belongs_to :brand
validates :title, :presence => true
validates :brand, :presence => {:message => 'The brand no exists'}
end
and the brands model
class Brand < ActiveRecord::Base
attr_accessible :name
validates :name, :presence => true
has_many :products, :dependent => :destroy
end
I want to validate if exist a product with a name in this brand.
I mean I could have 2 products with the same name in different brands but not in the same brand.
You could use the uniqueness validation with a scope:
validates :name, :uniqueness => { :scope => :brand_id }
Note that you have to specify :brand_id instead of :brand, because the validation can't be made on the relation.
If you don't know it, I suggest you to read the Active Record Validations and Callbacks guide.
NB: the syntax {:foo => 'bar'} is replaced (since Ruby 1.9.2) with {foo: 'bar'}.

Choose from foreign keys in rails admin not working

Following is my models:
class Poll < ActiveRecord::Base
attr_accessible :published, :title
validates :published, :presence => true
validates :title, :presence => true,
:length => { :minimum => 10 }
has_many :choice, :dependent => :destroy
end
class Choice < ActiveRecord::Base
belongs_to :poll
attr_accessible :choice_text, :votes
validates :choice_text, :presence => true
end
I then tried to install the rails admin. I was able to create the choices and polls in the admin, but i was unable to associate a choice with a poll and vice versa.
How can i do it?
First of all in has_many class name should be in plural:
has_many :choices
And you should add attr_accessible poll_id or choice_ids for Model from which you want to edit this association. Or just delete all attr_accessible for first try.
class Poll < ActiveRecord::Base
attr_accessible :published, :title, choice_ids
validates :published, :presence => true
validates :title, :presence => true, :length => { :minimum => 10 }
has_many :choices, :dependent => :destroy
end
class Choice < ActiveRecord::Base
belongs_to :poll
attr_accessible :choice_text, :votes, :poll_id
validates :choice_text, :presence => true
end
There is no attr_accessible in Rails 4. Use accepts_nested_attributes_for instead. More info:
https://github.com/sferik/rails_admin/wiki/Belongs-to-association

Resources