I start to use Socialization gem.
So, created User model with devise:
class User < ActiveRecord::Base
has_many :posts
devise :database_authenticatable,
:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable
acts_as_follower
acts_as_followable
acts_as_liker
end
Then I created Post with scaffold:
class Post < ActiveRecord::Base
belongs_to :user
acts_as_likeable
end
And I want to allow user like posts. But I don't know how to create view with like button, also I dont know how to write methods for likes. Please give me little example. I'm new in rails
I create link in veiw/posts/show.html.erb.
<%= link_to "Like", like_post_path(#post),
:method => :post, :class => 'btn btn-primary btn-xs' %>
And method in app_contoller:
def like
#post = Post.find(params[:id])
current_user.like!(#post)
end
How to write route for this?
You can already test in your console to see how it works first: rails c
user = User.first
post = Post.first
user.like!(post)
user.likes?(post)
So you can create an action: likes in your Posts controller.
def likes
#user = current_user # before_action :authenticate_user, only: [:likes]
#post = Post.find(params[:id])
#user.like!(#post)
redirect_to :back, notice: "Liked this post successfully!"
end
And create a route for that action:
get 'post/:id/likes', to: 'posts#likes', as: :likes
And in your views:
<%= link_to 'like', likes_path(#post) %>
Related
I have an application with users using devise for authentication, in the user model I have added in the database a column called admin with false value by default. that way I have managed to have access as administrator to certain parts of the application.
I have a subscription model and each user when authenticated gets a free value by default. what I want to achieve is that the admin user in your user list can be able to switch from free to premium. this is the code i have and i can't get it to work.
Users Model:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
#Validaciones
validates :nombre, :apellido, presence: true
devise :database_authenticatable, :validatable, password_length: 8..128
#Relaciones
has_many :patients, dependent: :destroy
has_many :articles, dependent: :destroy
has_one :profile, dependent: :destroy
has_one :suscription, dependent: :destroy
#Creación de perfil
after_create :set_profile
def set_profile
self.profile = Profile.create()
end
#Creación de suscripcion
after_create :set_suscription
def set_suscription
self.suscription = Suscription.create()
end
end
Suscription Model:
class Suscription < ApplicationRecord
belongs_to :user
enum status: {
free: 0,
premium: 1
}
end
Users controllers:
class UsersController < ApplicationController
def index
#pagy, #users = pagy(User.order(created_at: :asc), items:12)
end
def show
#user = User.find(params[:id])
end
end
Suscriptios controller:
class SuscriptionsController < ApplicationController
before_action :set_suscription
def show
end
def edit
end
def update
#suscription = Suscription.find(params[:id]).update_params
redirect_to profile_path
flash[:notice] = "La suscripción ha sido actualizada"
end
private
def set_suscription
#suscription = (current_user.suscription ||= Suscription.create)
end
def suscription_params
params.require(:suscription).permit(:status)
end
end
Route:
#UPDATE PREMIUM
patch "suscriptions", to:"suscriptions#update", as: "user_premium"
View (Link):
<%= link_to 'Update', user_premium_path ,method: :patch %>
This should fix it:
subscriptions_controller.rb
def update
#suscription = Suscription.find(params[:id]).update(subscription_params)
redirect_to profile_path
flash[:notice] = "La suscripción ha sido actualizada"
end
view
<%= link_to 'Update', user_premium_path(id: #subscription.id, status: "premium"), method: :patch %>
One other thing that is not needed, but normally I would see something like this in a controller:
private
def set_suscription
#suscription = Suscription.find(params[:id])
end
which then makes your update method look like this:
def update
#subscription.update(subscription_params)
redirect_to profile_path
flash[:notice] = "La suscripción ha sido actualizada"
end
This is all assuming you are simply trying to update the subscription from free to premium with your link_to. I wouldn't recommend doing anything like this, because what if someone accidentally marks this? They can no longer go back to a free subscription. Maybe have a modal open that is routed to subscription edit with a drop down to select the status would be better?
This is my posts controller:
class PostsController < ApplicationController
before_action :authenticate_user!
def index
#post = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(set_post)
#post.user_id = current_user.id
if #post.save
redirect_to post_path(#post)
else
redirect_to new_post_path
end
end
My models:
class Post < ActiveRecord::Base
has_attached_file :image, styles: { medium: "400x400#" }
validates_attachment_content_type :image, content_type: /\Aimage
\/.*\Z/
belongs_to :user
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts
end
Now what I have to do is in my index action where there are all posts I need only the post of user who created it, so when user gets logged in he
should be redirected to his own posts instead of all posts. I am new to rails, any suggestion would be appreciated. I don't know what to put in index and what to add in views. I have used Devise
This would do that:
def index
#post = current_user.posts
end
Just change your controller's index method.
def index
#posts = Post.where(:user_id => current_user.id)
end
This will give you an array of posts belonging to the user logged in. And one more thing, please rename the object in index from 'post' to 'posts' since the result is not a single post.
Hey there,
I am fairly new to Rails and I've managed to create a Favorite controller for my Items(Tools) and Users, which works totally fine.Now I am trying to do the same just in that user module. So users are able to favorite other users. I played around, and came up with this:
I am getting this error in the browser when accessing /users/index view:
NoMethodError in Users#index
undefined method `favorite_user_path' for #<#<Class:0x8ca77b8>:0x8ca50b8>
Here is my code:
app/models/favorite_user.rb
class FavoriteUser < ActiveRecord::Base
belongs_to :c_user_id
belongs_to :user_id
end
app/models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :tools
# Favorite tools of user
has_many :favorite_tools # just the 'relationships'
has_many :favorites, through: :favorite_tools, source: :tool # the actual tools the user favorites
# Favorite users of user
has_many :favorite_users # just the 'relationships'
has_many :userfavorites, through: :favorite_users, source: :user # the actual users the user favorites
has_many :userfavorited_by, through: :favourite_users, source: :user # the actual users favoriting a user
mount_uploader :avatar_filename, AvatarUploader
end
app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :find_user, only: [:show, :favorite]
# Add and remove favorite recipes
# for current_user
def userfavorite
type = params[:type]
if type == "favorite"
current_user.userfavorites << #user
elsif type == "unfavorite"
current_user.userfavorites.delete(#user)
else
# Type missing, nothing happens
redirect_to :back, notice: 'Nothing happened.'
end
end
def index
#users = User.all
end
def show
#tools = Tool.where(user_id: #user).order("created_at DESC")
#tool = Tool.find(1)
end
private
def find_user
#user = User.find(params[:id])
end
end
app/views/users/index.html.haml
- #users.each do |user|
= image_tag gravatar_for user if user.use_gravatar == true
= image_tag user.avatar_filename.url if user.use_gravatar == false
%h2= link_to user.username, user
%p= link_to "Favorite", favorite_user_path(user, type: "favorite"), method: :get
%p= link_to "Unfavorite", favorite_user_path(user, type: "unfavorite"), method: :get
app/config/routes.rb
resources :users, only: [:index, :show, :userfavorite] do
get :userfavorite, on: :member
end
I hope the provided data is enough, if not please tell me. I'm grateful for all Your replies.
You haven't declared any such path in the routes file. As per your routes file you can use named path like
userfavorite_user_path(user_id)
I am stuck with the friendships model. I can be friends with an user multiple times. So I need a condition to avoid add to friend link .
My users_controller :
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
#users = User.all
end
def show
#user = User.find(params[:id])
#topics = #user.topics.paginate(page: params[:page])
#friendship = #user.friendships.build(:friend_id => params[:friend_id])
#friendships = #user.friendships.all
end
my show.html.erb:
<section>
<h1><%= #user.username %></h1>
<%= link_to "Arkadaşlarıma Ekle", friendships_path(:friend_id => #user), :method => :post,class: "btn btn-large btn-primary" %>
</section>
my friendships_controller :
class FriendshipsController < ApplicationController
before_filter :authenticate_user!
def create
#friendship = current_user.friendships.build(:friend_id => params[:friend_id])
if #friendship.save
flash[:notice] = "Arkadaşlara eklendi."
redirect_to root_url
else
flash[:error] = "Arkadaşlara Eklenemiyor."
redirect_to root_url
end
end
def destroy
#friendship = current_user.friendships.find(params[:id])
#friendship.destroy
flash[:notice] = "Arkadaşlarımdan kaldırıldı."
redirect_to current_user
end
end
so I guess , I tried add this method in users_controller but still no solution for it. Can you help me to fix it?
def friend?(other_user)
friendships.find_by_friend_id(other_user.id)
end
and In before link
<% unless friend?(#user) %>
%= link_to "Arkadaşlarıma Ekle", friendships_path(:friend_id => #user), :method => :post,class: "btn btn-large btn-primary" %>
<%end %>
My user model :
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username
# attr_accessible :title, :body
has_many :topics
has_many :posts
has_many :friendships
has_many :friends, :through => :friendships
has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id"
has_many :inverse_friends, :through => :inverse_friendships, :source => :user
end
my Friendship model :
class Friendship < ActiveRecord::Base
attr_accessible :friend_id, :user_id
belongs_to :user
belongs_to :friend, :class_name => "User"
validates :friend, :presence => true, :unless => :friend_is_self
def friend_is_self
user_id == friend_id ? false : true
end
end
I think it is best to do such validations on the model level. use validate_uniqueness_of in your model and test for validity in your controller.
I think the friend? method should be something similar as:
def friend?(other_user)
current_user.friendships.find_by_friend_id(other_user.id)
end
since I guess friendship should be a table with user_id and friend_id, what we want to check is if this user has othter_user as a friend or not.
Your friend? method is returning the friendship or nil, not true or false as you would expect with a ? method.
Try
def friend?(other_user)
# this assumes Friendship is a user, which probably isn't true
# but I don't have your models but this should give you the right idea
self.friendships.include other_user
end
I am trying to show a list of user's books,but for some reason the saved books won't appear on the view.The application is supposed to allow a signed in user to save books and then show list of books saved by that particular user. Here is my code..
<h1>Home#index</h1>
<%=link_to 'add a book',new_book_path%>
<ul>
<% #books.each do |b|%>
<li><%= b.title %></li>
<li><%= b.author %></li>
<%end%>
</ul>
BOOK CONTROLLER
class BooksController < ApplicationController
def index
end
def create
#book=current_user.books.build(params[:book])
if #book.save
redirect_to '/home/index'
else
render :action =>'new'
end
end
def new
#book=Book.new
end
end
Home controller
class HomeController < ApplicationController
#kip_before_filter :authenticate_user!
#efore_filter :homenticate_user!
def index
#books=current_user.books
end
def show
end
def welcome
end
end
Book model
class Book < ActiveRecord::Base
has_many :book_ownerships
has_many :users,:through => :book_ownerships
end
User model
class User < ActiveRecord::Base
has_many :book_ownerships
has_many :books,:through => :book_ownerships
has_many :skills
# Include default devise modules. Others available are:
# :token_authenticatable, :lockable, :timeoutable and :activatable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation,:firstname
end
Book ownership model
class BookOwnership < ActiveRecord::Base
belongs_to :user
belongs_to :book
end
Book view
<h1>Book#new</h1>
<p>Find me in app/views/book/index.html.erb</p>
<%= form_for(#book) do |f|%>
<%=f.text_field :title%>
<%=f.text_field :author%>
<%=f.submit%>
<%end%>
I assume that the first view in your example actually is Books#index and not Home#index and if that is true then you need to set the variable #books to something in the controller.
It should be enough to make the index action in your BooksController look like this:
def index
#books = current_user.books
end
At least if you are using Rails 3. If you are on an earlier version then you should add the call to the all method like this:
#books = current_user.books.all