Rails uniqueness validation based on relation - ruby-on-rails

I have two models...
create_table "registrations", :force => true do |t|
t.integer "orientation_id"
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "student_id"
...
end
create_table "orientations", :force => true do |t|
t.date "class_date"
t.text "class_time"
t.integer "seats"
t.boolean "active", :default => true
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
I want to create a validation in my registration model that says the student_id must be unique in each Orientation.

If i understood your question correctly,you want the scope option of the validates_uniqueness_of.If so,this should work
In your Registration model,
Class Registration < ActiveRecord::Base
......
validates_uniqueness_of :student_id, scope: :orientation_id
end
And also,you should be generating a migration to add this
add_index :registration, [ :student_id, :orientation_id ], :unique => true
More Info here

Related

wrong number of arguments (1 for 2) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I know there are quite a few questions on this topic here on SO but none of them seem to be the solution for my case. So, I was hoping someone might be able to help.
When I run a migration I get the following error:
CreateEvents: migrating
-- create_table(:events)
-> 0.0558s
-- add_index(:events)
rake aborted!
An error has occurred, this and all later migrations canceled:
wrong number of arguments (1 for 2)
I don't know exactly what I'm looking for and where. I wanted to change my Users table to a Registrations table.
Registrations Controller:
class RegistrationsController < ApplicationController
end
Registration Model:
class Registration < ActiveRecord::Base
attr_accessible :email, :password_digest
end
Registration Migration:
class CreateRegistrations < ActiveRecord::Migration
def change
create_table :registrations do |t|
t.string :email
t.string :password_digest
t.timestamps
end
end
end
Schema.rb:
ActiveRecord::Schema.define(:version => 20130825195829) do
create_table "activities", :force => true do |t|
t.integer "trackable_id"
t.string "trackable_type"
t.integer "owner_id"
t.string "owner_type"
t.string "key"
t.text "parameters"
t.integer "recipient_id"
t.string "recipient_type"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "activities", ["owner_id", "owner_type"], :name => "index_activities_on_owner_id_and_owner_type"
add_index "activities", ["recipient_id", "recipient_type"], :name => "index_activities_on_recipient_id_and_recipient_type"
add_index "activities", ["trackable_id", "trackable_type"], :name => "index_activities_on_trackable_id_and_trackable_type"
create_table "comments", :force => true do |t|
t.string "commenter"
t.text "body"
t.integer "event_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "comments", ["event_id"], :name => "index_comments_on_event_id"
create_table "events", :force => true do |t|
t.string "title"
t.text "text"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
add_index needs 2 arguments example: add_index :events, :title

students and teachers in a class_instruction

Setting up the database, I am just curious if I did it correctly, as it looks a bit off. There are people, who have a user account, and a role (teacher or student). they are participants in a class (where a class has many students and teachers; a student has many classes; a teacher has many classes). I think my class_instruction model is off in the DB, but please tell me if it will work, or if there is a better way (like maybe with a has_many_through table of participants)
schema.rb:
ActiveRecord::Schema.define(:version => 20130524160107) do
create_table "class_instructions", :force => true do |t|
t.string "name"
t.datetime "time"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "person_id"
end
add_index "class_instructions", ["person_id"], :name => "index_class_instructions_on_person_id"
create_table "people", :force => true do |t|
t.string "firstName"
t.string "lastName"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "people", ["user_id"], :name => "index_people_on_user_id"
create_table "roles", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "user_roles", :force => true do |t|
t.integer "user_id"
t.integer "role_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "user_roles", ["role_id"], :name => "index_user_roles_on_role_id"
add_index "user_roles", ["user_id"], :name => "index_user_roles_on_user_id"
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
end
My concern is that the person_id is part of the class. Is this correct?
ClassInsturction.rb :
class ClassInstruction < ActiveRecord::Base
belongs_to :people
has_many :cassignments
has_many :assignments, :through => :cassignments
def className
self.name
end
def classAssignments
return self.cassignments
end
end
I would make a joining table that has both class and people and use has many through. If people have many classes and classes have many people you can not do this any other way.
I have seen usually belongs_to with singular form:
belongs_to :person
I am not sure if this is what you are asking for though.

Restrict attr_accessible to types of user with Ruby on Rails

I am creating a forum software. I want admins and mods to be able to close certain topics.
Codes are sanitized to show only relevant info.
Models
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :bio
has_many :topics, dependent: :destroy
end
class Topic < ActiveRecord::Base
belongs_to :user
attr_accessible :name, :last_post_id, :content
end
Schema for user: admin and mod columns determine admins and mods.
create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "password_digest"
t.string "remember_token"
t.boolean "admin", :default => false
t.text "bio"
t.boolean "mod", :default => false
end
Schema for topic: closed column determines topic's closed status.
create_table "topics", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "forum_id"
t.string "name"
t.integer "last_post_id"
t.integer "views"
t.integer "user_id"
t.boolean "closed", :default => false
t.text "content"
end
I am reluctant to user attr_accessible :closed for TOPIC model because it will be vulnerable to malicious PUT request (correct me if I am wrong).
Is there some way for Rails app to be able to access and modify value of closed column of TOPIC without using attr_accessible, so that only mods and admins can edit them?
I searched on google and found this ascii cast.
Basically, you are looking for dynamic attr_accessible.
If you currently have
class Article < ActiveRecord::Base  
  attr_accessible :name, :content, :closed  
end  
You ca use dynamic attr_accessible like this :
class Article < ActiveRecord::Base  
  attr_accessible :name, :content  
 private  
def mass_assignment_authorizer  
    super + [:closed]  
  end  
end  
I hope I is what you are looking for.
Be sure to check the link I gave you for complete reference.

How to perform a query over models with attributes stored in other models?

I have the following models:
class Constraint < ActiveRecord::Base
belongs_to :constraint_category
end
class ConstraintCategory < ActiveRecord::Base
has_many :constraints
end
The models have these attributes (from db/schema.rb):
create_table "constraint_categories", :force => true do |t|
t.string "value"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "active"
end
create_table "constraints", :force => true do |t|
t.string "phrase"
t.integer "constraint_category_id", :limit => 255
t.boolean "active"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
I would like to create a query that finds all constraints where the "active" attribute is "true" and the "constraint_category.value" is "Noun".
Would love any advice on getting there.
Constraint.joins(:constraint_category).where('constraints.active = ? and constraint_categories.value = ?', true, 'Noun')
See conditions and joins in the guide.

How can I display all tags from all users for a model instance?

I want to get all the tags from all the users in my app for a brand whose ID is 37. The following works but only gets the tags from one of the 2 users currently in the app:
<%= BrandUser.last.brand.tags.join(", ") %>
The following is my attempt but doesn't work:
<%= BrandUser.where(:brand_id => 37).each {|brand| p brand.tags} %>
Brand has_many tags, has_many brand_users and has_many users through brand_users
User has_many :brand_users and has_many :brands, :through => :brand_users
BrandUser belongs_to :brand and belongs_to :user
Below is my schema:
ActiveRecord::Schema.define(:version => 20110824083919) do
create_table "brand_users", :force => true do |t|
t.integer "brand_id"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "brands", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.string "user_id"
end
create_table "taggings", :force => true do |t|
t.integer "tag_id"
t.integer "taggable_id"
t.string "taggable_type"
t.integer "tagger_id"
t.string "tagger_type"
t.string "context"
t.datetime "created_at"
end
add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
create_table "tags", :force => true do |t|
t.string "name"
end
create_table "users", :force => true do |t|
t.string "provider"
t.string "uid"
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Solution:
As per the answer below, running the following in the console gave me the tags I was looking for:
ActsAsTaggableOn::Tagging.where(:taggable_id => 37, :taggable_type => 'Brand', :tagger_type => 'User').includes(:tag)
However running the following also works:
Brand.find(37).all_tags_on(:tags)
Just select the tagging where the taggable_id is the brand_id, the taggable_type is Brand, the tagger_type is User, and include tag.
Tagging.where(:taggable_id => 37, :taggable_type => 'Brand', :tagger_type => 'User').include(:tag)
To do the same but only for users that are associated with the brand, and a :tagger_id field:
Tagging.where(:taggable_id => 37, :taggable_type => 'Brand', :tagger_type => 'User', :tagger_id => User.where('brands.id' => 37).joins(:brands).select('users.id')).include(:tag)

Resources