Rails: should I use STI? - ruby-on-rails

I want to present my case, and know whether or not I should use STI solution.
I am creating a message-board website and so far I have couple of Models: User, Topic, Post..
to make it clear: Post is like a comment for a Topic. Topic has title and content. Post has only has content.
Now, the User has the option to Like/Dislike a Post or a Topic.
I thought about three options:
Topic and Post don't have a connection (each Model has "num_of_likes", "num_of_dislikes")
Topic inherit Post.
Topic and Post inherit from a Base Model which can be called LikeableObj for example.
Which of those three options is the most suitable for my needs?
Is there a fourth option I didn't think about?
What if I'd like in the future to have a third Model which can be Liked?

I assume you'll want to keep track of whether a user has liked a certain post or topic, so I would make a join model for likes that connects a user to either a post or topic.
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :liked_obj, polymorphic:true, counter_cache:true
end
Since the liked_obj is polymorphic, it can be a post or a topic. You can then put has_many :likes on those models and a column likes_count, which will be updated automatically as a counter cache.
If you have any code that deals with likes that is common between Post and Topic, put it in a module Likeable and include it in both classes.

Related

Rails: Models design for a questionnaire application

I am very new to rails. I am currently working on this questionnaire application that open once every few months. Responses given by the users will be saved in the database for a few survey rounds and then be archived and deleted afterwards.
Administrators are able to view the responses, and modify the existing list of survey questions for the next round of survey. Administrators have a fixed user account under users table as I am currently using devise for authentication.
The part that I can't wrap my head around is how do I make it such that modifying questions can be possible without affecting the existing responses of past questionnaire rounds. I have thought of duplicating the questions but I'm not too sure on how to implement it due to my lack of my understanding of rails.
This is the current model I have came up with:
class Questionnaire < ApplicationRecord
has_many :responses
end
class Response < ApplicationRecord
belongs_to :questionnaires
belongs_to :users
belongs_to :questions
end
class Question < ApplicationRecord
has_many :responses
end
class Users < ApplicationRecord
has_many :responses
end
#zhenbin I would suggest you to use something as act_as_versioned gem which keeps the version with every change in questions . So when ever new user gives survey latest question is pulled but when survey responses are pulled its pulled with its corresponding question
Why do you want to modify questions? If you make the next round of surveys, just create new ones.
Furthermore, in your model you can't write belongs_to with pluralized names as you will get an error, refer to http://guides.rubyonrails.org/association_basics.html#the-belongs-to-association for more details.
I would suggest exporting the questions and answers from the database after each survey round, that way you can always modify questions at a later date without having to worry about maintaining older question/answer relationships.
It could (for example) be exported to a database dump file, or a CSV file (marketing departments love those). Exporting to a file in ruby isn't very complicated, and I think you'll be able to find many resources for doing so. For a CSV export, for instance, check out the CSV class.
Good luck!

How do I create a voting system in Rails 4 for my blog posts that requires more than two options for voting?

I have built a very simple rails blog that is based on therapy-like sessions in real life. At the end of every blog post, a user can vote on the post where it says "How does that make you feel?"
I am nearly finished developing the application but I can't figure out how to make an expanded voting system.
There are 6 different emotion options that the user needs to be able to vote with (Happy, Sad, Angry, Inspired, Boring, Anxious). This means that one vote is not in any way better than the other. There are no positive and negative votes. They're just different.
So far, all the gems and tutorials I have come across feature a voting system that consists of two options. I need a way to implement 6.
Lastly, I would like to be able to count all of the total emotions belonging to a particular blog post and display the emotion with the most votes next to the title.
Has anyone ever tried something like this? After I figure out how to do this, I would like to make it into a gem if there isn't already one.
(I'm assuming a user just picks one vote per post, and that you're using the latest Rails 4.2)
Just create a new table that references both User and Post which has an integer field that we're going to use the new enum with, eg. Vote with integer field choice, so the model will be:
class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :post
enum choice: %i[happy sad angry inspired boring anxious]
end
And your User and Post models will both has_many :votes
Then (as per the docs) you use Vote.choices to get a hash of name to integer (you'll use this to populate your view).
...and lastly, you'll get a hash of the count of emotions for a blog post with:
post.votes.group('votes.choice').count
I'm sure you can pick the most votes in there.
Update
The OP asked in a comment where I found this out, I thought my response to him might help others:
Hmm, well aside from the docs that I already linked you to in my answer, I follow the rails-core mailing list which announces and discusses upcoming features, I follow #rails on twitter where they announce all sorts of things, I read the release notes for new versions and I go through the release notes in the guides after major releases.

How to handle rails 3 model relationships at view and controller level?

I have a project going on right now that is really big data model wise. I am trying to figure out the best way to handle inter-model relationships.
For the sake of brevity:
Car
has_many :passengers
has_many :items
or
Team
has_one :head_coach
has_many :coaches
has_many :players
belongs_to :owner
So from the show page I would see who is in the car and what items are in the car. I have some co-workers who think we should have a controller action called manage where they would click a link on the show page to manage the relationship between the other models
So the Team controller would have this
class TeamController < ApplicationController
# ... magic ...
def manage_players
#signed_players = Player.signed_players
#free_agents = Player.free_agents
end
end
The manage_players view would just have links to the actual RESTful actions on the appropriate controller to remove relationships etc...
Anyone have thoughts on how this should be accomplished?
That's an overly complicated approach, and the good news is, it's way simpler than you think.
Save yourself some trouble. The quick answer to your question is to use nested resources: you can have a single form that handles the Car and all the associated passengers/items, or the Team and its coach, players, etc.
The action/view you're describing would just be the edit action on the Car/Team. The manage action name is a nice idea and all, but the action you're really taking is an edit (nothing special, by what you're describing), so why confuse what's going on when the default is to call it edit?
If you want a live example of something that takes advantage of nested routes, check out rpglogger.com (it's my site). When you play around with it, notice the routes/URLs in the address bar.
It's also open source. Specifically relevant to your question is:
see the routes.rb file, and note how I define resources on sections twice - this actually gives me two different versions of the routes - one that's scoped to the LogBook, and one that's scoped to the objects in a section
see the world_object_form.haml (haml also rocks, FYI), which is both my new and edit form - yet it's short, rather uncomplicated, and pretty easy to read/undestand given what it does.

How can I expose a Mongoid embedded collection?

I have mongoid setup in my rails3 app, and have created 2 models.
One model is user, and the other model is article.
Since I each user can create many articles, I have put:
embedded_in :user
in model/article.rb file, and:
embeds_many :articles
in model/user.rb file.
Now, if I access article by 'app_url/articles/random_article_id' I get the following error.
Access to the collection for Article is not allowed since it is an embedded document, please access a collection from the root document.
While I want to maintain relationship, I want articles to be accessible to any people. How can I do that??
It sounds like what you want is a referenced relation rather than an embeds relation for this: http://mongoid.org/docs/relations/referenced.html
also, if you really need to make articles embedded, do this:
User.where("article.id" => params[:id].first.articles.find(params[:id])
but, as Ben said, you would better use belongs_to instead of embedded_in.

How to create a view to manage associations between HABTM models? (Rails)

I am using Ruby on Rails and need to create a view that allows the creation of records through a HABTM relationship to another model. Specifically, I have the following models: Customer and ServiceOverride, and a join table customers_serviceoverrides. Using the customer view for create/update, I need to be able to create, update and delete ServiceOverrides and manage the attributes of the associated model(s) from the same view.
Visually I'd prefer to have something like a plus/minus sign to add/delete service overrides, and each serviceoverride record has two string entities which need to be displayed and editable as well. However, if I could just get the code (a kind of nested form, I'm assuming?) working, I could work out the UI aspects.
The models are pretty simple:
class ServiceOverride < ActiveRecord::Base
has_and_belongs_to_many :customers
end
class Customer < ActiveRecord::Base
has_and_belongs_to_many :serviceoverrides
end
The closest thing I've found explaining this online is on this blog but it doesn't really address what I'm trying to do (both manage the linkages to the other model, and edit attributes of that model.
Any help is appreciated. Thanks in advance.
Chris
The ascii cast at http://asciicasts.com/episodes/17-habtm-checkboxes has a simple and functional example.

Resources