I am using a ruby gem called acts_as_follower
My code:
user.rb
class User < ApplicationRecord
acts_as_followable
acts_as_follower
end
users_controller.rb
def follow
#user = User.find(params[:id])
current_user.follow(#user)
redirect_to root_path
end
def unfollow
#user = User.find(params[:id])
current_user.stop_following(#user)
redirect_to root_path
end
followers.html.erb
<% #user.followers.each do |user| %>
<div class="panel panel-default col-md-offset-3 col-md-6">
<br>
<div class="panel panel-heading">
<%= avatar_for(user, size: 50) %>
<h1> <%=link_to user.name, user %></h1>
</div>
</div>
routes.rb
#followers
resources :users do
member do
get :follow
get :unfollow
end
end
How to display the users I follow?
How to display the users I follow?
I believe the method you want is all_following
user.all_following
Returns an array of every followed object for the user, this can be a
collection of different object types, eg: User, Book
So, the below should work
#user.all_following
Related
I am working on my first Rails project and I am running into a persistent issue. I suspect it has something to do with the routing, however, I can't seem to find anything about it online.
I assume it a rather simple fix, so please take a look and let me know if you can help.
TL;DR
What I was trying to achieve
Account detail Cards display Name, Phone number, and a note.
A delete and edit button would allow users to delete or edit.
What is happening:
Edit and Delete buttons return a weird param.
see image
Image of error, Showing Rails getting a different ID
Controller
class AccountdetailsController < ApplicationController
def index
#accountdetail = Accountdetail.all
end
#I can't find the ID to show the relevent card.
def show
#accountdetail = Accountdetail.find(params[:id])
if #accountdetail.nil?
redirect_to accountdetail_path
end
end
def new
#accountdetail = Accountdetail.new
end
def edit
#accountdetail = Accountdetail.find(params[:id])
end
def create
#accountdetail = Accountdetail.new(accountdetail_params)
if #accountdetail.save
redirect_to #accountdetail
else
render 'new'
end
end
#it affects this
def update
#accountdetail = Accountdetail.find(params[:id])
if #accountdetail.update(accountdetail_params)
redirect_to accountdetail
else
render 'edit'
end
end
#and this
def destroy
#accountdetail = Accountdetail.find(params[:id])
#accountdetail.destroy
redirect_to accountdetail_path
end
private def accountdetail_params
params.require(:accountdetail).permit(:first_name, :last_name, :phone, :notes, :id)
end
end
Index.HTML.ERB
<div class="ui card">
<div class="content">
<a class="header"><%= account.first_name %> <%= account.last_name %> </a>
<div class="meta">
<span class="date"><%= account.phone %></span>
<strong><p><%= account.notes %></p></strong> <br>
<%= link_to "edit", edit_accountdetail_path(#accountdetail) %>
<%= link_to 'Inspect', accountdetail_path(#accountdetail) %>
</div>
</div>
</div>
<% end %>
Routes
Rails.application.routes.draw do
get 'welcome/index'
resources :articles do
resources :comments
end
resources :accountdetails
root 'welcome#index'
end
In you index.html.erb replace following
<%= link_to "edit", edit_accountdetail_path(#accountdetail) %>
<%= link_to 'Inspect', accountdetail_path(#accountdetail) %>
with
<%= link_to "edit", edit_accountdetail_path(account) %>
<%= link_to 'Inspect', accountdetail_path(account) %>
#accountdetail was providing you all the records of account, as it was firing select query in controller. But here we need only one instance, so account.
Hope this helps.
I am really new at rails so please forgive me if i can't see it.
I am trying to edit the permissions on each individual user and i am getting this error in form_for:
undefined method `to_key' for #<User::ActiveRecord_Relation:0x007f1bf8c2fd60>
From what i have seen on other questions on stackoverflow, this usually happens when you try to call a collection in a form but this is not the case?
view:
<div class="n-container">
<tr-form data-riot riot-tag="tr-form">
<%= form_for(#user) do |f| %>
<section>
<div class="w-container">
<h1>User permissions</h1>
<% #permissions.each do |permission| %>
<%= check_box_tag 'permission_ids[]', permission.id %>
<div>
<%= permission.description %>
</div>
<% end %>
</div>
</section>
<section>
<div class="f-controls align-right">
<%= f.submit class: "btn fill blue", value: "Submit" %>
</div>
</section>
<% end %>
</tr-form>
</div>
users_controller:
class UsersController < ApplicationController
def user_params
params.require('user').permit(
permissions: []
)
end
def permissions
#user = User.where(id: params[:user_id])
#permissions = Permission.all
end
end
routes:
resources :users do
get 'permissions'
post 'permissions'
end
Thank you in advance!
One should use ActiveRecord::FinderMethods#find, not where, to receive a single instance:
def permissions
# WRONG: where returns a relation
# #user = User.where(id: params[:user_id])
#user = User.find(params[:user_id])
#permissions = Permission.all
end
It worth to mention, that find raise a RecordNotFound exception on fail, hence you probably want to rescue from it:
def permissions
#user = User.find(params[:user_id])
#permissions = Permission.all
rescue RecordNotFound => rnf
# Log or just skip
end
where might be [ab]used here as well, but in such a case you need to explicitly say that you need the only user:
#user = User.where(id: params[:user_id]).first
I am getting the following error on my Rails 4.2 application. I'm trying to setup subscriptions with Stripe. A subscription belongs to a business and has_one plan.
On my view I pass the params in the URL:
http://localhost:3000/subscriptions/new?plan_id=2&business_id=1001
After I submit the form I get the error below and my code follows. Forgive me if this is a beginner question.
Subscriptions Controller
class SubscriptionsController < ApplicationController
before_action :set_subscription, only: [:show, :edit, :update, :destroy]
# GET /subscriptions
def index
#subscriptions = Subscription.all
end
# GET /subscriptions/1
def show
end
# GET /subscriptions/new
def new
#subscription = Subscription.new
#plan = Plan.find_by id: params["plan_id"]
#business = Business.find_by id: params["business_id"]
end
# POST /subscriptions
def create
#subscription = Subscription.new subscription_params.merge(email: stripe_params["stripeEmail"],
card_token: stripe_params["stripeToken"])
raise "Please, check subscription errors" unless #subscription.valid?
#subscription.process_payment
#subscription.save
redirect_to #subscription, notice: 'Subscription was successfully created.'
rescue => e
flash[:error] = e.message
render :new
end
private
def stripe_params
params.permit :stripeEmail, :stripeToken
end
# Use callbacks to share common setup or constraints between actions.
def set_subscription
#subscription = Subscription.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def subscription_params
params.require(:subscription).permit(:plan_id, :business_id)
end
end
Subscription Model
class Subscription < ActiveRecord::Base
belongs_to :business
has_one :plan
def process_payment
customer = Stripe::Customer.create email: email,
card: card_token
Stripe::Charge.create customer: customer.id,
amount: plan.price * 100,
description: plan.name,
currency: 'usd'
end
end
Subscription View (new.html.erb)
<%= form_for #subscription do |f| %>
<% if #subscription.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#subscription.errors.count, "error") %>
prohibited this subscription from being saved:
</h2>
<ul>
<% #subscription.errors.full_messages.each do |message| %>
<li>
<%= message %>
</li>
<% end %>
</ul>
</div>
<% end %>
<h1><%= #business.name %></h1>
<div class="field">
<%= f.hidden_field :plan_id, value: #plan.id %>
</div>
<div class="field">
<%= f.hidden_field :business_id, value: #business.id %>
</div>
<div class="actions">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.application.secrets.stripe_publishable_key %>"
data-image="/img/documentation/checkout/marketplace.png"
data-name="Business Name"
data-description="<%= #plan.name %>"
data-amount="<%= #plan.price*100 %>">
</script>
</div>
<% end %>
Plan Model
class Plan < ActiveRecord::Base
belongs_to :subscription
end
Calling render only loads the view for an action, it doesn't run any of the logic in the method behind the action, which is why there is no #plan available when you render :new from the create action.
I figured out the issue was with my association between Plans and Subscriptions. I had Plans belongs_to Subscription when I should have had it the other way around.
class Subscription < ActiveRecord::Base
belongs_to :business
belongs_to :plan
...
For my rails application, I am trying to create a random permalink for my users so that it is not localhost:3000/users/:id, but rather, it is localhost:3000/users/permalink.
I have followed the post made here:
how to make ID a random 8 digit alphanumeric in rails?
Following the post, I have been able to create the random permalink column and pages for my users, but have not been able to get the sub-pages to work. For my users, I currently have sub-pages: Followers, etc.
Question: The pages are currently routed to localhost:3000/users/:id/followers, etc. But does somebody know how to fix routes.rb so that I can also route these pages to localhost:3000/users/permalink/followers, etc.
routes.rb
match 'users/:permalink' => 'users#show', :as => "show_user"
resources :users do
member do
get :followers
end
end
user.rb
attr_accessible :permalink
before_create :make_it_permalink
def make_it_permalink
self.permalink = SecureRandom.base64(8)
end
users_controller.rb
def show
#user = User.find_by_permalink(params[:permalink])
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.page(params[:page]).per_page(5)
render 'show_follow'
end
users/_header.html.erb
<%= render 'users/followerstats' %>
users/_followerstats.html.erb
<a href = "<%= followers_user_path(#user) %>">
My Followers ( <%= #user.followers.count %> )
</a>
users/show_follow.html.erb
<div class = "container">
<%= render 'header' %>
<% provide(:title, #title) %>
<div class="row">
<div class="span12">
<h4><%= #title %></h4>
<% if #users.any? %>
<ul class="users">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
/div>
</div>
I got it to work by adding the following:
routes.rb
match 'users/:permalink/followers' => 'users#followers', :as => "followers_user"
users_controller.rb
def followers
#title = "Followers"
#user = User.find_by_permalink(params[:permalink])
#users = #user.followers.page(params[:page]).per_page(5)
render 'show_follow'
end
users/_followerstats.html.erb
<a href = "<%= followers_user_path(#user.permalink) %>">
My Followers ( <%= #user.followers.count %> )
</a>
*****UPDATE:**
Based on suggestion of #Benjamin Sinclaire and post here (Best way to create unique token in Rails?), I fixed up the make_it_permalink in user.rb:
def make_it_permalink
loop do
# this can create permalink with random 8 digit alphanumeric
self.permalink = SecureRandom.urlsafe_base64(8)
break self.permalink unless User.where(permalink: self.permalink).exists?
end
end
Ok you found it while I was writing :)
Also be careful with your make_it_permalink function. There is a tiny chance that 2 users get the same permalink with your code. I suggest you to change it to:
def make_it_permalink
begin
self.permalink = SecureRandom.base64(8)
end while User.exists?(:permalink => self.permalink)
end
First question, please be gentle :)
I am having trouble creating an index view for a client model that belongs_to the user model with a has_many association.
The error message:
'nil' is not an ActiveModel-compatible object that returns a valid partial path.
Specifically the error refers to the partial on line #11:
/views/clients/index.html
<% provide(:title, current_user.name) %>
<div class="row">
<aside class="span4">
<section>
<h1>Your clients</h1>
</section>
</aside>
<div class="span8">
<% if current_user.clients.any? %>
<ol class="clients">
<%= render #clients %>
</ol>
<%= will_paginate %>
<% end %>
</div>
</div>
/clients/_client.html.erb
<li>
<span class="client-name"><%= client.name %></span>
<span class="client-info">
Extra client info to come.
</span>
</li>
Clients controller:
class ClientsController < ApplicationController
belongs_to :user
def index
#clients = current_user.clients.paginate(page: params[:page])
end
EDIT:
Users controller if it helps...
class UsersController < ApplicationController
before_filter :authenticate_user!
def show
if current_user.admin?
#user = User.find(params[:id])
else
#user = current_user
end
end
def index
if current_user.admin?
#users = User.paginate(page: params[:page])
else
redirect_to root_path
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_path
end
end
As you can probably tell I am new to rails, but have searched to ensure this hasn't been covered already.
Should you be passing :page => params[:page] to paginate instead?
I declared belongs_to in the clients controller and the model instead of just the model. And didn't notice for two days.