Add followable to budget investment model.
This commit is contained in:
committed by
Senén Rodero Rodríguez
parent
84dbef16a4
commit
bce28afe36
@@ -18,11 +18,6 @@ class FollowsController < ApplicationController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def find_followable
|
def find_followable
|
||||||
params.each do |name, value|
|
params[:followable_type].constantize.find(params[:followable_id])
|
||||||
if name =~ /(.+)_id$/
|
|
||||||
return $1.classify.constantize.find(value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,17 +8,21 @@ module FollowsHelper
|
|||||||
current_user && followed?(followable)
|
current_user && followed?(followable)
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow_entity_text(entity)
|
def follow_entity_text(followable)
|
||||||
|
entity = followable.class.name.gsub('::', '/').downcase
|
||||||
t('shared.follow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
t('shared.follow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfollow_entity_text(entity)
|
def unfollow_entity_text(followable)
|
||||||
|
entity = followable.class.name.gsub('::', '/').downcase
|
||||||
t('shared.unfollow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
t('shared.unfollow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
||||||
end
|
end
|
||||||
|
|
||||||
def entity_name(followable)
|
def entity_name(followable)
|
||||||
followable.class.name.downcase
|
entity_name = followable.class.name.split('::').last
|
||||||
|
entity_name.downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def followed?(followable)
|
def followed?(followable)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class Budget
|
|||||||
include Taggable
|
include Taggable
|
||||||
include Searchable
|
include Searchable
|
||||||
include Reclassification
|
include Reclassification
|
||||||
|
include Followable
|
||||||
|
|
||||||
acts_as_votable
|
acts_as_votable
|
||||||
acts_as_paranoid column: :hidden_at
|
acts_as_paranoid column: :hidden_at
|
||||||
|
|||||||
@@ -13,17 +13,6 @@ class Follow < ActiveRecord::Base
|
|||||||
followable_id: followable.id)
|
followable_id: followable.id)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
# def self.follow(user, followable)
|
|
||||||
# return false if interested?(user, followable)
|
|
||||||
# create(user: user, followable: followable)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# def self.unfollow(user, followable)
|
|
||||||
# interests = by_user_and_followable(user, followable)
|
|
||||||
# return false if interests.empty?
|
|
||||||
# interests.destroy_all
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
def self.followed?(user, followable)
|
def self.followed?(user, followable)
|
||||||
return false unless user
|
return false unless user
|
||||||
!! by_user_and_followable(user, followable).try(:first)
|
!! by_user_and_followable(user, followable).try(:first)
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
<%= l investment.created_at.to_date %>
|
<%= l investment.created_at.to_date %>
|
||||||
<span class="bullet"> • </span>
|
<span class="bullet"> • </span>
|
||||||
<%= investment.heading.name %>
|
<%= investment.heading.name %>
|
||||||
|
<span class="bullet"> • </span>
|
||||||
|
<span class="js-follow">
|
||||||
|
<%= render 'follows/followable_button', followable: investment %>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
|
<% entity = entity_name(followable) %>
|
||||||
<span class="followable-content">
|
<span class="followable-content">
|
||||||
<% if show_follow_action? followable %>
|
<% if show_follow_action? followable %>
|
||||||
<a id="follow-expand-<%= entity_name(followable) %>-<%= followable.id %>" data-toggle="follow-drop-<%= entity_name(followable) %>-<%= followable.id %>" title="<%= follow_entity_text(entity_name(followable)) %>">
|
<a id="follow-expand-<%= entity %>-<%= followable.id %>" data-toggle="follow-drop-<%= entity %>-<%= followable.id %>" title="<%= follow_entity_text(followable) %>">
|
||||||
<%= t('shared.follow') %>
|
<%= t('shared.follow') %>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-pane" id="follow-drop-<%= entity_name(followable) %>-<%= followable.id %>" data-dropdown data-auto-focus="true">
|
<div class="dropdown-pane" id="follow-drop-<%= entity %>-<%= followable.id %>" data-dropdown data-auto-focus="true">
|
||||||
<%= link_to follow_entity_text(entity_name(followable)), follows_path("#{entity_name(followable)}_id": followable.id), method: :post, remote: true, id: "follow-#{entity_name(followable)}-#{ followable.id }" %>
|
<%= link_to follow_entity_text(followable), follows_path(followable_id: followable.id, followable_type: followable.class.name), method: :post, remote: true, id: "follow-#{entity}-#{ followable.id }" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if show_unfollow_action? followable %>
|
<% if show_unfollow_action? followable %>
|
||||||
<% follow = followable.follows.where(user: current_user).first %>
|
<% follow = followable.follows.where(user: current_user).first %>
|
||||||
<a id="unfollow-expand-<%= entity_name(followable) %>-<%= followable.id %>" data-toggle="unfollow-drop-<%= entity_name(followable) %>-<%= followable.id %>" title="<%= unfollow_entity_text(entity_name(followable)) %>">
|
<a id="unfollow-expand-<%= entity %>-<%= followable.id %>" data-toggle="unfollow-drop-<%= entity %>-<%= followable.id %>" title="<%= unfollow_entity_text(followable) %>">
|
||||||
<%= t('shared.unfollow') %>
|
<%= t('shared.unfollow') %>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-pane" id="unfollow-drop-<%= entity_name(followable) %>-<%= followable.id %>" data-dropdown data-auto-focus="true">
|
<div class="dropdown-pane" id="unfollow-drop-<%= entity %>-<%= followable.id %>" data-dropdown data-auto-focus="true">
|
||||||
<%= link_to unfollow_entity_text(entity_name(followable)), follow_path(follow), method: :delete, remote: true, id: "unfollow-#{entity_name(followable)}-#{ followable.id }" %>
|
<%= link_to unfollow_entity_text(followable), follow_path(follow), method: :delete, remote: true, id: "unfollow-#{entity}-#{ followable.id }" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -355,6 +355,10 @@ FactoryGirl.define do
|
|||||||
trait :followed_proposal do
|
trait :followed_proposal do
|
||||||
association :followable, factory: :proposal
|
association :followable, factory: :proposal
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :followed_investment do
|
||||||
|
association :followable, factory: :budget_investment
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :comment do
|
factory :comment do
|
||||||
|
|||||||
@@ -420,6 +420,74 @@ feature 'Budget Investments' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature "Follows" do
|
||||||
|
|
||||||
|
scenario "Should not show follow button when there is no logged user" do
|
||||||
|
investment = create(:budget_investment)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget_id: investment.budget.id, id: investment.id)
|
||||||
|
|
||||||
|
within "#budget_investment_#{investment.id}" do
|
||||||
|
expect(page).not_to have_link("Follow citizen proposal")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Following", :js do
|
||||||
|
user = create(:user)
|
||||||
|
investment = create(:budget_investment)
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget_id: investment.budget.id, id: investment.id)
|
||||||
|
within "#budget_investment_#{investment.id}" do
|
||||||
|
page.find("#follow-expand-investment-#{investment.id}").click
|
||||||
|
page.find("#follow-investment-#{investment.id}").click
|
||||||
|
|
||||||
|
expect(page).to have_css("#unfollow-expand-investment-#{investment.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(Follow.followed?(user, investment)).to be
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Show unfollow button when user already follow this investment" do
|
||||||
|
user = create(:user)
|
||||||
|
investment = create(:budget_investment)
|
||||||
|
follow = create(:follow, :followed_investment, user: user, followable: investment)
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget_id: investment.budget.id, id: investment.id)
|
||||||
|
|
||||||
|
expect(page).to have_link("Unfollow investment")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Unfollowing", :js do
|
||||||
|
user = create(:user)
|
||||||
|
investment = create(:budget_investment)
|
||||||
|
follow = create(:follow, :followed_investment, user: user, followable: investment)
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget_id: investment.budget.id, id: investment.id)
|
||||||
|
within "#budget_investment_#{investment.id}" do
|
||||||
|
page.find("#unfollow-expand-investment-#{investment.id}").click
|
||||||
|
page.find("#unfollow-investment-#{investment.id}").click
|
||||||
|
|
||||||
|
expect(page).to have_css("#follow-expand-investment-#{investment.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(Follow.followed?(user, investment)).not_to be
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Show follow button when user is not following this investment" do
|
||||||
|
user = create(:user)
|
||||||
|
investment = create(:budget_investment)
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget_id: investment.budget.id, id: investment.id)
|
||||||
|
|
||||||
|
expect(page).to have_link("Follow investment")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
context "Destroy" do
|
context "Destroy" do
|
||||||
|
|
||||||
scenario "Admin cannot destroy budget investments" do
|
scenario "Admin cannot destroy budget investments" do
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ describe Follow do
|
|||||||
|
|
||||||
let(:follow) { build(:follow, :followed_proposal) }
|
let(:follow) { build(:follow, :followed_proposal) }
|
||||||
|
|
||||||
# it_behaves_like "has_public_author"
|
|
||||||
|
|
||||||
it "should be valid" do
|
it "should be valid" do
|
||||||
expect(follow).to be_valid
|
expect(follow).to be_valid
|
||||||
end
|
end
|
||||||
@@ -25,110 +23,4 @@ describe Follow do
|
|||||||
expect(follow).to_not be_valid
|
expect(follow).to_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# describe "proposal" do
|
|
||||||
#
|
|
||||||
# let(:proposal) { create(:proposal) }
|
|
||||||
#
|
|
||||||
# describe 'create' do
|
|
||||||
#
|
|
||||||
# it 'creates a interest when there is none' do
|
|
||||||
# expect { described_class.follow(user, proposal) }.to change{ Interest.count }.by(1)
|
|
||||||
# expect(Interest.last.user).to eq(user)
|
|
||||||
# expect(Interest.last.interestable).to eq(proposal)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'does nothing if the interest already exists' do
|
|
||||||
# described_class.follow(user, proposal)
|
|
||||||
# expect(described_class.follow(user, proposal)).to eq(false)
|
|
||||||
# expect(Interest.by_user_and_interestable(user, proposal).count).to eq(1)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'increases the interest count' do
|
|
||||||
# expect { described_class.follow(user, proposal) }.to change{ proposal.reload.interests_count }.by(1)
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe 'destroy' do
|
|
||||||
# it 'raises an error if the interest does not exist' do
|
|
||||||
# expect(described_class.unfollow(user, proposal)).to eq(false)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe 'when the interest already exists' do
|
|
||||||
# before(:each) { described_class.follow(user, proposal) }
|
|
||||||
#
|
|
||||||
# it 'removes an existing interest' do
|
|
||||||
# expect { described_class.unfollow(user, proposal) }.to change{ Interest.count }.by(-1)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'decreases the interest count' do
|
|
||||||
# expect { described_class.unfollow(user, proposal) }.to change{ proposal.reload.interests_count }.by(-1)
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe '.interested?' do
|
|
||||||
# it 'returns false when the user has not flagged the proposal' do
|
|
||||||
# expect(described_class.interested?(user, proposal)).to_not be
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'returns true when the user has interested the proposal' do
|
|
||||||
# described_class.follow(user, proposal)
|
|
||||||
# expect(described_class.interested?(user, proposal)).to be
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe "debate" do
|
|
||||||
#
|
|
||||||
# let(:debate) { create(:debate) }
|
|
||||||
#
|
|
||||||
# describe 'create' do
|
|
||||||
#
|
|
||||||
# it 'creates a interest when there is none' do
|
|
||||||
# expect { described_class.follow(user, debate) }.to change{ Interest.count }.by(1)
|
|
||||||
# expect(Interest.last.user).to eq(user)
|
|
||||||
# expect(Interest.last.interestable).to eq(debate)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'does nothing if the interest already exists' do
|
|
||||||
# described_class.follow(user, debate)
|
|
||||||
# expect(described_class.follow(user, debate)).to eq(false)
|
|
||||||
# expect(Interest.by_user_and_interestable(user, debate).count).to eq(1)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'increases the interest count' do
|
|
||||||
# expect { described_class.follow(user, debate) }.to change{ debate.reload.interests_count }.by(1)
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe 'destroy' do
|
|
||||||
# it 'raises an error if the interest does not exist' do
|
|
||||||
# expect(described_class.unfollow(user, debate)).to eq(false)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe 'when the interest already exists' do
|
|
||||||
# before(:each) { described_class.follow(user, debate) }
|
|
||||||
#
|
|
||||||
# it 'removes an existing interest' do
|
|
||||||
# expect { described_class.unfollow(user, debate) }.to change{ Interest.count }.by(-1)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'decreases the interest count' do
|
|
||||||
# expect { described_class.unfollow(user, debate) }.to change{ debate.reload.interests_count }.by(-1)
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# describe '.interested?' do
|
|
||||||
# it 'returns false when the user has not flagged the debate' do
|
|
||||||
# expect(described_class.interested?(user, debate)).to_not be
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'returns true when the user has interested the debate' do
|
|
||||||
# described_class.follow(user, debate)
|
|
||||||
# expect(described_class.interested?(user, debate)).to be
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user