I'm trying to create a record with some nested attributes and the nested attributes are in a polymorphic model; something like this:
class Office < ActiveRecord::Base
attr_accessible :name, :description, :address_attributes
has_one :address, as: :location_data_source
accepts_nested_attributes_for :address
end
class Shop < ActiveRecord::Base
attr_accessible :name, :description, :address_attributes
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
And I'd like to create a record like this:
o = Office.create(:name = 'The Big Office', description = 'a really big office' :address_attributes => [:street => 'main street', :city => 'No Name City'])
But I get an 'with_indifferent_access' error:
NoMethodError: undefined method `with_indifferent_access' for...
I think I'm struggling becuase I don't really understand what the error means. Any ideas?
Related
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
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
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
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
I have an app that lets users input dates & interests that relate to those dates .I need to send them deals (a few days before the date - Via Email) that are based off of their interests and location. I have all the models setup and recording the data properly, just wondering how to query the models for the dates and then send the appropriate deal based off of the city and interests.
Notes:
*Each city and interest category has only 1 deal
*I have several different models for types of dates (Holidays, Occasions, Friends Birthdays ect).. all are pretty much identical in structure.
*All interests for each type of date are stored in person_interests.
Models:
Class User
belongs_to :province
belongs_to :city
has_many :friends_bdays
has_many :occasions
has_many :person_interests, :as => :person
has_many :interests, :through => :person_interests
has_many :user_holidays
has_many :holidays, :through => :user_holidays
has_many :anniversaries
end
class Deal < ActiveRecord::Base
belongs_to :interest
belongs_to :city
belongs_to :store
end
class Store < ActiveRecord::Base
has_many :deals
belongs_to :city
belongs_to :province
end
class PersonInterest < ActiveRecord::Base
belongs_to :interest
belongs_to :person, :polymorphic => true
end
class Interest < ActiveRecord::Base
has_many :person_interests
has_many :deals
end
class Occasion < ActiveRecord::Base
belongs_to :user
belongs_to :admin_user
has_many :person_interests, :as => :person
has_many :interests, :through => :person_interests
end
class Anniversary < ActiveRecord::Base
belongs_to :user
has_many :person_interests, :as => :person
has_many :interests, :through => :person_interests
end
class Friend_bday < ActiveRecord::Base
belongs_to :user
has_many :person_interests, :as => :person
has_many :interests, :through => :person_interests
end
You can achieve this using a variation of the solution below:
Install the squeel gem
class User
def deals(reload=false)
#deals = nil if
#deals ||= Deal.where{
( (:city => city_id) | ( :interest_id => interest_ids) ) &
:deal_date => (Time.now..3.days.from_now)
}
end
end
Now, user.deals returns the deals that will be active in next 3 days matching the user's city OR interests.
Edit 1:
Based on your comment it looks like you don't need the squeel gem. You can achieve what you want using regular AR syntax.
class User
def deals(reload=false)
#deals = nil if reload
#deals ||= Deal.where(
:city => city_id,
:interest_id => interest_ids,
:deal_date => (Time.now..3.days.from_now)
)
end
end