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
Related
I am trying to implement likes into my rails app.
like model
class Like < ApplicationRecord
belongs_to :comment
belongs_to :post
belongs_to :user
validates :user_id, uniqueness: {scope: :post_id}
validates :user_id, uniqueness: {scope: :comment_id}
end
user model
class User < ApplicationRecord
has_secure_password
has_one :profile, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :posts, dependent: :destroy
has_many :likes, dependent: :destroy
has_many :liked_comments, :through => :likes, :source => :comment, dependent: :destroy
has_many :liked_posts, :through => :likes, :source => :post, dependent: :destroy
has_one_attached :avatar
validates :username, presence: true, uniqueness: true
validates :email, presence: true, uniqueness: true
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
validates :password, length: { minimum: 8 }
validates :password, format: { with: /\A[a-zA-Z0-9!##$%^&*()_]+\z/ }
# validates :password, confirmation: true
# validates :password_confirmation, presence: true
end
post & comment model
class Post < ApplicationRecord
belongs_to :category
belongs_to :user
has_many :comments, dependent: :destroy
has_many :likes, dependent: :destroy
has_many :liking_users, :through => :likes, :source => :user
has_many_attached :images
def liked?(user)
!!self.likes.find{|like| like.user_id == user.id}
end
end
class Comment < ApplicationRecord
belongs_to :post
belongs_to :user
has_many :likes, dependent: :destroy
has_many :liking_users, :through => :likes, :source => :user
has_many_attached :images
def liked?(user)
!!self.likes.find{|like| like.user_id == user.id}
end
end
The issue I'm having is when I run my seed data I get one of two errors NoMethodError: undefined method "marked_for_destruction?" for false:FalseClass if set up like so:
#like0 = Like.create!(
user: #admin0,
post: #post3 & #post5 & #post6 & #post8 & #post9,
comment: #comment1,
username: #admin0.username
)
or NotNullViolation: ERROR: null value in column "comment_id" violates not-null constraint if set up like so:
class Like < ApplicationRecord
belongs_to :comment, optional: true
belongs_to :post, optional: true
belongs_to :user
validates :user_id, uniqueness: {scope: :post_id}
validates :user_id, uniqueness: {scope: :comment_id}
end
#like0 = Like.create!(
user: #admin0,
post: #post3,
comment: #comment1,
username: #admin0.username
)
my question is how can I better set up the relationship between these 4 models so as to not get these errors?
I have Locations, Order and Event Models.
class Order < ActiveRecord::Base
belongs_to :event
validates :first_name, presence: true
validates :last_name, presence: true
validates :amount, presence: true, :numericality => {:only_integer=>true, :greater_than =>0}
end
class Event < ActiveRecord::Base
belongs_to :location
validates :title, presence: true
validates :price, presence: true, :numericality => {:greater_than =>0}
end
class Location < ActiveRecord::Base
has_many :events, dependent: :destroy
has_many :orders, through: :events
validates :title, presence: true
validates :size, presence: true, :numericality => {:only_integer=>true,:greater_than =>0}
end
I want to check, in the orders create controller, how many seats the location has.
#orders.events returns me the right event.
if I ask for #order.event.location the return is always "#".
Is this a security issue? I also added in the Location model:
has_many: orders, through: events
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'}.
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
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