Getting ActiveRecord associations belongs_to through - ruby-on-rails

I have models associated with has_many through. I am able to get a relationship in one direction but not the other (there is no belongs_to through setting)
Projects have_many datasets through taskflows. Taskflows are associated to datasets in a join table.
I am able to do Project.datasets simply by using the has_many through setting. I'd also like to call dataset.project to get the associated project of a dataset (through taskflow).
Is this possible? Many thanks for any help.
I have four models (I've tried the delegate setting but it doesn't seem to work):
class Project < ActiveRecord::Base
validates :title, presence: true, length: {minimum: 3}
has_many :taskflows
has_many :datasets, :through => :taskflows
end
class Taskflow < ActiveRecord::Base
belongs_to :project
has_many :dataset_assignments
has_many :datasets, :through => :dataset_assignments
end
class Dataset < ActiveRecord::Base
has_many :dataset_assignments
has_many :taskflows, :through => :dataset_assignments
delegate :project, :to => :taskflows, :has_nil =>true
end
class DatasetAssignment < ActiveRecord::Base
belongs_to :dataset
belongs_to :taskflow
end

has_many_through works both ways.
If you put the has_many_through in reverse in your Dataset Model it should work as you wish.
A good example I use - and I learned on
Recipe Model
Ingredient Model
Component Model
A Recipe has many ingredients through components
An Ingredient has many recipes through components.
In my limited experience with it, your logic makes sense, the has_many through usually flows 'one way' in terms of creation, but in terms of rails it's the same relation type - an ingredient 'has_many' recipes through the components

Related

Which Association Should I Use?

My app has 5 core models. I'm trying to figure out the best way to associate the models. How many tables should I build and which kind etc?
Here are the associations I would like to include and their respective models:
User
Has many boards
Has many lists
Has many cards
Has many comments
Board
Has many users
Has many lists
Has many cards
List
Belongs to board
Has many cards
Card
Belongs to board
Belongs to list
Has many comments
Comment
Belongs to card
Belongs to user
class User < ActiveRecord::Base
has_and_belongs_to_many :boards
has_many :lists, as: listable
has_many :cards, as: cardable
has_may :comments, as: commentable
end
class Board < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :lists, as: listable
has_many :cards, as: cardable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class List < ActiveRecord::Base
belongs_to :listable, :polymorphic => true
has_many :cards, as: cardable
end
class Card < ActiveRecord::Base
belongs_to :cardable, :polymorphic => true
has_many :comments, as:commentable
end
To establish HABTM relation you have to create a table named 'users_boards'
As Board and User are having many to many relationship, there will be a new table for it, if you want HABTM you can use it.
User(id, name, other_attributes...)
Board(id, name,...)
List(id, name, user_id(fk),...)
Card(id, name, user_id(fk), list_id(fk), board_id(fk),...)
Comment(id, comment_msg, user_id(fk), card_id(fk),...)
Board_User(board_id(fk), user_if(fk)) --- M-M relation
Few attributes might change if there is a has_many through relation.
FK-- Foreign key, you can use has_many through depending on your requirements.
Using polymorphic associations has some limitations, so please do through it then decide to use a polymorphic association
http://codeblow.com/questions/pros-and-cons-for-ruby-on-rails-polymorphic-associations/

Whats a best practice for implementing a hierarchical relation in Rails?

I'd like to model users that belong to groups, and groups that belong to groups, so I'm thinking along the lines of (forgive the newb syntax):
class Group < ActiveRecord::Base
attr_accessible :description, :group_id, :name
has_and_belongs_to_many :users
end
class User < ActiveRecord::Base
attr_accessible :email, :name
has_and_belongs_to_many :groups
end
Would the above be a preferred way to implement this? Is there a simple way of deleting a 'parent' group and have it delete it's children?
At the time of the writing, I'm learning with rails 3.2.x ...
I hate to be a gem-pusher, but I recently started using ancestry, and it works very well. It has a unique way of indexing ancestors and descendants for great performance.
There's also a Railscast that covers it.
Ancestry is a gem/plugin that allows the records of a Ruby on Rails
ActiveRecord model to be organised as a tree structure (or hierarchy).
It uses a single, intuitively formatted database column, using a
variation on the materialised path pattern. It exposes all the
standard tree structure relations (ancestors, parent, root, children,
siblings, descendants) and all of them can be fetched in a single SQL
query. Additional features are STI support, scopes, depth caching,
depth constraints, easy migration from older plugins/gems, integrity
checking, integrity restoration, arrangement of (sub)tree into hashes
and different strategies for dealing with orphaned records.
Source: https://github.com/stefankroes/ancestry#readme
I'm guessing here - but would users be able to be in multiple groups and groups would only be in one (a parent group)?
class Group < ActiveRecord::Base
attr_accessible :description, :name
has_many :groups, :dependent => :destroy
has_many :group_users, :dependent => :destroy
has_many :users, :through => :group_users
belongs_to :parent_group, :class_name => :group
end
class GroupUsers < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
class User < ActiveRecord::Base
attr_accessible :email, :name
has_many :group_users, :dependent => :destroy
has_many :groups, :through => :group_users
end

Proper Rails Association to use

I am trying to create an association between two tables. A student table and a computer table.
A computer can only ever be assigned to one student (at any one time) but a student can be assigned to multiple computers.
This is what I currently have in mind. Setting up a has-many through relationship and modifying it a bit.
class Student < ActiveRecord::Base
has_many :assignemnts
has_many :computers, :through => :assignments
end
class Computer < ActiveRecord::Base
has_one :assignment
has_one :student, :through => :assignments
end
class Assignment < ActiveRecord::Base
belongs_to :student
belongs_to :computer
end
Does this seem like the best way to handle this problem? Or something better sound out quickly to the experts here. Thanks!
You need first to decide if a simple one-to many relationship is enough for you.
If yes, it gets a lot easier, because you can get rid of the Assignment-class and table.
Your database-table "computers" then needs a student_id column, with a non-unique index
Your models should look like this:
class Computer < ActiveRecord::Base
belongs_to :student
end
class Student < ActiveRecord::Base
has_many :computers, :dependent => :nullify
end
"dependent nullify" because you don't want to delete a computer when a student is deleted, but instead mark it as free.
Each of your computers can only be assigned to a single student, but you can reassign it to a different student, for example in the next year.
Actually your approach is fine, as one offered by #alexkv. It is more discussion, than question.
Another thing if you want to use mapping table for some other purposes, like storing additional fields - then your approach is the best thing. In has_many :through table for the join model has a primary key and can contain attributes just like any other model.
From api.rubyonrails.org:
Choosing which way to build a many-to-many relationship is not always
simple. If you need to work with the relationship model as its own
entity, use has_many :through. Use has_and_belongs_to_many when
working with legacy schemas or when you never work directly with the
relationship itself.
I can advise you read this, to understand what approach better to choose in your situation:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off
You can also use has_and_belongs_to_many method. In your case it will be:
class Student < ActiveRecord::Base
has_many :assignemnts
has_and_belongs_to_many :computers, :join_table => 'assignments',
end
class Computer < ActiveRecord::Base
has_one :assignment
has_and_belongs_to_many :student, :join_table => 'assignments',
end
or you can rename assignments table to computers_students and remove join_table
class Student < ActiveRecord::Base
has_many :assignemnts
has_and_belongs_to_many :computers
end
class Computer < ActiveRecord::Base
has_one :assignment
has_and_belongs_to_many :student
end

Using Rails, not sure if I should use belongs_to or not

Very new to Rails... I'm building out functionality that lets people compare photos, and I can't decide exactly how I should structure it. Ideally what I'd like is to have a "comparisons" table which keeps a record of the IDs of the photos compared as well as the user that compared them, but I'm not quite sure whether this warrants use of the "belongs_to" function or not. If so, how do I specify that each comparison belongs to TWO separate photos?
The following has_many, :through => Model structure will let you have additonal properties on the join table, e.g. 'comparing_user_id'.
class Photo < ActiveRecord::Base
has_many :appearances
has_many :users, :through => :appearances
end
class Appearance < ActiveRecord::Base
belongs_to :photo
belongs_to :user
end
class User < ActiveRecord::Base
has_many :appearances
has_many :photos, :through => :appearances
end

Rails Polymorphism 'backwards'

Say I'm writing a blog app with models for posts, pages and photos. I've got a category model, that may be linked to any of these models. So, a category may contain various kinds of items. Every item only has ONE category.
I could implement this using a generic tagging pattern with a join table, but I want to make sure every subject can have only category.
What would be the best way to implement this in Rails?
Okay, I think I've got it:
class Post < ActiveRecord::Base
has_one :categorization, :as => :categorizable
has_one :category, :through => :categorization
end
class Category < ActiveRecord::Base
has_many :categorizations, :dependent => :destroy
end
class Categorization < ActiveRecord::Base
belongs_to :category
belongs_to :categorizable, :polymorphic => true
end
Now various models can have a category, but each instance can have only one category… I guess.

Resources