Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

ruby on rails - How to use private submit to hide from profile?

When a User submits via private how can we hide the submitted info from the feed and from other users being able to see it on his public profile?

<%= button_tag(type: 'submit', class: "btn")  do %>
  ...
<%= button_tag(type: 'submit', class: "btn", id: "2", name: 'private')  do %>
  ...

We put the below in the controller, but since the private button will be in a lot of different _forms, do I have to put it in each controller or can we put it in the application controller?

if params[:private]
  # the private action / What do we need to put here?
else
  # normal submit / and here?

I followed this railcast episode nearly to the T to build the activity feed: http://railscasts.com/episodes/406-public-activity.

Here 's the code for the public profile:

users_controller.rb

def show
   @user = User.find(params[:id])
   @habits = @user.habits
   @valuations = @user.valuations
   @accomplished_goals = @user.goals.accomplished
   @unaccomplished_goals = @user.goals.unaccomplished
   @averaged_quantifieds = @user.quantifieds.averaged
   @instance_quantifieds = @user.quantifieds.instance
end

show.html.erb

<% if @user.habits.any? %>
  <h2>Habits</h2>
  <h4>Challenges</h4>
  <%= render partial: 'habits', locals: {habits: @habits} %>
<% end %>

<% if @user.valuations.any? %>
  <h2>Values</h2>
  <%= render @valuations %>
<% end %>

<% if @user.goals.any? %>
  <h2>Goals</h2>
  <h4> Current</h4>
  <%= render @unaccomplished_goals %>
<% end %>

<% if @user.goals.any? %>
  <h4>Accomplished</h4>
  <%= render @accomplished_goals %>
<% end %>

<% if @user.quantifieds.any? %>
  <h2>Stats</h2>
  <h4>Averaged</h4>
  <%= render partial: 'averaged', locals: {habits: @averaged_quantifieds} %>
<% end %>

<% if @user.quantifieds.any? %>
  <h4>Instance</h4>
  <%= render partial: 'instance', locals: {habits: @instance_quantifieds} %>
<% end %>

As Requested :)

User Model

class User < ActiveRecord::Base
  has_many :authentications
  has_many :habits, dependent: :destroy
  has_many :levels
  has_many :valuations, dependent: :destroy
  has_many :comments, as: :commentable
  has_many :goals, dependent: :destroy
  has_many :quantifieds, dependent: :destroy
  has_many :results, through: :quantifieds
  accepts_nested_attributes_for :quantifieds, :reject_if => :all_blank, :allow_destroy => true
  accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true
  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  has_many :passive_relationships, class_name:  "Relationship",
                                   foreign_key: "followed_id",
                                   dependent:   :destroy
  has_many :following, through: :active_relationships,  source: :followed
  has_many :followers, through: :passive_relationships, source: :follower
  attr_accessor :remember_token, :activation_token, :reset_token
  before_save   :downcase_email
  before_create :create_activation_digest
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /A[w+-.]+@[a-zd-.]+.[a-z]+z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }, unless: -> { from_omniauth? }
  has_secure_password
  validates :password, length: { minimum: 6 }


  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      user.name = auth.info.name
      user.oauth_token = auth.credentials.token
      user.oauth_expires_at = Time.at(auth.credentials.expires_at)
      user.password = (0...8).map { (65 + rand(26)).chr }.join
      user.email = (0...8).map { (65 + rand(26)).chr }.join+"@mailinator.com"
      user.save!
    end
  end

  # Returns the hash digest of the given string.
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

  # Returns a random token.
  def User.new_token
    SecureRandom.urlsafe_base64
  end

  # Remembers a user in the database for use in persistent sessions.
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end

  # Forgets a user. NOT SURE IF I REMOVE
  def forget
    update_attribute(:remember_digest, nil)
  end

  # Returns true if the given token matches the digest.
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

  # Activates an account.
  def activate
    update_attribute(:activated,    true)
    update_attribute(:activated_at, Time.zone.now)
  end

  # Sends activation email.
  def send_activation_email
    UserMailer.account_activation(self).deliver_now
  end

  def create_reset_digest
    self.reset_token = User.new_token
    update_attribute(:reset_digest,  User.digest(reset_token))
    update_attribute(:reset_sent_at, Time.zone.now)
  end

  # Sends password reset email.
  def send_password_reset_email
    UserMailer.password_reset(self).deliver_now
  end

   # Returns true if a password reset has expired.
  def password_reset_expired?
    reset_sent_at < 2.hours.ago
  end

  def good_results_count
    results.good_count
  end

  # Returns status feed.
  def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE  follower_id = :user_id"
    Habit.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
    Valuation.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
    Goal.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
    Quantified.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
  end

  # Follows a user.
  def follow(other_user)
    active_relationships.create(followed_id: other_user.id)
  end

  # Unfollows a user.
  def unfollow(other_user)
    active_relationships.find_by(followed_id: other_user.id).destroy
  end

  # Returns true if the current user is following the other user.
  def following?(other_user)
    following.include?(other_user)
  end

private 

    def from_omniauth? 
    provider && uid 
    end

      # Converts email to all lower-case.
    def downcase_email 
      self.email = email.downcase unless from_omniauth? 
    end

    # Creates and assigns the activation token and digest.
    def create_activation_digest
      self.activation_token  = User.new_token
      self.activation_digest = User.digest(activation_token)
    end
end
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Add a field 'private' to the User model with its default value 'false'. All normal user informations will be flagged as 'public' (because the private field has the value false) Only if params[:private], then the value of the private field will be set to 'true'.

Next you can add a method to the user model which will grab only the data of user with the private = false flag (for public views).

EDIT:

Displaying public or private:

Add a field 'private' to each of your related models which possibly could be marked as private. Don't forget to add this in your migrations. Set the private's default to false.

Include in valuation & user migration/schema

t.boolean :private, default: false

valuation.rb

def public?
  private == true ? false : true
end

user.rb

# gets public valutations or nil, if there's no public valutation
def public_valuations
    valuations.find(&:public?)
end

Do this in the same way for each of your wanted relations. It enables you to get the public informations via

@valuations = @user.public_valuations

Your current show action displays now all additional user's informations - public and private - which are should be only displayed if the current_user = @user.

At last you have to insert a condition in your show action:

def show
  @user = User.find(params[:id])
  if current_user == @user
    @habits = @user.habits
    @valuations = @user.valuations
    @accomplished_goals = @user.goals.accomplished
    @unaccomplished_goals = @user.goals.unaccomplished
    @averaged_quantifieds = @user.quantifieds.averaged
    @instance_quantifieds = @user.quantifieds.instance
  else
    @valuations = @user.public_valuations
  end
end

That solution depends on current_user, i.e. you must have a method which returns the object of the currently logged_in user (maybe in a session). Michael Hartl wrote an awesome tutorial about user authentication. *RubyonRailsBeginner used Hartl Tutorial for this :)

Creating public or private records

Since you had set the private's default to false, you can use your existing code to create public entries.

For private entries you must set the corresponding attribute in your user_params to true.

EDIT with params.require:

I set the [:private] in the else clause explicit to false, so that a user might set his private attributes to public, if wanted.

def user_params
  if params[:private] = true
    params.require(:user).permit(:name, :email, :password, :private, :password_confirmation, valuations_attributes: [:name, :tag_list, :private])
  else
    params[:user][:valuations][:private] = false
    params.require(:user).permit(:name, :email, :password, :password_confirmation, valuations_attributes: [:name, :tag_list])
  end
end

The Rails Api gives you some hints about strong parameters with nested attributes.

Hope that helps!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...