Rails test introduced the following warning when I was testing my model. What modifications should I make to my model,
rake test test/models/user.rb
[RailsAdmin] RailsAdmin initialization disabled by default. Pass SKIP_RAILS_ADMIN_INITIALIZER=false if you need it.
DEPRECATION WARNING: The following options in your User.has_many :incoming_friends declaration are deprecated: :conditions. Please use a scope block instead. For example, the following:
has_many :spam_comments, conditions: { spam: true }, class_name: 'Comment'
should be rewritten as the following:
has_many :spam_comments, -> { where spam: true }, class_name: 'Comment'
. (called from <class:User> at /home/divya/projects/shufflejoy/app/models/user.rb:9)
and this is my user model,
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :user_name , :email, :first_name ,:last_name , :presence => true
has_many :invitations
has_many :incoming_friends , :class_name => "User" , :foreign_key=>"friend_id" , :through => :invitations, :conditions => ["status = 1"]
has_many :outgoing_friends , :class_name => "User" , :foreign_key=>"user_id", :through => :invitations, :conditions => ["status = 1"]
end
You need to write your association conditions as callable objects. Like so:
has_many :incoming_friends, -> { where(:status => '1') }, :class_name => "User", :foreign_key => "friend_id", :through => :invitations
has_many :outgoing_friends, -> { where(:status => '1') }, :class_name => "User", :foreign_key => "user_id", :through => :invitations
More info at the official Rails docs: http://guides.rubyonrails.org/association_basics.html#scopes-for-has-many
Related
New to RoR, here couldn't find the solution I was looking for so I'm typing my problem here:
I have a web app where after the user is logged in they will be redirected to a dashboard that shows them their various information.
For now - as I'm getting the feel of RoR - the view of the dashboard was suppose to get a lot of information:
def index
#logged_user = Person.includes(:user, :addresses).find(session[:user_id])
end
but when I checked using #logged_user.inspect it only gave me this
#<Person (person model attributes here) >
I checked the log and it seems the User and Addresses were loaded
printscreen of my log http://prntscr.com/c40fee
but they aren't in the #logged_user variable... did I miss a step here? where did I go wrong?
EDIT:
here's the model of Person
class Person < ActiveRecord::Base
validates :first_name, :last_name, presence: true
has_one :user, :dependent => :destroy
has_one :medical_record
has_many :addresses, :dependent => :destroy
has_many :contacts,:dependent => :destroy
has_many :enrollments_as_student, :class_name => 'Enrollment', :foreign_key => :student_id, :dependent => :destroy
accepts_nested_attributes_for :addresses, allow_destroy: true
accepts_nested_attributes_for :contacts, allow_destroy: true
accepts_nested_attributes_for :medical_record, allow_destroy: true
end
model for User
class User < ActiveRecord::Base
validates :username, presence: true
validates :username, :password, format: {with: /\A[a-zA-Z0-9 ñÑ]+\Z/, message: "Special characters aren't allowed"}
validates :username, uniqueness: {message: "username is already taken"}
has_secure_password
belongs_to :person
end
model for Addresses
class Address < ActiveRecord::Base
validates :street, :barangay, :city, :province,
presence: {message: "Fill in all necessary fields"}
validates :zipcode,
numericality: {message: "Zipcodes should only contain numbers"},
length: {minimum: 4, maximum: 4, message: "Invalid zipcode length"}
belongs_to :person
end
also snippet for the login
def login
#user = User.find_by_username(params[:receptions][:username])
if #user && #user.authenticate(params[:receptions][:password])
session[:user_id] = #user.person_id
flash[:notice] = "You have succfully logged in"
redirect_to '/dashboards'
else
flash[:notice] = "Invalid username or password"
redirect_to '/login'
end
Following a tutorial for adding favorites to my existing project, whereby users can favorite property listings but can't get past the error below:
Routing error,uninitialized constant FavoriteRoomsController
favoriterooms_controller.rb
class FavoriteRoomsController < ApplicationController
before_action :set_room
def create
if Favorite.create(favorited: #room, user: current_user)
redirect_to #room, notice: 'Room has been favorited'
else
redirect_to #room, alert: 'Something went wrong...*sad panda*'
end
end
def destroy
Favorite.where(favorited_id: #room.id, user_id: current_user.id).first.destroy
redirect_to #room, notice: 'Room is no longer in favorites'
end
private
def set_room
#room = Room.find(params[:room_id] || params[:id])
end
end
room.rb
class Room < ActiveRecord::Base
belongs_to :user
has_many :photos
has_many :favorites
geocoded_by :address
after_validation :geocode, if: :address_changed?
validates :home_type, presence: true
validates :room_type, presence: true
validates :accommodate, presence: true
validates :bed_room, presence: true
validates :bath_room, presence: true
validates :listing_name, presence: true, length: {maximum: 50}
validates :summary, presence: true, length: {maximum: 500}
validates :address, presence: true
validates :lister_type, presence: true
validates :gender_type, presence: true
validates :occupation_type, presence: true
validates :move_in, presence: true
validates :term, presence: true
validates :term, presence: true
end
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :omniauthable
validates :fullname, presence: true, length: {maximum: 50}
has_many :rooms
has_many :favorites
has_many :favorite_rooms, through: :favorites, source: :favorited, source_type: 'Room'
def self.from_omniauth(auth)
user = User.where(email: auth.info.email).first
if user
return user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.fullname = auth.info.name
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.image = auth.info.image
user.password = Devise.friendly_token[0,20]
end
end
end
end
favorite.rb
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :favorited, polymorphic: true
end
routes.rb
Rails.application.routes.draw do
root 'pages#home'
devise_for :users,
:path => '',
:path_names => {:sign_in => 'login', :sign_out => 'logout', :edit => 'profile'},
:controllers => {:omniauth_callbacks => 'omniauth_callbacks',
:registrations => 'registrations'
}
resources :users, only: [:show]
resources :rooms
resources :photos
resources :conversations, only: [:index, :create] do
resources :messages, only: [:index, :create]
end
resources :favorite_rooms, only: [:create, :destroy]
end
roomshow.html.erb
favorites button link code added in my roomsshow.html.erb
<%- unless current_user.favorite_rooms.exists?(id: #room.id) -%>
<%= link_to 'Add to favorites', favorite_rooms_path(room_id: #room), method: :post %>
<%- else -%>
<%= link_to 'Remove from favorites', favorite_room_path(#room), method: :delete %>
<%- end -%>
favorite_rooms_path POST /favorite_rooms(.:format) favorite_rooms#create
favorite_room_path DELETE /favorite_rooms/:id(.:format) favorite_rooms
Screenshot of error message with full trace
I've watched various tututorials and followed numerous suggestions but dont seem to be able to solve the issue by myself.
Routing error,uninitialized constant FavoriteRoomsController
Rails follow naming conventions very strictly and for a good reason. It expects the file names to be in a snake case. So you should change the file name favoriterooms_controller.rb to favorite_rooms_controller.rb
I have manually specified the relationships in the models (haven't found a way how to automatically generate them from a ERD model or an existing database) and than tried to generate a migration containing the FKs using the immigrant gem. I am getting:
rails generate immigration AddKeys
lib/active_support/dependencies.rb:478:in `load_missing_constant': Circular dependency detected while autoloading constant Assignment (RuntimeError)
from /Users/nnikolo/.rvm/gems/ruby-2.0.0-p451#railstutorial_rails_4_0/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:180:in `const_missing'
from /Users/nnikolo/.rvm/gems/ruby-2.0.0-p451#railstutorial_rails_4_0/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:512:in `load_missing_constant'
from /Users/nnikolo/.rvm/gems/ruby-2.0.0-p451#railstutorial_rails_4_0/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:180:in `const_missing'
Here is the code for the models:
class Account < ActiveRecord::Base
include Person
include Contact
has_many :coworkers, :class_name => 'Coworker'
has_many :customers, :class_name => 'Customer'
has_many :locations, :class_name => 'Location'
has_many :appointment_types, :class_name => 'AppointmentType'
before_create :create_remember_token
has_secure_password
validates :password, length: { minimum: 6 }
validates :rem_notice_hrs, presence: true
validates :rem_notice_hrs, numericality: true
validates :rem_text, presence: true
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
after_initialize :init
def Account.new_remember_token
SecureRandom.urlsafe_base64
end
def Account.digest(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def init
if self.new_record?
if self.rem_notice_hrs.nil?
self.rem_notice_hrs = 24
end
if self.rem_text.nil?
if self.company.nil?
self.rem_text = "Dear [customer title: automatic] [customer family name: automatic], this is a reminder of your appointment with %{title} %{family_name} on [date/time]."
else
self.rem_text = "Dear [title] [customer family name], this is a reminder of your appointment with %{company} on [date/time]."
end
end
end
end
def create_remember_token
self.remember_token = User.digest(User.new_remember_token)
end
end
class Location < ActiveRecord::Base
belongs_to :coworker, :class_name => 'Coworker', :foreign_key => :wor_id
belongs_to :appointment, :class_name => 'Appointment', :foreign_key => :app_id
#optional deletion flag:
validates_inclusion_of :deleted, in: [true, false]
end
class Coworker < ActiveRecord::Base
include Person
validates_inclusion_of :deleted, in: [true, false]
belongs_to :account, :class_name => 'Account', :foreign_key => :acc_id
has_many :assignments
end
class Location < ActiveRecord::Base
belongs_to :coworker, :class_name => 'Coworker', :foreign_key => :wor_id
belongs_to :appointment, :class_name => 'Appointment', :foreign_key => :app_id
validates_inclusion_of :deleted, in: [true, false]
end
class Appointment < ActiveRecord::Base
belongs_to :customer, :class_name => 'Customer', :foreign_key => :cus_id
belongs_to :location, :class_name => 'Location', :foreign_key => :loc_id
belongs_to :appointment_type, :class_name => 'AppointmentType', :foreign_key => :app_type_id
has_many :assignments, :class_name => 'Assignment'
has_many :reminders, :class_name => 'Reminder'
validates_date :from, :on_or_after => :today
validates_date :till, :on_or_after => :from
validates_inclusion_of :deleted, in: [true, false]
attr_accessor :title
end
Some of the models above implement the following concerns:
module Contact
extend ActiveSupport::Concern
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
# phone attribute
included do
validates :phone, presence: true
validates :phone, numericality: true
attr_accessor :company
end
#email regex
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
end
module Person
extend ActiveSupport::Concern
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
included do
# deleted flag attribute
attr_accessor :first_name, :family_name, :title
end
end
Can you tell what's going wrong here?
This is a classical example of a copy-paste mess - I've copied the code of Location.rb into Assignment.rb, edited it but forgot to re-name the class. So I end up having two Location models - in 2 different rb files. Doh!
I am following the HABTM Railscast #17 on using checkboxes to create associated records using a join table.
I finally got my records to save to the join table....but I can't control them by checking or unchecking a box....meaning unchecking the record does nothing and leaving the record checked makes ANOTHER duplicate record.
I have 3 tables.
:project has_many :restrictions, :through => :project_restrictions
What I'd like to be able to do is have an array of checkboxes that I can check to create :project_restrictions...or, if I uncheck them, the remove the :project_restriction record.
Right now it just keeps saving multiple records and does not delete them if I uncheck one.
I have put all my logic in the ProjectsController and am running the method for adding the :project_restrictions through a custom PATCH method called "add_restrictions". Should this be a POST? I can't figure out if I'm PATCHING Project by adding associated records or POSTING just the associated records.
my join table has an :id and no :timestamps .... I don't know if this matters....obviously, I'm new.
I am using rails 4.
MY MODELS
class Project < ActiveRecord::Base
has_many :project_restrictions, dependent: :destroy
has_many :restrictions, :through => :project_restrictions
accepts_nested_attributes_for :project_restrictions, allow_destroy: true, :reject_if => :all_blank
class Restriction < ActiveRecord::Base
has_many :projects, :through => :project_restrictions
has_many :project_restrictions, dependent: :destroy
class ProjectRestriction< ActiveRecord::Base
belongs_to :restriction
belongs_to :project
end
**My PATCH Controller Method to Create Associated Records **
def add_restrictions
#diet = Restriction.k1.order(:name)
#project = Project.find(params[:p])
params[:project][:restriction_ids].reject!(&:empty?).each do |restriction|
#proj_rule = ProjectRestriction.create!(:project_id => #project.id, :restriction_id => restriction)
#proj_rule.save
end
respond_to do |format|
format.html { redirect_to t1s3_path(:p => #project.id ) ,
notice: 'Success! You added restrictions!' }
format.json {}
end
end
And my form
<%= form_for #project, url: add_restrictions_path(:p => #project.id) do |f| %>
<div class=" fields ">
<%= hidden_field_tag "project[restriction_ids][]", nil %>
<% #diet.each do |restriction| %>
<%= check_box_tag "project[restriction_ids][]", restriction.id,
#project.restriction_ids.include?(restriction.id), id: dom_id(restriction)%>
<%= label_tag dom_id(restriction), restriction.name %><br>
<% end %>
</div>
<%= f.submit %>
UPDATE:
I have updated my Models to have "uniq and inverse_of ....however I'm still creating duplicate records and unable to destroy them by unchecking the checkbox
class Project < ActiveRecord::Base
has_many :project_restrictions -> { uniq }, dependent: :destroy, inverse_of: :project
has_many :restrictions, -> { uniq }, through: :project_restrictions
accepts_nested_attributes_for :project_restrictions, allow_destroy: true, :reject_if => :all_blank
class Restriction < ActiveRecord::Base
has_many :projects, -> { uniq }, through: :project_restrictions
has_many :project_restrictions, -> { uniq }, dependent: :destroy, inverse_of: :restriction
class ProjectRestriction< ActiveRecord::Base
belongs_to :restriction, -> { uniq }, inverse_of: :project_restrictions
belongs_to :project, -> { uniq }, inverse_of: :project_restrictions
end
change this in your add_restrictions method and try
def add_restrictions
#diet = Restriction.k1.order(:name)
#project = Project.find(params[:p])
params[:project][:restriction_ids].reject!(&:empty?).each do |restriction|
#projectrestrictions = ProjectRestriction.all
#projectrestrictions.each do |prj|
if prj.restriction_id == restriction
ProjectRestriction.destroy_all(prj.id)
else
#proj_rule = ProjectRestriction.create!(:project_id => #project.id, :restriction_id => restriction)
#proj_rule.save
end
end
respond_to do |format|
format.html { redirect_to t1s3_path(:p => #project.id ) ,
notice: 'Success! You added restrictions!' }
format.json {}
end
end
I'm attempting to write out some unit tests for my Rails application using RSpec. I'm using Rails 4.0.0 and Rspec-Rails 2.14.6. My User model:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => Settings.authentication.providers.map { |i| i.to_sym }
validates :password, presence: true, allow_nil: true,
allow_blank: true, if: :password_required?
validates :email, presence: true
def password_required?
self.providers.empty?
end
has_many :providers
has_one :profile
end
And my (magical) spec:
require 'spec_helper'
describe User do
describe '.new' do
it 'can create a valid user with no providers' do
params = ActionController::Parameters.new(FactoryGirl.attributes_for :user)
u = User.create params.permit!
expect(u).to be_new_record
end
end
describe '.build_with_provider' do
it 'can create a valid user with a provider' do
puts ap(User)
provider = FactoryGirl.create :provider
oauth_data = FactoryGirl.attributes_for :oauth_data
u = User.build_from_provider_and_oauth_data provider, oauth_data
expect(u).to_not be_nil
expect(u).to be_new_record
expect(u).to be_valid
u.save
expect(u).to be_persisted
end
end
end
If I'm missing something, please let me know. As far as I know, using ActionController::Parameters is the new way of (white|black)listing parameters in Rails 4.