How to insert multiple rows based on a defaults table? - sql

I have the following tables: Users, Default Prices, Clients, Client Prices. What I'd like is to have the default_prices automatically fill in the client_prices table when a new client is created. It looks like I might be able to use a similar solution to this answer. What I would like to happen is when a new client is created by a user, all of the client_prices for the client are populated by the default_prices table.
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :stripe_token, :default_prices_attributes
has_many :default_prices
has_many :clients
accepts_nested_attributes_for :default_prices, :allow_destroy => true
class DefaultPrice < ActiveRecord::Base
attr_accessible :price, :user_id, :visit_type, :id
belongs_to :user
end
class Client < ActiveRecord::Base
attr_accessible :active, :address_1, :address_2, :city, :email, :first_name, :last_name, :state, :user_id, :zip, :client_prices_attributes
belongs_to :user
has_many :client_prices
accepts_nested_attributes_for :client_prices_attributes
class ClientPrice < ActiveRecord::Base
attr_accessible :price, :client_id, :visit_type, :id
belongs_to :uclient
end

You can add before_create block to copy default price.
before_create do
user.default_prices.each do |default_price|
client_prices.build(default_price.attributes.slice("price", "visit_type"))
end
end

Related

How do I write an Rspec test for an ActiveRecord polymorphic association

Has anyone found a way to write an rspec example for an ActiveRecord polymorphic association?
I'm used to using Thoughtbot's shoulda matches, but I think polymorphic's are beyond it's scope?
Just for clarity my models would have a similar pattern to this:
class Person < ActiveRecord::Base
attr_accessible :name
has_one :address, as: :location_data_source
accepts_nested_attributes_for :address
end
class Company < ActiveRecord::Base
attr_accessible :name
has_one :address, as: :location_data_source
accepts_nested_attributes_for :address
end
class Address < ActiveRecord::Base
attr_accessible :street, :city
belongs_to :location_data_source, polymorphic: true
end

Ruby on Rails: SQLite3::SQLException: no such column:

SELECT "groups".* FROM "groups"
INNER JOIN "groups_interests" ON "groups"."id" = "groups_interests"."group_id"
WHERE "groups_interests"."interest_id" = 1
SQLite3::SQLException: no such column: groups_interests.interest_id: SELECT "groups".* FROM "groups" INNER JOIN "groups_interests" ON "groups"."id" = "groups_interests"."group_id" WHERE "groups_interests"."interest_id" = 1
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: groups_interests.interest_id: SELECT "groups".* FROM "groups" INNER JOIN "groups_interests" ON "groups"."id" = "groups_interests"."group_id" WHERE "groups_interests"."interest_id" = 1
I think I have a misunderstanding about foreign keys and the has_many relation
To get the error I used rails c
Interest.find(1).groups
I also want this command to run correcty
Groups.find(5).interests
class Group < ActiveRecord::Base
attr_accessible :description, :name, :project_id
has_many :students
has_many :group_interests
has_many :interests, :through => :group_interests
belongs_to :project
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
class Interest < ActiveRecord::Base
attr_accessible :name
has_many :group_interests
has_many :groups, :through => :group_interests
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
class GroupInterest < ActiveRecord::Base
attr_accessible :group_id, :interest_id
belongs_to :groups
belongs_to :interests
end
I got the idea to do this from ruby on rails guides
The reason for your error: there are two typos
class GroupInterest < ActiveRecord::Base
attr_accessible :group_id, :interest_id
belongs_to :groups #should be :group
belongs_to :interests #should be :interest
end
Group has_many :group_interests (plural)
GroupInterest belongs_to :group (singular)
EDIT - Do not use has_and_belongs_to_many unless you are sure that you will never need a new attribute in the association table. has_many :through is much more flexible.
Why don't you use has_and_belongs_to_many:
class Group < ActiveRecord::Base
attr_accessible :description, :name, :project_id
has_many :students
has_and_belongs_to_many :interests
belongs_to :project
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
class Interest < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :groups
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
class GroupInterest < ActiveRecord::Base
attr_accessible :group_id, :interest_id
end
You need to change your table structure on join_table. See the link provided for that.
class GroupInterest < ActiveRecord::Base
attr_accessible :group_id, :interest_id
belongs_to :group
belongs_to :interest
end
Group.find(5).interests

ActiveRecord::HasManyThroughNestedAssociationsAreReadonly Error in Rails Admin

I just upgraded to Rails 3.2.10 and am getting an error message that I never used to get when updating a record via RailsAdmin.
ActiveRecord::HasManyThroughNestedAssociationsAreReadonly at /admin/vendor/12/edit
Message Cannot modify association 'Vendor#categories' because it goes through more than one other association.
This is my Vendor model:
class Vendor < ActiveRecord::Base
attr_accessible :name, :description, :banner_image, :logo_image, :intro_text, :thumb_image, :category_ids, :product_ids, :user_id, :remove_banner_image, :banner_image_cache, :remove_logo_image, :logo_image_cache
mount_uploader :banner_image, ImageUploader
mount_uploader :logo_image, ImageUploader
mount_uploader :thumb_image, ImageUploader
has_many :products, :dependent => :destroy
has_many :categories, :through => :products
belongs_to :owner, :class_name => "User",
:foreign_key => "user_id"
end
This is my Category model:
class Category < ActiveRecord::Base
attr_accessible :name, :product_ids, :category_ids
has_many :category_products do
def with_products
includes(:product)
end
end
has_many :products, :through => :category_products
end
This is my Product model:
class Product < ActiveRecord::Base
attr_accessible :name, :description, :price, :vendor_id, :image, :category_ids, :sku, :remove_image, :image_cache
mount_uploader :image, ImageUploader
belongs_to :vendor
has_many :category_products do
def with_categories
includes(:category)
end
end
has_many :categories, :through => :category_products
end
This is my CategoryProduct model:
class CategoryProduct < ActiveRecord::Base
attr_accessible :product_id, :category_id, :purchases_count
belongs_to :product
belongs_to :category
validates_uniqueness_of :product_id, :scope => :category_id
end
This happens because your association is nested, meaning (from rails source) :
A through association is nested if there would be more than one join table... which is your case here.
Apparently a workaround (I didn't test) is telling Vendor it doesn’t need to autosave the association.
has_many :categories, :through => :products, :autosave => false
You can mark the association as readonly and rails_admin will then not generate the category fields in the form for vendor:
has_many :categories, -> { readonly }, through: :products

Multiple associations

I have an event, a vendor, and a venue model.
An event can have multiple vendors but one venue.
A venue can have multiple vendors and multiple events.
A vendor can have multiple venues and multiple events.
I have an events table, a venues table, a vendor table, an events_vendor table and a events_venue table.
How do I have to setup my models?
class Event < ActiveRecord::Base
attr_accessible :name, :budget, :client, :date, :description, :attendees,
:assets_attributes, :tag_list
belongs_to :user
has_many :assets, :dependent => :destroy
has_many :vendors
has_one :venue
accepts_nested_attributes_for :assets, :allow_destroy => true
acts_as_taggable
end
class EventsVendors < ActiveRecord::Base
attr_accessible :event_id, :vendor_id
end
class EventsVenues < ActiveRecord::Base
attr_accessible :event_id, :venue_id
end
class Vendor < ActiveRecord::Base
attr_accessible :city, :contact, :country, :description, :email, :employees,
:latitude, :longitude, :minimum, :name, :state, :street, :tel, :type
belongs_to :event
end
class Venue < ActiveRecord::Base
attr_accessible :capacity, :city, :contact, :country, :email, :exclusiveVendors, :fee,
:latitude, :longitude, :name, :state, :street, :tel, :union
belongs_to :event
has_many :vendors
end
Does my events_venues model belong to both events and venues? Do I have to specify the :through relationship?
Any help would be appreciated. thanks!
Yes, the join tables should look something like this.
EventsVenues
belongs_to :event
belongs_to :venue
Event
has_many :venues, through: :events_venues
has_many :events_venues
Venues
has_many :events, through: :events_venues
has_many :events_venues

Rails 3 - WARNING: Can't mass-assign protected attributes: user_ids

I have a has_many through relationship between Course and User.
class Course < ActiveRecord::Base
belongs_to :user
has_many :enrollments, :dependent => :delete_all
has_many :users, :through => :enrollments
attr_accessible :description, :duration, :name, :prerequisites, :short_name, :start_date, :user_id
accepts_nested_attributes_for :users, :allow_destroy => true
attr_accessible :users_attributes
and User:
class User < ActiveRecord::Base
has_many :subjects, :class_name => "Course" # to get this call user.subjects
has_many :enrollments, :dependent => :delete_all
has_many :courses, :through => :enrollments
and Enrollment:
class Enrollment < ActiveRecord::Base
belongs_to :course
belongs_to :user
attr_accessible :course_id, :user_id
end
Now I'm trying to set user_ids from inside Course, using a nested form. It keeps giving me that Mass Assignment warning, and nothing is saved. I read I was supposed to add attr_accessible user_id but it still doesn't work.
Even if I do something like this from the rails console:
#c.update_attributes({:user_ids => [7,8]})
with #c being the course
Any help would be greatly appreciated,
Thank you.
It's user_ids, not user_id.
You need to add user_ids to your attr_accessible.