find_or_initialize_by_title uniqueness - ruby-on-rails

I've got a text_field for tags in a nested form(It's being associated with Trips) that is being split on a comma on save and saving the words in the string seperated by the comma. I've jumped through some hoops to make it happen, and it's happening as I want by now. The only downside is that it seems that it doesn't make the current tag a unique tag(If it exists associate the existing one with the new Trip instead of making a new tag)
Here's the code splitting and saving the tag seperately:
if params[:trip][:tags_attributes].present?
params[:trip][:tags_attributes].each do |tag|
#a = tag[1]['title']
#a.split(',').each do |single|
#trip.tags.find_or_initialize_by_title(single)
end
end
end
And just in case my Trip.rb:
class Trip < ActiveRecord::Base
attr_accessible :description, :title, :user_id,
:triplocations_attributes, :photo, :category_ids,
:start_city, :tripphotos_attributes, :img_url, :thumb_url, :images,
:tags_attributes, :province
# validates :title, :length => {:minimum => 3}
# validates :description, :presence => true
# validates_associated :tags
has_many :triplocations, :dependent => :destroy
has_many :tripphotos, :dependent => :destroy
has_and_belongs_to_many :categories
has_and_belongs_to_many :tags
accepts_nested_attributes_for :triplocations, allow_destroy: true
accepts_nested_attributes_for :tripphotos, allow_destroy: true
accepts_nested_attributes_for :categories
accepts_nested_attributes_for :tags
end
Thanks in advance!

Related

Using has_many with Multple Model Types via STI

How do I save and view a has_many relationship with 2 different models that are inheriting though STI?
I've got a base Model for Projects as follows:
class Project < ActiveRecord::Base
attr_accessible :slug,
:category_id,
:description,
:name,
:visible,
:note,
:contractor, :contractor_url,
:date_complete, :architect, :architect_url,
:building_year,
:project_type,
:address, :city, :state, :country,
:pictures,
:photo_credit
has_many :pictures, :order=>:id, :dependent => :destroy
Picture.rb:
class Picture < ActiveRecord::Base
attr_accessible :project_id, :image, :caption, :cover, :dimensions
belongs_to :project
And using STI I have Homepage Items which display a subset of Projects and are specific to the homepage:
class HomepageItem < Project
attr_accessible :slug,
:name,
:visible,
:note,
:pictures,
:photo_credit
has_many :pictures, :order=>:id, :dependent => :destroy
This results in an error expecting a new column on pictures homepage_item_id instead of project_id
PG::UndefinedColumn: ERROR: column pictures.homepage_item_id does not exist
I believe this should be looking on the pictures.project_id column.
Note: Without the has_many defined in HomepageItem, the items are saved, but no Pictures are created. Also this is a Rails 3.2.22 project.
as you see it looking for foreign key, so include foreign key in the association like below,
class HomepageItem < Project
attr_accessible :slug,
:name,
:visible,
:note,
:pictures,
:photo_credit
has_many :pictures, :foreign_key =>:project_id, :order=>:id, :dependent => :destroy

Multiple nested form in a HABTM relation

I'm fighting with this bug for the past few hours and I can't make sense of it and my researches didn't give an answer.
It is a basic HABTM relationship. Inputs HABTM Visualizations, and I have a cross table InputsVisualizations that has some attributes of its own.
= form_for(#visualization) do |f|
= f.input :title
= f.fields_for :inputs_visualizations do |iv|
= iv.input :color
= iv.fields_for :input do |i|
= i.input :title
= f.button :submit, "Save"
class Input < ActiveRecord::Base
# Associations ------------------
has_many :inputs_visualizations, dependent: :destroy, order: "inputs_visualizations.order ASC"
has_many :visualizations, through: :inputs_visualizations
# Attributes --------------------
attr_accessible :title, :unit
end
class InputsVisualization < ActiveRecord::Base
# Associations ------------------
belongs_to :input
belongs_to :visualization
# Attributes --------------------
attr_accessible :input_id, :visualization_id, :color, :input_attributes
accepts_nested_attributes_for :input, :reject_if => lambda { |i| i[:title].blank? }, :allow_destroy => true
end
class Visualization < ActiveRecord::Base
# Associations ------------------
has_many :inputs_visualizations, dependent: :destroy, order: "inputs_visualizations.order ASC"
has_many :inputs, through: :inputs_visualizations, order: "inputs_visualizations.order ASC"
# Attributes --------------------
attr_accessible :title, :inputs_visualizations_attributes
accepts_nested_attributes_for :inputs_visualizations, :reject_if => lambda { |a| a[:input_id].blank? }, :allow_destroy => true
end
I need a form for Visualizations that let me manage both InputsVisualizations and Inputs. As you can see in my form, there are two nested fields_for.
Case 1:
I create a nested InputsVisualization with a nested Input (both are new_record). I save the form, they both are created. Cool!
Case 2:
From the same form, I update an Input (existing record). I save, nothing is updated even though the attributes are properly passed to the controller.
I read that nested_attributes don't work with belongs_to relationship, though it created it just fine. Why doesn't it update afterwards?
Thanks
The :reject_if condition on this line looks for an :input_id but that value is not included in the form. So this could prevent the update from going through.
accepts_nested_attributes_for :inputs_visualizations, :reject_if => lambda { |a| a[:input_id].blank? }, :allow_destroy => true

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

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

Resources