I have a rails app with a basic set up to allows users to upvote pins, those pins are ordered from the most upvoted to the less upvoted. What I would like to do now is to render the lists of pins that a user upvoted on his profile.
Here is my config:
app/controllers/pins_controllers.rb
def upvote
#pin = Pin.find(params[:id])
if #pin.votes.create(user_id: current_user.id)
flash[:notice] = "Thank you for upvoting! You can upvote a startup only once."
redirect_to(pins_path)
else
flash[:notice] = "You have already upvoted this!"
redirect_to(pins_path)
end
end
app/models/pin.rb
class Pin < ActiveRecord::Base
belongs_to :user
has_many :votes, dependent: :destroy
has_many :upvoted_users, through: :votes, source: :user
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
has_attached_file :logo, :styles => { :medium => "300x300>", :thumb => "100x100>" }
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 :pins
has_many :votes, dependent: :destroy
has_many :upvoted_pins, through: :votes, source: :pin
end
app/models/vote.rb
class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :pin, counter_cache: true
validates_uniqueness_of :pin_id, scope: :user_id
end
And my routes.rb
resources :pins do
member do
post 'upvote'
end
end
Do you have any ideas how I could do that?
You can get the pins a user #user upvoted for example by the following:
#pins_for_user = []
#user.votes.each do |vote|
#pins_for_user << vote.pin
end
You can embedd this in your user controller, for example in the show method.
Then you can refer to #pins_for_user in your show view (show.html.erb) and display it by:
<% #pins_for_user.each do |pin| %>
<%= pin.name %> # or any other code to display that special pin
<% end %>
Related
I have setup a rails application with devise on it so users can register and login and they can add posts and other resources based on their roles(Admin,Teacher,Author,Pupil). Admin as access to everything and I am using gem 'cancan' for roles.
if user.role
if user.role.name == "Admin"
can :manage, :all
elsif user.role.name == "Teacher"
can :manage, [Book, Story]
can :read, [Book, Author, Story]
elsif user.role.name == "Author"
can :manage, [Book, Author]
can :read, [Book, Author, Story]
elsif user.role.name == "Pupil"
can :manage, [Story]
can :read, [Book, Author, Story]
elsif user
can :read, :all
end
else
can :read, :all
end
Currently Authors are just added to a book when you create the book. In the backend you just add authors as many as you like and then assign that to a book. If your an admin you can edit authors details and if your an author you can edit your own profile area in your author resource but there is no login for an author to do this at all.
What I want to know is: Is it easy to create a devise user type like author from authors already added to the backend or will they need to be created all over again?
=== Edit below here ====
user.rb
class User < ActiveRecord::Base
belongs_to :role
def confirmation_required?
false
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_attached_file :avatar, styles: {
large: "600x450#",
medium: "250x250#",
small: "100x100#"
}, :default_url => "/images/:style/filler.png"
#validates_attachment_content_type :avatar, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
validates :avatar, :email, :username, :password, presence: true
end
role.rb
class Role < ActiveRecord::Base
has_many :users
end
author.rb
class Author < ActiveRecord::Base
has_many :books, dependent: :destroy
has_many :ideas, dependent: :destroy
accepts_nested_attributes_for :books
accepts_nested_attributes_for :ideas
validates_uniqueness_of :name
has_attached_file :avatar, :styles => { :large => "980x760", :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end
Thanks
Mark
You don't need to create separate model(Author) just to handle author logins.
Better approach will be using associations in this case.
#user_role.rb
class UserRole < ActiveRecord::Base
has_many :users
end
#user.rb
Class User < ActiveRecord::Base
belongs_to :user_role
end
Typical user model attributes will be
User(id: integer, email: string, name:string, user_role_id:integer)
user_role model attributes will be
UserRole(id: integer, role: string)
UserRole.create(role: 'Admin')
UserRole.create(role: 'Teacher')
UserRole.create(role: 'Author')
UserRole.create(role: 'Pupil')
then create your author( Let's assume the id for 'Author' role is 3)
user = User.create(name: 'abc', email: 'def#gmail.com', user_role_id: 3)
now, use this user object and go for devise login.
Now to list all the authors of our Application.
#user.rb
def self.all_authors
User.select('users.id, users.name, user_roles.role AS USER_ROLE')
.joins(:user_role).where(user_roles: {role: 'Author'})
end
Now to get all authors just give a call :
User.all_authors #this will list all the users of type 'author'
In my rails application I have an upvote system, it allows people to upvote a pin. Then when a user upvoted a pin I render a list of upvoted pins in the user profile. What I want to do know is to provide a list of the users who upvoted a specific pin.
app/controller/pins_controller.rb
def upvote
#pin = Pin.find(params[:id])
if #pin.votes.create(user_id: current_user.id)
flash[:notice] = "Thank you for upvoting! You can upvote a startup only once."
redirect_to(pins_path)
else
flash[:notice] = "You have already upvoted this!"
redirect_to(pins_path)
end
end
app/controller/users_controller.rb
def show
#user = User.find(params[:id])
#pins_for_user = []
#user.votes.each do |vote|
#pins_for_user << vote.pin
end
end
app/models/pin.rb
class Pin < ActiveRecord::Base
belongs_to :user
has_many :votes, dependent: :destroy
has_many :upvoted_users, through: :votes, source: :user
has_many :rewards, dependent: :destroy
has_many :rewarded_users, through: :rewards, source: :user
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
has_attached_file :logo, :styles => { :medium => "300x300>", :thumb => "100x100>" }
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 :pins
has_many :votes, dependent: :destroy
has_many :upvoted_pins, through: :votes, source: :pin
has_many :rewards, dependent: :destroy
has_many :rewarded_pins, through: :rewards, source: :pin
end
app/models/vote.rb
class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :pin, counter_cache: true
validates_uniqueness_of :pin_id, scope: :user_id
end
I was thinking of using #pin.upvoted_users to provide this list but I didn't succeeded to implement it correctly, any ideas?
My brain is getting tangled. I have users and they can have one plan and one subscription. I am using ryan bates example for subscription and have everything working except I don't know how to get the user_id into the subscription
here is my subscription controller.
class SubscriptionsController < ApplicationController
before_action :authenticate_user!
def new
plan = Plan.find(params[:plan_id])
#subscription = plan.subscriptions.build
end
def create
#subscription = Subscription.new(subscription_params)
if #subscription.save
redirect_to #subscription, :notice => "Thank you for subscribing!"
else
render :new
end
end
def show
#subscription = Subscription.find(params[:id])
end
private
def subscription_params
params.require(:subscription).permit(:plan_id, :email, :user_id)
end
end
here is my user model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :videos
has_many :votes
has_many :favorites
has_many :videos_with_votes, :through => :votes, :source => :video
has_many :videos_with_favorites, :through => :favorites, :source => :video
has_one :subscription
has_one :plan, :through => :subscription
has_attached_file :avatar, :styles => { :medium => "300x300#", :thumb => "80x80#" }
def voted?(video)
votes.exists?(video_id: video.id)
end
def favorited?(video)
favorites.exists?(video_id: video.id)
end
end
here is my plan model
class Plan < ActiveRecord::Base
has_many :subscriptions
has_many :users
end
here is my subscription model
class Subscription < ActiveRecord::Base
belongs_to :plan
belongs_to :user
validates_presence_of :plan_id
validates_presence_of :email
end
i am following this post for adding users as friends in ruby on rails
http://asciicasts.com/episodes/163-self-referential-association
I am able to add users as friends via rails console but not via the actual page...this is my controller code
class FriendshipsController < ApplicationController
def new
end
def create
#friendship = current_user.friendships.build(:friend_id => params[:friend_id])
if #friendship.save
flash[:notice] = "Added friend."
redirect_to phones_index_path
else
flash[:notice] = "Unable to add friend."
redirect_to phones_index_path
end
end
def show
end
end
Model:
User:
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
has_many :contacts
has_many :phones
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
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :user_id
# attr_accessible :title, :body
end
friends:
class Friendship < ActiveRecord::Base
attr_accessible :friend_id, :user_id
belongs_to :user
belongs_to :friend, :class_name => 'User'
end
view:
<h1>Phones#index</h1>
<center>Users in the system<center><br/>
<p><% #phones.each do |variable|%>
<% if #phn.email!= variable.email %>
<br/><%= variable.email %> <%= link_to 'Add as Friend' , friendships_path(:friend_id => #user), :method => :post %>
<%end%>
<%end%>
<p>friends</p>
<% for user in current_user.friends %>
<p><%= user.email %></p>
<%end%>
my view is working correctly .. if i add friends via console and commit it, it displays in the view..
where did i go wrong here??
I was able to correct it..had wrong code in my view file.. thanks a lot jvnill....had it not been for you, I would not have checked my view file... :)
changing friendships_path(:friend_id => #user)
to friendships_path(:friend_id => variable) did the trick
I have a Post model:
class Post < ActiveRecord::Base
attr_accessible :title, :content, :tag_names
belongs_to :user
has_many :taggings, :dependent => :destroy
has_many :tags, :through => :taggings
attr_writer :tag_names
after_save :assign_tags
def tag_names
#tag_names || tags.map(&:name).join(' ')
end
private
def assign_tags
if #tag_names
self.tags = #tag_names.split(" ").map do |name|
Tag.find_or_create_by_name(name)
end
end
end
end
a Tag model:
class Tag < ActiveRecord::Base
has_many :taggings, :dependent => :destroy
has_many :posts, :through => :taggings
has_many :subscriptions
has_many :subscribed_users, :source => :user, :through => :subscriptions
end
and an User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :avatar
has_many :posts, :dependent => :destroy
has_many :subscriptions
has_many :subscribed_tags, :source => :tag, :through => :subscriptions
end
posts and tags have a many-to-many relationship (the following is the model for the join table):
class Tagging < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end
users and tags have also a many-to-many relationship:
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :tag
end
Only posts with tags that the user has subscribed to should display:
def index
#title = "Posts"
#posts = current_user.subscribed_tags.map(&:posts).flatten.paginate(:page => params[:page], :per_page => 5)
Let say I create a tag for a post:
$ post.tags.create(:name => "food")
$ post.tags
=> [#<Tag id: 6, name: "food", created_at: "2012-03-02 10:03:59", updated_at: "2012-03-02 10:03:59"]
Now I have no idea how to subscribe the user to that tag.
I tried this:
$ user.subscribed_tags.create(:name => "food")
$ post.tags
=> [#<Tag id: 7, name: "food", created_at: "2012-03-02 10:04:38", updated_at: "2012-03-02 10:04:38"]
But as you can see it actually creates a new tag instead of adding the food tag with ID 6 to the user.subscribed_tags attribute.
Any suggestions to solve this issue?
You can append to the user's subscriped_tags, as you would do an array.
ex: user.subscribed_tags << Tag.find_by_name("food")