Pass value to Mongoid model.new method without creating a field - mongoid

I want to pass a value to a Mongoid model that is not correlated with any field and should not be stored in the database, but should instead be used for some additional actions (e.g. performing custom initialization):
class Author
include Mongoid::Document
embeds_many :books
field :name, type: String
# Create a set number of empty books associated with this author.
def create_this_many_books(quantity)
quantity.each do |i|
books << Book.new
end
end
end
class Book
include Mongoid::Document
embedded_in :author
field :title, type: String
end
Now, how can I create a given number of embedded empty book objects when creating a new author:
author = Author.new(name: 'Jack London', number_of_books: 41)
Here, :number_of_books is not a field in the Author model, but a value passed to create_this_many_books. What is the best way of doing this?

alter the Author model to be
class Author
include Mongoid::Document
embeds_many :books
field :name, type: String
attr_accessor :number_of_books
# this is plain old ruby class member not saved to the db but can be set and get
after_create :create_this_many_books
def create_this_many_books
self.number_of_books.each do |i|
books << Book.new
end
end
end

Related

Django: overriding default field names in ManyToManyField

Good day,
Using a ManyToManyField as in the example below causes django to automatically create a Model called country_region with fields country_id and region_id, which is very cool. But what if the region_country database table (for reasons beyond the scope of this thread) has field names other than country_id and region_id?
Django generates the field names in the many-to-many table based on the model names of the related tables, so the only way I have found to achieve this is to change the two Model names. But that forces me to have model names that I don't want! How can I tell django what field names to use in the automatic many-to-many Model?
I have tried explicitly specifying the many-to-many Model using the through= keyword argument of the ManyToManyField, and this works, but then forms based on the Region Model do not allow saving...
Any advice greatly appreciated.
Thanks,
Randal
class Country(models.Model):
country_id = models.AutoField(primary_key=True)
country_name = models.CharField(max_length=200)
class Meta:
managed = False
db_table = 'country'
def __unicode__(self):
return '%s' % (self.country_name)
class Region(models.Model):
region_id = models.AutoField(primary_key=True)
region_name = models.CharField(max_length=200)
region = models.ManyToManyField(Country, db_table='region_country')
class Meta:
managed = False
db_table = 'region'

DB query from a belongs_to relationship

I have a model: Animal
belongs_to :owner
I have a model: Owner
has_many :animals
Owner has a boolean attribute active
def self.not_active
where('owner.active == ?', false)
end
The above code does not work for some reason. I've tried lots of things around it, but keep getting errors. When calling something like Animal.first.owner.active I get back either true or false, but the database call must be different...
For clarification I want the Animals for which their owner is not active. I don't want to do the opposite call though (Starting with the owner db and checking active and returning animals) because of calls I'm linking together off of Animal
Your code should be:
def self.not_active
includes(:owner).where("owners.active = ?", false)
end
When referencing a model in pure SQL, as you are doing so above, you need to use the table name, not the singular model name. Thus, owners, not owner.
A clearer style would be:
def self.not_active
includes(:owner).where(owners: {active: false})
end
Rails AREL will take care of referencing the active attribute in the query correctly, and you don't have to worry about the exact table/model name.

how do I save an array containing id values on ruby on rails

How do I store arrays values in the database using ruby on rails? I am building a school timetable which have 6 periods a day. I am storing the subject ID into an array, but I just don't know how to save the id values of that array.
My Controller:
def create
#timetable = Timetable.new(params[:timetable])
#buildtimetable = params[:gradeclassroomsubject_id]
#buildtimetable.each do |subjectID|
subjectID.save!(params[:gradeclassroomsubject_id].reject { |k,v| v.blank? })
end
end
class CreateTimetables < ActiveRecord::Migration
def change
create_table :timetables do |t|
t.integer :period_no
t.integer :day_no
t.integer :gradeclassroomsubject_id
t.integer :user_id
t.timestamps
end
end
end
Any help is much appreciated I am way under pressure and this kinda feels embarrassing.
Many thanks
short answer: it's impossible to store many values(all values in an array) into a column of a table.
As you just want to store subject_id, I suppose you already have a table that stores all subjects and the only thing you want to do is setting a relationship between a specific user and the subjects he/she takes. A many-to-many relationship is the one you need.
create a new table:
class CreateStuendship < ActiveRecord::Migration
def change
create_table :stuedentships do |t|
t.integer :subject_id
t.integer :user_id
# something else you want to store about this relationship, ex: year, semester...
end
end
app/models/studentship:
class Studentship < ActiveRecord::Base
belong_to :user
belong_to :subject
end
app/models/user.rb:
class User < ActiveRecord::Base
has_many :studentship
has_many :subjects, :through => :studentship
end
app/models/subject.rb:
class Subject < ActiveRecord::Base
has_many :studentship
has_many :users, :through => :studentship
end
furthermore, I think you can store your "period_no" and "day_no" into your subjects table, so you can know the time of the course by the subjects table. If the time of the course is not fixed( subjects with the same id have different course time), storing these two attributes into studentship may be a good idea. By doing so, you don't need the table timetables, which is unnecessary, anymore.
when you want to store the subjects taken by a user, just create new studentships according to your array iteratively.
Finally, you can
user = User.frist
subject = Subject.first
user.subjects # subjects taken by the first user
subject.users # users who take the first subject

Rails 3.2.8 - Multiple database access within one single Rails App

I'm building a webapp that has its own database called 'products_db'. But my app will have to call reviews which is located in the database 'reviews_db', which is a legacy db being used by another system that I can't do anything because client wants it that way.
So, luckily both db are located in the same SQL Server (MSSQL). I've already have te 'activerecord-sqlserver-adapter' working but I need to figure out a way to access 'reviews_db' from my webapp.
The reviews_db doesn't follow any Rails convention because its a legacy system.
So, my class Product:
class Product < ActiveRecord::Base
attr_accessible :name, :description, :price
has_many :reviews
end
And my class Review:
class Review < ActiveRecord::Base
# THIS CLASS DOESN'T FOLLOW RAILS CONVENTION
# HOW DO I SET AND MANAGE LEGACY PRIMARY KEY?
# HOW DO I CONNECT THIS MODEL TO THE OTHER DATABASE?
# HOW DO I CONNECT THIS MODEL TO THE RIGHT TABLE NAME?
attr_accessible :rv_tbl_title, :rv_tbl_id, :rv_tbl_text, :rv_tbl_author, :rv_tbl_ref_prod
has_one :Product, foreign_key: :rv_tbl_author
end
Is there a gem for it? What's the solution to use in the Review class questions?
I'm not sure if this first part is necessary or not, but in your database.yml file, make a new connection by adding something like this to the end:
review:
adapter: sqlserver
database: reviews_db
.... put your other configuration info here
Then in your review model review.rb:
class Review < ActiveRecord::Base
establish_connection :review
self.table_name = "review_table"
self.primary_key = "review_id"
end
Change the table name to the correct table, and the primary key to the correct column name.
Then create a new table/model for the sole purpose of having a local reference to a review. So you could call it ReviewReference
class ReviewReference < ActiveRecord::Base
belongs_to :review
has_one :product
end
And change your Product model to
class Product < ActiveRecord::Base
has_many :reviews, class_name: "ReviewReference"
end
This should get you a long way toward your goal. You might have to end up doing a lot of
#reviews = Review.where("some_column = ?", some_value)
or
#reviews = Review.find_by_sql("Some SQL Here") if you're doing more complex queries.
Sorry my answer isn't more concrete, I've only done this once. Props to Chad Fowler's Rails Recipes book for the concept.

Django's ManyToMany Relationship with Additional Fields

I want to store some additional information in that, automatically created, ManyToMany join-table. How would I do that in Django?
In my case I have two tables: "Employees" and "Projects". What I want to store is how much each of the employees receives per hour of work in each of the projects, since those values are not the same. So, how would I do that?
What occurred to me was to, instead of the method "ManyToManyField", create explicitly a third class/table to store those new informations and to set its relationship with "Employees" and "Projects" using the "ForeignKey" method. I'm pretty sure it will work, but is this the best approach?
Here is example of what you want to achieve:
http://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships
In case link ever breaks:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self): # __unicode__ on Python 2
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self): # __unicode__ on Python 2
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)

Resources