Saving result of has_one association to avoid fetching DB in Rails? - ruby-on-rails-3

I have a has_one association between User model and Player model. I see myself doing current_user.player so many times in controllers and views, and I feel like I am hitting the DB way too much every time I do that. Also it would be nice to have a current_player method.
How and where would I define a method like that so I can access current_player from both the controllers and the views?

It's (properly) going to reload at least once each time you hit the page, but you can help prevent following loads by memoizing the result:
class User
has_one :player
def current_player
#current_player ||= player
end
end
As an alternative, you could possibly include the player model
in the default scope, so it loads whenever the User model is loaded:
class User
has_one :player
default_scope includes(:player)
end
Unfortunately, whenever I've tried that I tend to quickly find I actually didn't want it auto-loading the other table every time, and switch back to the previous method which only loads from the 2nd table on first use. Simply memoizing the object into an ivar is vastly more flexible.

Related

Rails Uniqueness: true model with a DB with has_many references - Ruby on Rails

I have a problem. I need to set a model of report_templates unique in my database in relation to the classroom, each classroom has only one report_template.
But in my DB, I already have a classroom with multiple report_templates.
is it safe to add this validation to report_template model upload to staging?
There are two approaches:-
If you add validation then you will get error when you are editing existing report templates. This is because validations are called when you save the record. So you might have to remove the duplicate/multiple records manually via console or db or a rake task.
Simply accessing the record will not throw an error.
If one classroom has only report template do you think it is better to use either of below? I do not know the exact scenario so cannot suggest an approach.
has_one association
belongs_to association
Thank you.

Rails has_many through: association or simple has_many/belongs_to association

It's been a while since I've used a join table so I'm looking to refresh my memory on best practice usage.
I have a Rails 3.2.19 app that has a Unit model and I will be adding a Maintenance model. The idea is to create a resource to add maintenance records for each unit. So for instance when the tires are rotated or the oil is changed a maintenance record is created and the unit is assigned to that maintenance record.
I'd like to be able to iterate over each maintenance record in a view, displaying the unit name, type of maintenance, and details of what maintenance was performed.
I'm unsure of the best way to do this via associations. Here was my initial thought:
unit.rb
has_many :maintenances
maintenance.rb
attr_accessible :unit_id
belongs_to :unit
That should allow me to iterate over each maintenance object and display the records for a particular unit. But something doesn't seem right. I'm wondering if I need to setup a join table and do a has_many :through like this.
unit.rb
has_many :unit_maintenances
has_many :maintenances, through: :unit_maintenances
maintenance.rb
has_many :unit_maintenances
has_many :units, through: :unit_maintenances
unit_maintenance.rb
attr_accessible :maintenance_id, :unit_id
belongs_to :maintenance
belongs_to :unit
I am a bit unsure if I'm going overboard here and if I even need a join table considering there will be multiple maintenance records each with one unit assigned to it. I'm thinking that a basic has_many and belongs_to association will work but I'm also wondering if I need to do a join table at all.
I'd also like to be able to see all maintenance records by truck, search by truck in the view, and also setup alerts if a certain threshold is met (like oil_change_mileage is > 5000).
If I can clarify what I'm trying to do here, please let me know. But basically I'm setting up maintenance records for each unit so we can keep a record of what was done and hopefully build it up into something a bit more robust.

What is the best practice for handling one controller with multiple entry points?

Users come to my app to enter Cards that they own. Cards are organized by Issue such that
Issue has_many Cards
So our base case (1) is when a user is logged in and updating his collection, he visits
/issues/{id}
Which hits issues#show renders issues\show.haml. On this page they enter or remove cards from their collection. The page has all sorts of sorting and buttons etc...
I want to make user collections public (2), so that others can visit
/{username}/issues/{id}
This page would have far less going on and would display other information relevant to the logged in user, not the owner of the cards. The obvious choice is to nest :issues under :users and make IssuesController#show handle everything. But IssuesController#show is already handling the first case described above.
One implementation is to do:
class IssuesController
def show
if(params[:user_id])
#do something
elsif
#do and render something else
end
end
end
...but that looks horrible. Further, this is a notion that we'll be using around the app and I'd hate to pollute all the controllers like that.
What is the best practice for handling this situation?
For a start /issues/:id should be handled by IssuesController#show not #index
You can choose to route /:user_id/issues/:id to any controller and action that you like. There is not necessarily a best practice for this, so pick something you're happy with. I'd route this to something like IssuesController#show_for_user so it was nice and clear.

Using Devise to check a resource against current_user

I'm using Rails 3 and Devise 2.0
In the index view of the Posts resource, I want to display a vote button unless the current_user has already voted.
I am only passing in #posts = Post.all into the index view. What's the best way to check each post to see if the current_user has already voted and render the view accordingly?
I'm currently trying to do this by having a voted? method in my Post model, but the current_user method is not available there.
The other solution I see is to have if letter.votes.find_by_user_id(current_user.id) in the index view, but I'm not sure if this belongs in view logic.
One good solution would be to implement a method in your Post model or a helper as follows (assuming post has_many votes):
def voted?(user)
!votes.find_by_user_id(user.id).empty?
end
Then, in your view you can put if post.voted?(current_user)
You are right, the logic belongs in the model, and the model does not have any knowledge (nor should it) of anything outside the model, such as the current user. You have to pass it in as an argument
You have a Post, a Vote and a User model
And you want to know when a post has a vote from a specific user
One way to do it could be Justin's method, but that will produce way too many database queries than needed
A better solution would be to use a has_many :through association like this:
class Post
has_many :votes
has_many :voted_users, through: :votes, source: :user
end
And now you can call #posts = Post.includes(:voted_users)
This will eager load all the users that voted on each post
And you could just say
if post.voted_users.include? current_user
#do stuff
end

Ruby On Rails: Ask for Confirmation When Table Entry Associated With Another Is Destroyed

I would like some assistance with the following problem:
I have a table of groups that is self-associated with itself, so each group is (optionally) linked to another in a hierarchical fashion. I want to write some code that will somehow check before the destruction of a group entry, if it has any children, and ask the user for confirmation, or whether they wish to delete the child groups as well.
I've looked at callbacks, but I don't know how to get the confirmation request to the end user in the view, and then get the response back to the model's callback.
Thanks
(Note: I'm a Rails noob)
Maybe you could probably use, say, a "before_destroy" wrapper in your models somehow:
def before_destroy
raise flag unless okay_to_destroy?
end
But since this decision is pushed to the user before you even destroy any models, it seems to make the most sense to me to just handle this straight forwardly. Present the user with the relevant information (# children, confirmation of parent to delete), let them select a radio button or whatever to destroy children/just parent/cancel, then destroy the appropriate records.