I am trying to implement a resume feature and I was wondering the best practice for handling it. Lets assume a user has 2 pieces to a resume, education and work experience, and this is constant among all users. Then under each I want to save titles of things they've done (eg. Attended school at ______, worked at ________, project doing _______). Within these I want to save a description of that specific activity. What would be the best practice for implementing this?
So I need some association like: a user has_many experiences. An experience has_many titles. A title has_many descriptions. I also need to make the title of the experience is associated with the correct header (education or work experience).
I'm still pretty new to rails, and I'm sure there is a much easier and intuitive way to do this. Thanks for the help!
You can try these simple models structure for
class User < ActiveRecord::Base
has_many :locations
has_many :projects, through: experience_projects
end
class Location < ActiveRecord::Base
belongs_to :user
end
class Experience < ActiveRecord::Base
#experiences table should contain title and descriptions
belongs_to :user
has_many :projects, through: experience_projects
end
Now Join model if you do not require this intervention model you can directly use has_and_belongs_to_many
class ExperienceProject < ActiveRecord::Base
belongs_to :user
belongs_to :experience
end
Related
I'm creating an app that has a User and a Plugin model. A user can have multiple plugins and a plugin can belong to multiple users, which I've implemented using a junction table.
class Plugin < ActiveRecord::Base
has_many :user_plugins
has_many :users, through: :user_plugins
end
class User < ActiveRecord::Base
has_many :user_plugins
has_many :plugins, through: :user_plugins
end
class UserPlugins < ActiveRecord::Base
belongs_to :user
belongs_to :plugin
end
However, I then want to store arbitrary data for each user plugin (for example, things like api keys, options etc that can differ for each plugin.).
My initial approach was to have a user_plugins_options that joined on user_plugins, but I can't seem to get this to work correctly.
class UserPluginOptions < ActiveRecord::Base
belongs_to :user_plugins
end
My question, how should I go about approaching this to best work with ActiveRecord?
I think you misnamed your class, as the table is user_plugins but the model is UserPlugin. It’s plausible you are running into issues because of this.
Agree with Alex. Why don’t you create a json field on UserPlugin called options and keep a hash of plugin specific values here.
If you must have another table, you should add a has_one :user_plugin_option to your UserPlugin
I'm uncertain of the best approach to model conversation relationships.
My application has Users, Conversations, UserConversations, Venues, & VenueConversations.
Users can have many Conversations & Conversations can have many Users. Thus, the bridging table (UserConversations).
Venues can also have Conversations and these Conversations can also have many Users. Thus, the bridging table (VenueConversations)
I've tried it with polymorphic associations but then Messages in the Conversations became difficult to manage. Also, a while back I asked a question on Stack and someone said I should steer clear of polymorphic associations at all costs.
I hope to do this properly so that querying doesn't become a nightmare in the future.
I'd also like to state I'd like to have one Conversation model because one day they'll share a lot of behavior.
User.rb
class User < ApplicationRecord
has_many :user_conversations
has_many :conversations, through: :user_conversations
has_many :venue_conversations
has_many :conversations, through: :venue_conversations
end
UserConversation.rb
class UserConversation < ApplicationRecord
belongs_to :user
belongs_to :conversation
end
Venue.rb
class Venue < ApplicationRecord
has_many :venue_conversations
has_many :conversations, through: :venue_conversations
end
VenueConversations.rb
class VenueConversations < ApplicationRecord
belongs_to :user
belongs_to :venue
belongs_to :conversation
end
The problem I'm having now is that when I do User.first.conversations I only find one of the types of conversations a User could have(Private vs Venue). It reflects the last definition I gave to has_many :conversations in the User.rb model. Perhaps a scope is in order? How would I make a distinction between private & venue conversations as well?
Please advise me on how I could resolve this or take a better approach
I've found good answers here, here, and here but I'm having trouble generalizing that to what I'm after.
I have multiple categories, that will be curated and selectable. So, users will be able to select cat1, cat2, and cat3, but not type a custom category.
A category can have many posts, a post can have many categories.
A post can have many comments.
A user can have many posts, and many comments.
For the post/category relationship, I'm thinking this will work, but the user/post/comment relationship is where I'm scratching my head...
# app/models/category.rb
class Category < ActiveRecord::Base
has_and_belongs_to_many :posts
end
# app/models/post.rb
class Post < ActiveRecord::Base
has_and_belongs_to_many :categories
belongs_to :user
has_many :comments
end
# app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
has_many :comments
end
# app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
Does this look close? Do I need any foreign keys anywhere to handle all this? Thanks in advance, I'm sure this is simple and I'm missing something obvious in my understanding.
And then I have to worry about how to write the tests for all this! That's for another day though...
EDIT: I should point out, I haven't started this yet. Just trying to map it out before I start, so it should simplify things, fewer migrations, etc.
EDIT AGAIN: Implemented suggested changes so far. Thanks!
why not start with the specs first? is a good practice on rails with all the power you have with rspec
Your Item should be called Post, why Item? is there any reason? if you want to call it "Item" you need to specify that on the associations
belongs_to :post, class_name: 'Item'
but you are better with Post instead of Item
A comment belongs to a user so the the user has_many :comments, you don't need the ", through: :posts" part
has_many :category_posts
has_many :posts, :through => :category_posts #or would has_and_belongs_to_many work better?
this depends on you, you need extra behavior on the CategoriesPosts? (Categories, in plural) if not, just use has_and_belongs_to_many
Really, i would suggest you start with the specs, you will end up with the implementations without thinking it too much and then you already have it tested and then you can add more specs and refactor it. Read something about TDD and BDD, it's hard at first but it's really good when you get it.
The only change I think I would make to this, other than actually naming Item Post, would be on your user model:
# app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
has_many :comments
end
You don't need a through association there. You could add other scoped comments to be something like comments_on_my_posts, through: :posts, class_name: "Comment", but for the above association on comments, it should be direct (commenter <=> comment).
In my rails app, user's can create Designs.
Design.rb
belongs_to :user
User.rb
has_many :designs
I'm trying to create a new model Look so user's can create Looks. The way I envision this to work is when a user goes to /looks/new, they have a list of all the designs they have favorited (which I have that set up that variable already) in a table format with the right column being checkboxes where the user can go through and check a few of those Designs and click Create. All the Designs that have been checked would be part of that Look.
As I haven't done this sort of thing before, I need some help accomplishing this in all aspects MVC.
Look.rb
has_many :designs
Design.rb
belongs_to :looks # ??? Would the model be something different since technically when you create a design it doesn't belong to a look.
Looks Controller
def new
#designs = #user.favorites #This get's me all the designs that the particular user has favorited
#look = Look.new # ??? Again, as I haven't set this sort of relation up before, I'm unsure.
end
Please let me know any other code I can provide to help out. I may even be making this sound more complicated than it is.
This configuration should work for you Justin:
class User < ActiveRecord::Base
has_many :designs
has_many :looks, through: :designs
end
class Design < ActiveRecord::Base
belongs_to :user
has_many :designs_looks
has_many :looks, through: :designs_looks
end
class Look < ActiveRecord::Base
has_many :designs_looks
has_many :designs, through: :designs_looks
end
class DesignsLook < ActiveRecord::Base
belongs_to :design
belongs_to :look
validates :design_id, presence: true
validates :look_id, presence: true
end
I don't know what you want to do in the future but you might want to consider putting the user_id on the DesignsLook model, so you would not need a complex join query to retrieve all the Looks of a User. And also you implement shared Designs with all users
Your user has many designs. New looks can have many designs. And design can belong to MANY looks, users. Smells like has many ..., :through
http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
class User
has_many :designs, through: :design_possesion
end
class Look
has_many :designs, through: :look_designs
end
class Design
has_many :look_designs, :design_possesion
end
Of course you'll have to create corresponding tables.
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