Rails3 has_many through working on local but fail on heroku - ruby-on-rails

i'm using sqlit3 for local and Postgre for heroku.
Everything works fine until i upload my files to heroku. Here is my model.
class User < ActiveRecord::Base
belongs_to :unit
has_friends
end
class Unit < ActiveRecord::Base
attr_accessible :unit, :floor
has_many :users
belongs_to :block
end
class Block < ActiveRecord::Base
attr_accessible :block, :units_attributes
has_many :units, :dependent => :destroy
accepts_nested_attributes_for :units, allow_destroy: true
belongs_to :postalcode
end
class Postalcode < ActiveRecord::Base
attr_accessible :postalcode, :blocks_attributes
has_many :blocks, :dependent => :destroy
accepts_nested_attributes_for :blocks, allow_destroy: true
belongs_to :neighbourhood
end
class Neighbourhood < ActiveRecord::Base
attr_accessible :name, :streetname, :postalcodes_attributes
has_many :postalcodes, :dependent => :destroy
has_many :blocks, :through => :postalcodes
has_many :units, :through => :blocks
has_many :users, :through => :units
accepts_nested_attributes_for :postalcodes, allow_destroy: true
validates :name, :presence => true
validates :streetname, :presence => true
end
i troubleshooted and found that the problem is with this method in the controller.
#neighbours = current_user.unit.block.postalcode.neighbourhood.users
Although #neighbours = current_user.unit.block.postalcode.neighbourhood works perfectly fine.
Please help, i'm desperate, i have tried googling for it one whole day.

Check out this answer to a similar issue
It is quite likely the error is coming up from WHERE "postalcodes"."neighbourhood_id" = 1 which indicates that neighbourhood_id in postalcodes table is created as a String, instead of an integer.
Follow the steps mentioned in the answer accordingly, and change it to an Integer.

Related

Reject nested assosciation creation rails

I have 2 models as below,
Updated based on suggestions
class User < ActiveRecord::Base
has_many :company_users, dependent: :destroy, inverse_of: :user
accepts_nested_attributes_for :company_users, allow_destroy: true
has_many :companies, through: :company_users
has_many :roles, through: :company_users
end
and
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :role
belongs_to :user, inverse_of: :company_users
validates :user, uniqueness: {scope: [:company, :role]}
end
I find the uniqueness validation is working only on the update request. On create request validation is not functioning and it simply bypasses it.
I want to enable the same validation to reject if a user has same company & role assigned more than once.
If you want a ensure the uniqueness of user on unique pair of :company and :role, then you can try following. By default, the validations run for both create and update. You don't need :on => [ :create, :update ]. So it should be just:
validates :user, uniqueness: {scope: [:company, :role]}
Solved this issue with the below validation,
class User < ActiveRecord::Base
has_many :company_users, dependent: :destroy, inverse_of: :user
accepts_nested_attributes_for :company_users, allow_destroy: true
has_many :companies, through: :company_users
has_many :roles, through: :company_users
validate :company_users, :uniqueness_of_company_users
end
private
def uniqueness_of_company_users
errors.add(:company_users, 'error in role creation') if company_users.map{|x| "#{x.company_id} #{x.role_id}"}.uniq.size != company_users.size
end
This is the additional validation required to solve the issue
Thanks Rich Peck for this https://railscoding.wordpress.com/2015/04/27/uniqueness-gotcha/
From the docs
The :on option takes one of the values :create or :update
--
A validation is only run on create or update anyway, right?
find doesn't manipulate the db, destroy gets rid of the record & new just invokes a new instance of the object. You have literally zero other reasons to validate.
So, really, you should have:
validates :user, uniqueness: {scope: [:company_id, :role_id]}
This will look up against the values in company_id and role_id, which is probably going to be more efficient than calling the company and role objects themselves.
I could be wrong, but I really think if you used the above, it should work.
--
You may also wish to clean up your models:
class User < ActiveRecord::Base
has_many :company_users, dependent: :destroy, inverse_of: :user
accepts_nested_attributes_for :company_users, allow_destroy: true
has_many :companies, through: :company_users
has_many :roles, through: :company_users
end
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :role
belongs_to :user, inverse_of: :company_users
validates :user, uniqueness: {scope: [:company_id, :role_id]}
end

Rails: Dependent delete_all not working

I have 5 models. Server, Platform, Game, RetentionReport, DataReport. And I am trying to use :dependent => :delete_all, but it wont work. Here are my models.
class Game < ActiveRecord::Base
attr_accessible :name
has_many :platforms, :dependent => :delete_all
end
class Platform < ActiveRecord::Base
attr_accessible :name, :game_id, :company_id
belongs_to :game
has_many :servers, :dependent => :delete_all
end
class Server < ActiveRecord::Base
attr_accessible :name, :region, :device_type, :platform_id, :platform_server_id
belongs_to :platform
has_many :gm_data_reports, :dependent => :delete_all
has_many :gm_retention_reports, :dependent => :delete_all
delegate :company_id, :to => :platform
validates :platform_server_id, :uniqueness => {:scope => :platform_id}
end
class DataReport < ActiveRecord::Base
belongs_to :server
end
class RetentionReport < ActiveRecord::Base
belongs_to :server
end
Whenever I run Game.delete_all in the terminal, nothing gets deleted not even the Platforms
delete_all does not trigger call_backs.
If you have Game.destroy_all it will do what you want.
You can use :dependent => :destroy or :dependent => :delete_all in the association declaration. The former will run callbacks in the association and the later one does not.

How do I validate the uniqueness of a has_many :through join model?

I have users and issues joined by a votership model. Users can vote on issues. They can either vote up or down (which is recorded in the votership model). First, I want to be able to prevent users from casting multiple votes in one direction. Second, I want to allow users to cast the opposite vote. So, if they voted up, they should still be able to vote down which will replace the up vote. Users should never be able to vote on an issue twice. Here are my files:
class Issue < ActiveRecord::Base
has_many :associations, :dependent => :destroy
has_many :users, :through => :associations
has_many :voterships, :dependent => :destroy
has_many :users, :through => :voterships
belongs_to :app
STATUS = ['Open', 'Closed']
validates :subject, :presence => true,
:length => { :maximum => 50 }
validates :description, :presence => true,
:length => { :maximum => 200 }
validates :type, :presence => true
validates :status, :presence => true
def cast_vote_up!(user_id, direction)
voterships.create!(:issue_id => self.id, :user_id => user_id,
:direction => direction)
end
end
class Votership < ActiveRecord::Base
belongs_to :user
belongs_to :issue
end
class VotershipsController < ApplicationController
def create
session[:return_to] = request.referrer
#issue = Issue.find(params[:votership][:issue_id])
#issue.cast_vote_up!(current_user.id, "up")
redirect_to session[:return_to]
end
end
class User < ActiveRecord::Base
authenticates_with_sorcery!
attr_accessible :email, :password, :password_confirmation
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email
has_many :associations, :dependent => :destroy
has_many :issues, :through => :associations
has_many :voterships, :dependent => :destroy
has_many :issues, :through => :voterships
end
You would put the uniqueness constraint on the Votership model. You don't need to put validations on the association itself.
class Votership < ActiveRecord::Base
belongs_to :user
belongs_to :issue
validates :issue_id, :uniqueness => {:scope=>:user_id}
end
This means a user can only have a single vote on a given issue (up or down).
Relationship models:
class Person
has_many :accounts
has_many :computers, through: :accounts
end
class Account
belongs_to :person
belongs_to :computer
scope :administrators, -> { where(role: 'administrator') }
end
class Computer
has_many :accounts
has_many :people, through: :accounts
end
This is how it is called
person.accounts.administrators.map(&:computer)
We can do this better using ActiveRecord::SpawnMethods#merge!
person.computers.merge(Account.administrators)
Ref: https://coderwall.com/p/9xk6ra/rails-filter-using-join-model-on-has_many-through

Join model not getting created properly using accepts_nested_attributes_for

I have a User model and a Project model joined with the Ownership model using has_many :through. I am trying to set an Ownership attribute's value as I create an association between a User and a Project by using accepts_nested_attributes_for.
Here is my User model:
class User < ActiveRecord::Base
attr_accessible :name, :email, :admin, :projects
has_many :ownerships
has_many :projects, :through => :ownerships
accepts_nested_attributes_for :projects
Here is my ownership model:
class Ownership < ActiveRecord::Base
attr_accessible :owner_type
belongs_to :project
belongs_to :user
validates :user_id, :presence => true
validates :project_id, :presence => true
validates :owner_type, :presence => true
end
and my project model:
class Project < ActiveRecord::Base
attr_accessible :name, :description
has_many :ownerships
has_many :users, :through => :ownerships
and this is how I'm trying to set the owner_type value of the ownership model as its being created:
current_user.ownerships.create(:owner_type => 'designer', :project => #project)
for some reason this isn't creating the ownership join model or (obviously) setting the owner_type value of the ownership model. What can I do to fix this?

accepts_nested_attributes_for called twice in model

class StepQuiz < ActiveRecord::Base
belongs_to :step
has_many :step_quiz_questions, :dependent => :destroy
accepts_nested_attributes_for :step
accepts_nested_attributes_for :step_quiz_questions, :allow_destroy => true
attr_accessible :step_id, :instructions, :correct_to_pass, :retakes_allowed, :time_limit, :step_attributes, :step_quiz_questions_attributes
end
Am I allowed to have accepts_nested_attributes_for called twice for a given model. It appears to work with no errors.
You are using a class method defined here: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
The answer is yes, so that you can tune every single case.

Resources