Skip to content

Instantly share code, notes, and snippets.

@randalmaile
Last active January 2, 2016 01:49
Show Gist options
  • Save randalmaile/8232545 to your computer and use it in GitHub Desktop.
Save randalmaile/8232545 to your computer and use it in GitHub Desktop.
Bloccit - Favoriting
1. Favorites model - is this just a pure association - in terms of the database - interesting that we only store references to users and posts. Any other way to do this than create a table? I guess you need to persist the absence or presence of either the user_id or post_id, no?
2. In the link_to helpers in the _favorite partial:
a. [topic, post, favorite/Favorite.new] provides the route or path ?
b. method: :post/:delete provides the action or method ?
3. In the create method, why are we attempting to create and validate? wouldn't we instantiate a new object and then validate? then save? and if save, flash error or not??
a. OK - I'm thinking about it more now - in the view, we created a new object already - so now the question is what does valid? really mean once the create AR method has already fired?
4. Can you explain why we created the send_favorite_emails as a private method?
## Requirements:
1. users need to opt-in or opt-out of receiving emails from Bloccit;
2. need a model to know which posts a user has favorited;
3. need to add a "Favorite" button on the posts/show.html.erb view to allow users to flag a post as a "favorite"
4. need to create email notifications when a new comment is added to a favorited post.
### Favoriting functionality:
1. Enable email_permissions on the User model: rails g migration AddEmailPermissionsToUser email_permissions:boolean
a. in migration file, add: , default: false to the :boolean symbol in the add_column method
2. Make :email_attribute accessible in user.rb model
3. Create a Favorite model: rails g model Favorites user:references post:references # this is interesting because there are no columns in the table other than foreign keys!!!
4. add has_many to both user.rb and post.rb - don't forget to add , dependent: :destroy
5. Modifiying views: You will need to have a button that toggles: "favorited" or "unfavorite" - in order to do that you need a method to return a valid object if it has been favorited - usual place - in the user.rb model:
a. def favorited(post)
self.favorites.where(post_id: post.id).first # again, we're using first to return an actual object
end
6. Generate a favorites controller and add a resource to routes - only creating and destroying:
- resources :favorites, only: [:create, :destroy]
7. Create a partial for _favorite - addin UI:
- # if the post is favorited, set the class to button style 1 / "Favorited" text
- # if the post is unfavorited, set the class to button style 2 / "Unfavorite" text
- if current_user.favorited(post) # if the post is already favorited, then click will fire off either the create or destroy actions in the favorite controller
= link_to [topic, post, favorite], class: 'btn btn-small', method: :delete do #this method will route via the delete method
i%.icon-star-empty Unfavorite
- else
= link_to [topic, post, Favorite.new], class: 'btn btn-small', method: :post do #this method will route via the create method
i%.icon-star Favorite
8. Create the create and destroy action in the favorites_controller.rb
a. Get @topic and @post
b. save a new @favorite to the db: creted from current_user and pass in @post
c. if valid? flashNotice/redirect || flashError/redirect
### Creating Mailer
1. rails g maile <name> to create a new mailer class
2. add a new_comment(user, post, comment) method # this is setting up the instance vars, headers and the actual mail command that fires off the email
a. This is more similar to a controller and not a model - you have have views that take instance variables you created in the class - feed to, say an email message you create in /views/favorite_mailer/
b. creted the views that comprise the email message with @post.title, @comment.user.name, @omment.body and a link_to a the new comment on post#show
3. What this means is that there needs to be something to invoke the mailer in the comment model for a new comment for a favorited post!!
a. after_create: :new_method
b. def new_method
self.post.favorites.each do |favorite|
FavoriteMailer.new_comment(favorite.user, self.post, self).deliver
end
end
@mkwiatkowski
Copy link

Now the questions.

  1. You need to store the information somewhere. In case of one-to-many relationship (like comment belongs to post) you store the id of the relevant post in one of the models (in this case post_id is in the comments table). In a many-to-many relationship you don't know how many records you are going to store, so you can't prepare columns for it. You need a new table instead. This is an important concept. I'd advise you to read in detail about different types of relationships and how they map to the database structure in the official Rails guide: http://guides.rubyonrails.org/association_basics.html
  2. a. link_to uses the routing system to figure out the URL based on the array of objects. So eventually the array is converted to a path.

    b. :post and :delete are HTTP methods, see http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods . The routing system maps that to proper controller (class) and action (method). Method in a class is not the same as HTTP method, although the name is the same. :)
  3. Play with it in the console, in particular compare how create, new, save and valid? work for both valid and invalid records. In short, it comes down to that: create always returns an instance, no matter if it saved it to the database or not. If the record did not save it was because of validations, so valid? is a good way to check if the record saved or not.
  4. We talked about that during the meeting already, but basically it comes down to encapsulation. You can read more about it here: http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment