Seeding relationships in Rails/ActiveRecord - ruby-on-rails

In my db/seeds.rb file of my Rails 3.2.8 project, I create seed data:
level_1 = Level.create(number: 1)
My model for Level is:
class Level < ActiveRecord::Base
attr_accessible :number
has_many :lessons
end
So then I want to seed the lessons:
Lesson.create(number: 5, level: level_1)
Its model is:
class Lesson < ActiveRecord::Base
attr_accessible :level_id, :number
belongs_to :level
end
When I run rake db:setup, I get the following error:
rake aborted! Can't mass-assign protected attributes: level
How do I get this to work, do I need to add :level to my list of attr_accessible elements in the Lesson model? Is this a bad idea? Should I instead simply create a Lesson without a Level and then afterwards call lesson.level = level_1?
UDPATE: The rails generated comments in the seeds.rb file shows this example:
cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
Mayor.create(name: 'Emanuel', city: cities.first)

Do you want to be able to mass-assign level? Put another way, will it be harmful if a form for Lesson objects can set the level attribute?
If it will not cause problems, go ahead and add it to attr_accessible, and keep doing what you're doing now.
If it will cause problems, use .new and set it manually:
lesson = Lesson.new
lesson.level = level_1
lesson.save

Related

activerecord shovel operator <<

From inside edit action in the contacts controller have ...
#programs << #contact.program
Which produces the following error:
NoMethodError - undefined method `<<' for Program::ActiveRecord_Relation
Contacts Model:
belongs_to :program
Program Model:
has_many :contacts
validates :name, presence: true, uniqueness: true
#programs.class
Program::ActiveRecord_Relation
#contact.program.class
Program(id: integer, name: string, active: boolean, created_at: datetime, updated_at: datetime)
Question: Why does this operation fail? Why can't the record get added to the record collection. What is preventing the collection(ActiveRecord_Relation) from adding the record?
You're contradicting yourself here:
Program has_many contacts vs Programs << Contact.program
If you're trying to add a Contact to a particular program, you would be looking at adding the contact:
program.contacts << contact
And if you're trying to set the program for the contact:
contact.program = program
What does not make sense, however, is to try to add something to “programs”, which isn't a relationship. Nothing in this system as you've defined it has_many :programs, so #programs.<< cannot possibly act on a relationship.
You're receiving this error because the ActiveRecord::Relation class is only a collection of results returned by an ActiveRecord query. You probably got it by running Program.where or a similar query. It is not an ActiveRecord::Association and therefore you cannot add more records to it.
You must instead use the association returned by the parent object.
Here's an example of what you're doing, vs what you should be doing:
class User < ApplicationRecord
has_many :programs
end
class Program < ApplicationRecord
belongs_to :user
end
new_program = Program.new
# What you're attempting.
programs_where = Program.where(user_id: User.first) # Class is Program::ActiveRecord_Relation
programs_where << new_program # Throws Error b/c << is not available on ActiveRecord::Relation objects.
# What you should be attempting.
user = User.first
programs_assoc = user.programs # Returns Programs::ActiveRecord_Associations_CollectionProxy
programs_assoc << new_program # Returns Correctly
Note: It's not clear how #programs is defined. Is this answer does not work for you then please provide the complete controller code, as well as the other model you're using.

Ruby On Rails Model has no methods

I have a model with a belongs to relationship.
class Product < ActiveRecord::Base
attr_accessible :name, :price, :request_id, :url
# Relationships
belongs_to :request
end
class Request < ActiveRecord::Base
attr_accessible :category, :keyword
# Relationships
has_many :products
end
This is the code in my controller function
product = Product.where({ :asin => asin }).first
# See if the product exists
begin
#This throws a method not found error for where
product = Product.where({ :name => name }).first
rescue
Product.new
# This throws a method not found error for request_id
product.request_id = request.id
product.save
end
I'm trying to create a new product object like so
product = Product.first(:conditions => { :name => name })
When I call that I get an error saying undefined method 'first' for Product:Class
I tried doing Product.new and I can't access any attributes. I get this for every one undefined method 'request_id=' for #<Product:0x007ffce89aa7f8>
I've been able to save request objects. What am I doing wrong with products?
EDIT:
So as it turns out there was an old Product data type that was being imported that wasn't an ActiveRecord class. It was using that instead of my Product::ActiveRecord. I deleted that import and it's good to go. Sorry to have wasted everybody's time.
Not sure what the proper protocol is here for what to do with this question.
Is your Product class an ActiveRecord::Base class? You can find out by running:
Product.ancestors.include?(ActiveRecord::Base)
If this returns false, it's getting the class loaded from somewhere else.
First check to see that your Product class is set up correctly by typing in:
rails c
# after console has loaded
Product
If this looks correct then we will try to instantiate a product by calling:
# Create a new product
product = Product.new(name: "first product", price: 100, url: "http://www.example.com")
# Persist this object to the database
product.save
If you are missing any attributes run another migration to add them to the Product table.
If none of those suggestions work, check to make sure that there isn't an existing class with the same name in your project. This would cause all kinds of errors and would explain certain methods not being found.

Can NOT insert data into database in migration?

I am using Rails 3. I don't know if it is the rule of rails that inside migration, it seems I can not insert data into database table. If someone can confirm it is so.
I tried the following things:
I have two ActiveRecord model:
class Car < ActiveRecord::Base
has_many :users
...
end
class User < ActiveRecord::Base
belongs_to :car
...
end
I have generate a migration file, inside the migration I have:
def self.up
default_car = Car.new({:name => 'default_car'})
default_car.save() #I got 'false' here
User.create!(:car_id => default_car.id}) #I got default_car.id is null value
end
def self.down
default_car = Car.find({:name => 'default_car'})
default_user = User.find({:car_id=>default_car.id})
default_car.delete
default_user.delete
end
I got false when I trying to save the default_car to database, and my default_user have null car_id.
Is it because in migration, it is NOT allowed to store data into database??
You can create data in migrations, however it is probably best not to, use seeds.rb instead.
Think the above will be failing because your car is not saving, I'm guessing you have some validation in your Car model.
Ok, we've figgured out that there was some validation issues. So you would like to now, that you can skip validations:
default_car = Car.new({:name => 'default_car'})
default_car.save(false)
#=> true

friendly_id and ActiveScaffold conflict

I have friendly_id and ActiveScaffold installed for my Rails application.
Because not all of my models have unique name fields I have to use the Slugged Model to make it work. friendly_id does the job flawlessly I have friendly URLs and I can load the objects using the friendly id.
But when I want to create a new object with ActiveScaffold, it says the following error message:
ActiveScaffold::ReverseAssociationRequired
(Association slugs: In order to
support :has_one and :has_many where
the parent record is new and the child
record(s) validate the presence of the
parent, ActiveScaffold requires the
reverse association (the belongs_to).)
Of course I cannot create the belongs_to association in that side because it's created by the friendly_id module and every model which works slugged way should be included there.
The model looks like this:
class FooBar < ActiveRecord::Base
has_friendly_id :name, :use_slug => true, :approximate_ascii => true
end
In my ApplicationController:
class Admin::FooBarsController < Admin::ApplicationController
active_scaffold :foo_bar do |config|
config.list.columns = [ :id, :name ])
config.update.columns = [ :name ]
config.create.columns = config.update.columns
end
end
Is there a way to make this work?
The versions: friendly_id 3.2.0, ActiveScaffold latest in the rails-2.3 git branch.
UPDATE: Seems like it does not conflict in production mode.
calling
has_friendly_id :name, :cache_column => 'cached_slug', :use_slug => true
... creates a has_many and a has one associations pointing to a slug AR model which hasn't any polymorphic belongs to association properly defined.
So basically what you need to do to solve this error is to define the reverse associations in the controller of your parent model (the one who has friendly_id stuff)
active_scaffold :products do |config|
...
config.columns[:slug].association.reverse = :product
config.columns[:slugs].association.reverse = :product
end
and it works :-)
PS : I use friendly_id as gem and ActiveScaffold VHO master branch for rails 3
In the past I have the same problem , i have solved , but i dont remember my solution , lookin at my code the only relevant hack is to use friendly_id as plugin and load it at last with config.plugin in environemnt.rb
aviable_plugins = Dir.glob(RAILS_ROOT+"/vendor/plugins/*").collect {|i| i.split("/").last }
config.plugins = aviable_plugins + [:friendly_id] #friendly_id must be last
I'M NOT SURE ,sorry, but if you try let my know.
sorry for my english to

Getting a NameError with ActiveRecord and relationships

I've run into a problem when using a one to many relationship. I want to have each Series have one Publisher and that one Publisher has many Series.
This is my Publisher model:
class Publisher < ActiveRecord::Base
validates_presence_of :name
has_many :series
end
This is my Serie model:
class Serie < ActiveRecord::Base
belongs_to :publisher
end
This is the failing test:
test "a publisher should have a list of series" do
#publisher = Publisher.new :name => "Standaard Uitgeverij"
#series = [ Serie.new(:name => "De avonturen van Urbanus", :publisher => #publisher),
Serie.new(:name => "Suske en Wiske", :publisher => #publisher) ]
assert_equal #series, #publisher.series
end
The test fails on the last line with NameError: uninitialized constant Publisher::Series.
I tried to save the publisher and the series, but this did not work. I tried it with only one serie, but this gives the same error.
Since I'm just starting out with Rails and Ruby, I am at a loss here. What am I doing wrong?
To address your actual question as mentioned in your comment (how can I name my model "Series"?), you need to make the Rails' Inflector aware of this exception to its default pluralization rules.
Add the following to config/environment.rb:
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable 'series'
end
This will let you name your model as Series. You can test that it's worked using script/console:
>> "series".pluralize #=> "series"
>> "series".singularize #=> "series"
—I have to say that I've just tried using The Pluralizer and it would appear that Rails has knowledge of how to handle the word series built-in. Try it for yourself.
I believe John's answer is the best one.
You can also directly specify the class name in the has_many declaration
has_many :series, :class_name => 'Serie'
Your has_many relationship name is fine, but your model name is wrong.
As the singular and plural of series are both series, you need to rename your model from Serie to Series. After that, everything should be fine.

Resources