Ive finished Learning Rails 3 by O'Really, and now its time to experiment knowledge on a real project and I'll be deploying to Red Hat's OpenShift platform.
Searching trough my laptop code projects folder, I came out with a simple TODO task manager ive wrote once in C++. So it would be a good idea to bring that project back to life, this time as a web task managing service in Rails, allowing auth with OmniAuth.
The original C++ project was planned on a OOP point of view. You could create a "Task" object with its current ID number, Text string, Date ,and Time.
Every part of a task was made as a different C++ class. Eash one cointains its validation on the constructor.
And then saved the tasks to sqlite or exporting them as a plain text that you could share or read again on the app.
So, back to business, I'm trying to adapt that little app into something more complex in Rails using MVC.
I thought about adding a Scaffolding that brings the form to fill the task's text field and pass it to the Controller.
The controller will set current date and time, and ID is set by default when saving to the DB.
Validations should go on the model, and I'll create a migration to build a table upon that fields.
As I'll be adding multiuser support with OmniAuth, (so every user could save his own tasks), I should create a new DB table, with users info.
But should I create a new task table for each user, and then mapping them to the users table?
Or just create one task table and drop every user's tasks in there and then mapping all there?
I cant figure out a good with saving user tasks to the db.
Any ideas?
Thanks in advance
This is assuming that a User can have many tasks, but a Task can belong to only one user.
You'll have one tasks table and put all user's tasks there.
You'll want to add a user_id column to the tasks table (rails g migration add_user_id_to_tasks user_id:integer) and add the following to the models -
class Task < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :tasks
end
Reference: Rails Guide to ActiveRecord Associations
You models will look like this:
class User < ActiveRecord::Base
has_many :tasks
end
class Task < ActiveRecord::Base
belongs_to :user
end
Your tables will look like this (in pseudo-ad-hoc-notation):
Users table => id:integer, name:String
Tasks table => id:integer, task:Text, user_id:integer
Does this help?
Related
I currently have a few models, users, clients, addresses and contacts.
I used scaffold to create my client model which only contains name, leadsource and DBA. It is currently working just fine.
My address and contact was created separately as a client can have many addresses and contacts and they require a client_id to set up the relationship.
Assuming I am using your standard crud operations, is there any way to set up a single nested form that will allow me to add all 3 at once?
Sure, the standard way is fields_for.
But normally you also want to dynamically add and remove associated objects (i.e. addresses) and that's a bit more advanced.
There are gems to help you. i.e. cocoon and a great railscast: episode 403.
Unfortunately it's a pro episode, but investing the $9 is well worth it, as the railscasts really are a source of inspiration (at least for me).
I assume, you already have the associations or create them:
rails generate migration AddClientReferenceToAddress client:references
rake db:migrate
and in models:
class Client < ActiveRecord::Base
has_many :addresses
end
class Address < ActiveRecord::Base
belongs_to :client
end
I have a model of say Apps and each App contains a bunch of users, and a reference to the store type, and has the properties, name, app_id, version, and price.
I want to be able to create clones of this app, which has all the same values, save for version, and store type.
I'd like to do this by adding a property/column to my app called "Is_clone", and I'd like a second table called AppToClone, which has two columns App and Clone.
In each row, I'll have say App:1 , Clone:[2,5,7,26]
This way I can edit each clone as its own app, but at the same time I can apply any changes in an app to all its clones.
I've set up the database for AppToClone but I'm stuck on how to create this association within the App Model itself. Examples I've found so far such as the gem rails_lookup_tables seems to only allow a single value rather than an array in the AppToClone table.
Currently in my App model I have the following line:
:has_many :apps, through: :appstoclones
But this doesn't feel correct to me, and I'm not sure how to build that database over time.
Feeling kinda stupid here, but I'm stuck.
So the has_many and belongs_to association stores the data in a different way than the question indicates. I would use single table inheritance, having a Clone model inherit from the App model.
class App < ActiveRecord::Base
has_many :clones
end
class Clone < App
belongs_to :app
end
You would need to have an app_id and type on your app table (strange I know), so your clone can be associated. What you would be able to do then is query your clone as an App.
Clone.last.is_a? App
-> true
What I think is closest to what you actually want though, is outlined in section 2.10 Self Joins of the Ruby on Rails Guides.
class App < ActiveRecord::Base
has_many :clones, class_name: "App",
foreign_key: "parent_app_id"
belongs_to :parent_app, class_name: "App"
end
You need to create the foreign_key in a migration.
To implement the is_clone:
def is_clone?
!!self.parent_app_id
end
To implement the AppToClone:
def clone_ids
self.clones.all.map(&id)
end
# Check it in the console:
App.last.clone_ids
-> [2,5,7,26]
The biggest concern here is thinking that a table will have a row with one column holding an array. That is not normalized! Normal associations work by having the foreign keys as seen in these examples, one per row. If you have a complex has_and_belongs_to_many relationship, the table that holds keys has two columns, each with one id.
Per the request in the comment below (self join update):
def clone_me
self.clones << self.clone
end
> new_cloned_app = App.last.clone_me
The reference for using has_many is found: In the rails guide here. Feel free to use a different helper function. Also, the returned value must be .saveed
I would say you are looking for a has-many belongs-to relationship.
For the has-many part: http://guides.rubyonrails.org/association_basics.html#the-has-many-association
For the belongs-to part: http://guides.rubyonrails.org/association_basics.html#the-belongs-to-association
One model would be the app, the other clone, where the clone table would store the the same fields an app has, as well as the additional fields needed for a clone instance. By inheriting the clone model from the app model which inherits from ActiveRecord, one can use a clone in the code where an app is used.
I would like to create new tables, add/delete columns from within my app. Is this possible?
Yes, you can do whatever the application database user can do to the database with ActiveRecord::Base.connection.execute. For example:
ActiveRecord::Base.connection.execute('ALTER TABLE people ADD name VARCHAR(60);')
But, if you add a column to a table, the corresponding attribute for the column will not be available in the ActiveRecord class until you restart the application.
No. It is not possible. Rails has to run migrations to get the tables in to the database. This requires that the server has be stopped and restarted after the migrations. You don't want this scenario in production.
Dynamic forms would accomplish what I believe you are after.
In short you make fields of a model a separate model. For instance
class Car
has_many :car_fields
end
class CarFields
belongs_to :car
end
Then you can make a form where the users can add and remove fields when the add a car to the database.
This is great explained by Ryan Bates here http://railscasts.com/episodes/403-dynamic-forms
I think you need a subscription to watch it. I you don't have one, get one. Railscasts is great!
The default behaviour for Ruby on Rails is to save changes made to collection associations.
Is there any way to change this behaviour, so that I can modify the collections in memory without the changes being written to the database.
So if I have two classes:
class Project < ActiveRecord::Base
has_many :tasks
class Task < ActiveRecord::Base
belongs_to :project
and write some code like:
Project.tasks.clear
Project.tasks << task1
Project.tasks << task2
then it automatically deletes all tasks associated with the Project and automatically writes the changes to the db.
This is a contrived example of what I'm trying to achieve. I know I could use Project.tasks.build() to add a new task to the collection without it being saved automatically, but the the tasks that I'm adding are not new tasks.They are links to a limited set of tasks defined in db. You could think of them as entries in an enumeration of tasks. In addition Project.tasks.clear immediately hits the db.
In java world, using Hibernate, I would disconnect the entity from the session and be able to modify the entity in memory until reconnecting and saving.
Thanks
Have you tried using the task_ids attribute instead?
Change your code to:
Project.tasks_ids = []
Project.tasks_ids << task1.id
Project.tasks_ids << task2.id
I know this question is a bit old, but since I tried to search a similar problem on Google I thought this might be useful to other people.
This is how my model looks like
User
belongs_to :computer
Computer
has_many :user
Users are created when people register for an account on the web site but computers are pre-loaded data that I create in seeds.rb/some .rake file. All is fine and good when the app is first launched and people start registering and get associated with the right computer_id. However, suppose I want to add another computer to the list
Computer.destroy_all
Computer.create({:name => "Akane"})
Computer.create({:name => "Yoda"})
Computer.create({:name => "Mojito"}) #newly added
running the rakefile the second time around will mess up the associations because computer_id in the User table refer to the old id in Computer table. Since I have run the script above, the id inside the computer table keeps incrementing without any regard to the association that user has to it. All the users now will have no reference back to its computer and all the computers now have new IDs.
Question: Is there a better way for me to pre-load data without screwing up my association? I want to be able to add new Computer without having to destroy the user's table. Destroying the computer table is fine with me and rebuilding it again but the old association that the existing users have must stay intact.
Have you thought about just running down the migration for the computers table?
lets say your migration's called db/migrate/1_create_computers.rb
$ rake db:migrate:down version=1
from the seed remove the destroy method.
You'd always keep the users table...in which by the way you must have a column computer_id
and of course the association goes
ComputerClass < ActiveRecord::Base
has_many :users #(don't forget the 's')
end