I'm facing to a stupid problem. I have created a collection select which is creating elements into a join table "staffs_task" to reference an association between the model staff and task.
And now I would like two things: (1) a button delete this association (2) and a little bit of code for my model staffs_task to avoid duplication, so with the task_id and staff_id. And last info, task is a model built by ranch
my code:
(the collection in new_task)
<%= select_tag "staffs_task", options_from_collection_for_select(#staffs, 'id', 'name') , :multiple => true %>
(task_controller)
skip_before_action :configure_sign_up_params
before_action :set_ranch
before_action :set_task, except: [:create]
def create
#task = #ranch.tasks.create(task_params)
#staffs = Staff.where(:id => params[:staffs_task])
#task.staffs << #staffs
if #task.save
#task.update(done: false)
#task.update(star: false)
flash[:success] = "The task was created "
else
flash[:success] = "The task was not created "
end
redirect_to #ranch
end
private
def task_params
params.require(:task).permit(:content, :deadline, :row_order, :date, :assigned_to)
end
def set_ranch
#ranch = Ranch.find(params[:ranch_id])
end
def set_task
#task = #ranch.tasks.find(params[:id])
end
So if you have any idea about one of this two things, your help would be welcome
Thanks in advance !!
Lets say you have the following many to many setup with a join model:
class Staff
has_many :assignments
has_many :tasks, through: :assignments
end
class Task
has_many :assignments
has_many :staff, through: :assignments
end
class Assignment
belongs_to :task
belongs_to :staff
end
Note that the plural of staff is staff - unless you are talking about the sticks carried by wizards.
ActiveRecord creates "magical" _ids setters for all has_many relationships. When used with a has_many through: relationship rails is smart enough to just remove the rows from the join table.
You can use this with the collection_select and collection_checkboxes methods:
<%= form_for([#task.ranch, #task]) do |f| %>
<%= f.collection_select(:staff_ids, Staff.all, :id, :name, multiple: true) %>
<% end %>
You would then set your controller up like so:
def create
#task = #ranch.tasks.new(task_params) do |t|
# this should really be done by setting default values
# for the DB columns
t.done = false
t.star = false
end
if #task.save
redirect_to #ranch, success: "The task was created"
else
render :new, error: "The task was not created"
end
end
private
def task_params
params.require(:task)
.permit(:content, :deadline, :row_order, :date, :assigned_to, staff_ids: [])
end
staff_ids: [] will allow an array of scalar values. Also not that .new and .create are not the same thing! You where saving the record 4 times if it was valid so the user has to wait for 4 expensive write queries when one will do.
Related
I need help implement a route to fetch all blog posts by author_ids.
The post that we're fetching needs to have at least one of the authors specified in the passed in author_ids parameters. I've created a helper function to help me fetch all blog posts by their ID, Post.get_posts_by_user_id
I also need to sort the posts by query parameters given. Also, I need to delete any duplicated posts as efficiently as possible.
I'm stumped here because of the way author_ids is being given. (I'm extremely new to Ruby)
This is what we should get returned from the route: "posts": [{"id": 1, "likes": 960, "popularity": 0.13, "reads": 50361, "tags": ["tech", "health"], text": "Some text here."}, ... ]
Query parameters expected to be given to this route
Update:
After creating the index method, it seems that it is only getting one post rather than getting all posts that are associated with the passed in authorIds.
def index
posts = current_user
.posts
.where(id: params[:authorIds].split(','))
.order(sort_column => sort_direction)
if posts
render json: { post: posts }, status: :ok
else
render json: {error: posts.errors}, status: :unprocessable_entity
end
end
Test cases
Update 2:
Post Model:
class Post < ApplicationRecord
# Associations
has_many :user_posts
has_many :users, through: :user_posts, dependent: :destroy
# Validations
validates :text, presence: true, length: { minimum: 3 }
validates :popularity, inclusion: { in: 0.0..1.0 }
def tags
if super
super.split(",")
end
end
def tags=(value)
if value.kind_of? Array
super value.join(",")
else
super value
end
end
def self.get_posts_by_user_id(user_id)
Post.joins(:user_posts).where(user_posts: { user_id: user_id })
end
end
User Model:
class User < ApplicationRecord
has_secure_password
# Associations
has_many :user_posts
has_many :posts, through: :user_posts, dependent: :destroy
# Validations
validates :username, :password, presence: true
validates :password, length: { minimum: 6 }
validates :username, uniqueness: true
end
User_post Model:
class UserPost < ApplicationRecord
belongs_to :user
belongs_to :post
end
I would do it like below.
def index
author_ids_array = params[:ids].to_s.split(',')
Post
.get_posts_by_user_id(author_ids_array)
.order(sort_column => sort_direction)
end
private
def sort_column
allow_list = %w[id reads likes popularity]
params[:sortBy].presence_in(allow_list) || allow_list.first
end
def sort_direction
allow_list = %w[asc desc]
params[:direction].presence_in(allow_list) || allow_list.first
end
I am new to web development (I have been coding for about 6/7 months now) in hopes of building my own app. I have been reading and working of the Ruby on Rails tutorial by Michael Hartl. I am on the chapter 9 section deleting users and am stuck. Everything works for the most part except that the user link. It just doesn't show on the display page. The users and their avatars fine. I just can't figure out a way to get the user delete link to show. Below is the code for the user model, the user controller, the session controller where the code current user lives and the view.
Also, when ever i take out the if statement from the user partial the delete link shows. I am not sure whats wrong since I already defined admin, and the current_user.
I would be entirely grateful for any kind of guidance. My project is also on github if the information below isn't sufficient enough
https://github.com/krischery2150/Try2150-master/tree/updating-users
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def new
#user = User.new
end
def show
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
if #user.save
log_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile Updated"
redirect_to #user
else
render 'edit'
end
end
def index
#users = User.paginate(page: params[:page])
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "Your profile was deleted"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:username, :email, :password,
:password_confirmation, :user_about_me,
:birthday, :avatar, :gender)
end
##Before filters method
# Confirms that a given user is logged in. Only when these conditions are met the user will
# be able to update or edit their page
def logged_in_user
unless logged_in?
store_location
flash[:danger]= "Please Log In"
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
.
class User < ActiveRecord::Base
before_save {self.email = email.downcase}
attr_accessor :remember_token
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "50x50>" }, default_url: "/images/:thumb/missing.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
# this before_save is a callback method. What it does is before it saves the email
#address it calls back and transforms all the letters into lower case. Had to do the indexing
#in active record in order for the method to work
validates :username , presence: true, length: {maximum: 250}
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
#code that ensures that a user puts the right format for emails in signup
#fields
validates :email, presence: true, length:{maximum: 50},
format:{with: VALID_EMAIL_REGEX },
uniqueness:{ case_sensitive: false }
#rails still assumes that uniquess is true
#whether the user types CAMELcase or lowercase
validates :password, presence: true, length:{maximum: 50}, allow_nil: true
validates :user_about_me, presence: true
validates :birthday, presence:true
has_secure_password
# 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 user token
def User.new_token
SecureRandom.urlsafe_base64
end
# Remember a given user to the database for use of persistent sessions
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
##returns true if given token matches the digest
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end
def forget
update_attribute(:remember_digest, nil)
end
def log_out
forget(current_user)
session.delete(:user_id)
#current_user = nil
end
end
This is the code in the partial rendering on the index page where all users show up.
<div class="col-md-9 col-offset-3" id="index-profile">
<li class="users">
<div class="col-xs-3 profilepic-container">
<%= image_tag user.avatar.url %>
</div>
<%= link_to user.username, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</li>
The delete link in your partial has two conditions that are required to be true. The user must be an admin, and the profile must not be their own profile. So if the admin user is the only user, then no delete link will show up.
Try creating a second user and see if the delete link shows up for that user.
I currently have a Rails app that allows users to create a group and allows other users to join the group. The group "creator" is the owner of the group and any that join ON REQUEST are the members. I want a user to be able to create only one group, but belong to many (I think that I've captured that relationship, but I'm a little uncertain). I need a little help understanding what I need to do to show the group associations on the User's page. How should I go about creating a group "show" page and how do I show the group memberships on the User "show" page? I got help from SO and followed the Railscast on self-referential association to help guide me through setting up the relationships.
In this example groups are called Cliqs and membership is controlled by a has_many :through. I used Devise for the User model.
To clarify my question: Am I capturing the relationship that I'm trying to set up? How would I go about allowing the user to view groups that they belong to?
As an aside, I'm not sure if the group creator is being associated as a member of the group. How do I represent that in my model/controller?
Here is my code:
Group Model:
class Cliq < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :members, through: :cliq_memberships, source: :user
has_many :cliq_memberships
end
Membership Model:
class CliqMembership < ActiveRecord::Base
belongs_to :cliq
belongs_to :user
end
User Model:
class User < ActiveRecord::Base
has_one :owned_group, foreign_key: 'owner_id', class_name: 'Group'
has_many :cliqs, through: :cliq_memberships
has_many :cliq_memberships
.
.
.
end
Group Controller:
class CliqsController < ApplicationController
def show
#cliq = Cliq.find(params[:id])
end
def new
#cliq = Cliq.new(params[:id])
end
def create
#cliq = Cliq.create(cliq_params)
if #cliq.save
redirect_to current_user
else
redirect_to new_cliq_path
end
end
def destroy
end
def cliq_params
params.require(:cliq).permit(:name, :cliq_id)
end
end
Group Membership Controller:
class CliqMembershipsController < ApplicationController
def create
#cliq = cliq.find(params[:cliq_id])
if #cliq_membership.save = current_user.cliq_memberships.build(:cliq_id => params[:cliq_id])
flash[:notice] = "Joined #{#cliq.name}"
else
#Set up multiple error message handler for rejections/already a member
flash[:notice] = "Not able to join Cliq."
end
redirect_to cliq_url
end
def destroy
#cliq = Cliq.find(params[:id])
#cliq_memberships = current_user.cliq_memberships.find(params[cliq_memberships: :cliq_id]).destroy
redirect_to user_path(current_user)
end
end
And my User Show Page:
<h1> <%= #user.username %> </h1>
<h2>Cliqs</h2>
<%= link_to "Create Cliq", new_cliq_path %>
<ul>
<% for cliq_membership in #user.cliq_memberships %>
<li>
<%= cliq_membership.cliq.name %>
(<%= link_to "Leave Cliq", cliq_membership, :method => :delete %>)
</li>
<% end %>
</ul>
<h3>Title:</h3>
<% #uploads.each do |upload| %>
<div>
<%= link_to upload.title, upload_url %>
</div>
<% end %>
And my Migrations:
Cliq:
class CreateCliqs < ActiveRecord::Migration
def change
create_table :cliqs do |t|
t.string :name
t.references :owner
t.integer :cliq_id
t.timestamps null: false
end
end
end
CliqMemberships:
class CreateCliqMemberships < ActiveRecord::Migration
def change
create_table :cliq_memberships do |t|
t.references :user
t.references :cliq
t.timestamps null: false
end
end
end
FULL SOLUTION OF WHAT WORKED BELOW.
Try the following:
Your revised models. Fixed the following issues:
In User model, for has_one :owned_group, you set class_name as Group instead of Cliq.
Declare has_many before has_many :through. It may work otherwise, but it is a good practice and easy for readability.
class User < ActiveRecord::Base
has_one :owned_group, foreign_key: 'owner_id', class_name: 'Cliq'
has_many :cliq_memberships
has_many :cliqs, through: :cliq_memberships
end
class CliqMembership < ActiveRecord::Base
belongs_to :cliq
belongs_to :user
end
class Cliq < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :cliq_memberships
has_many :members, through: :cliq_memberships, source: :user
end
Your revised controllers. Fixed the following issues:
In the CliqsController, as it is relates to Cliq, you won't get cliq_id while creating it. So removed the cliq_id from the cliq_params. You could add other cliq related attributes in there.
In create, you forgot to assign the current_user as the owner of the cliq. This is addressed by the next note.
As the user is the owner of the cliq, built the cliq using build_owned_group which automatically sets the current_user as the owner.
Try not to do multiple things in the same statement. Like assigning it to a variable as well as doing some operation on the newly assigned variable. For example: In create action of CliqMembershipsController, you were assigning the #cliq_membership as well as calling save on it. Separated those two into two steps.
In destroy of CliqMembershipsController, there is no need to load the #cliq and also fixed the way you are finding the #cliq_membership.
class CliqsController < ApplicationController
def show
#cliq = Cliq.find(params[:id])
end
def new
#cliq = Cliq.new(params[:id])
end
def create
#cliq = current_user.build_owned_group(cliq_params)
if #cliq.save
redirect_to current_user
else
redirect_to new_cliq_path
end
end
private
def cliq_params
params.require(:cliq).permit(:name)
end
end
class CliqMembershipsController < ApplicationController
def create
#cliq = Cliq.find(params[:cliq_id])
#cliq_membership = current_user.cliq_memberships.build(cliq: #cliq)
if #cliq_membership.save
flash[:notice] = "Joined #{#cliq.name}"
else
#Set up multiple error message handler for rejections/already a member
flash[:notice] = "Not able to join Cliq."
redirect_to cliq_url
end
def destroy
#cliq_membership = current_user.cliq_memberships.find(params[:id])
if #cliq_membership.destroy
redirect_to user_path(current_user)
end
end
end
And finally your revised view:
Fixed few things.
Try to use each on the collection to iteration through. This is more ruby way, instead of for loop.
Based on your CliqMemberhipsController code, I assumed you are using nested resources as below. So fixed the link_to to use cliq_cliq_memberhip_path instead of cliq_membership_path.
<h1><%= #user.username %></h1>
<h2>Cliqs</h2>
<%= link_to "Create Cliq", new_cliq_path %>
<ul>
<% #user.cliq_memberships.each do |cliq_membership| %>
<li><%= cliq_membership.cliq.name %>(<%= link_to "Leave Cliq", cliq_cliq_membership_path([cliq, cliq_membership]), method: :delete %>)</li>
<% end %>
</ul>
This assumes you have a routes file with the following:
resources :cliqs do
resources :cliq_memberships
end
Going along the lines of my comment above it seems to me the best thing to do is implement some kind of role attribute in the bridge table.
The Rails docs say this:
You should use has_many :through if you need validations, callbacks, or extra attributes on the join model.
So you might try this in your models:
class Cliq < ActiveRecord::Base
has_many :cliq_memberships
has_many :members, through: :cliq_memberships
def owner
cliq_memberships.where(role: 'owner').user
end
end
# this model is used to access attributes on the bridge table
class CliqMembership < ActiveRecord::Base
belongs_to :cliq
belongs_to :user
attr_accessor :role
end
class User < ActiveRecord::Base
has_many :cliq_memberships
has_many :cliqs, through: :cliq_memberships
# something like this would make it easy to grab the owned cliq
def ownedCliq
cliq_memberships.where(role: 'owner').cliq
end
end
so the bridge table stores role which would be an enum or a string representing 'member', 'owner', and maybe 'admin' or something.
Some example usage:
# say I have a user
u = User.find(1)
# and I want the cliq that he/she owns
owned_cliq = u.ownedCliq
# maybe I have a group:
g = Cliq.find(1)
# and I want the user that owns it:
my_owner = g.owner
# now let's get all the members of the cliq (including the 'owner')
my_members = g.members
More example usage:
# inside the controller...
# say I have a user:
u = User.find(1)
# this user is trying to create a cliq
# pretend we fill it in with its data here...
c = Cliq.new
c.save!
# we'll need to hook the two together:
cm = CliqMembership.new(role: 'owner', user_id: u.id, cliq_id: c.id)
cm.save!
# or we might try something like this:
#cm = CliqMembership.find_or_create_by #...
Also, I found this SO answer which does a good job of explaining things.
So I started with the code in my question above and then worked inward to my answer (through many additional trials). This may help someone in the future so here is what worked. (Taking advice from both answers):
class Cliq < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :cliq_memberships
has_many :members, through: :cliq_memberships, source: :user
end
class CliqMembership < ActiveRecord::Base
belongs_to :cliq
belongs_to :user
end
class User < ActiveRecord::Base
has_one :owned_cliq, foreign_key: 'owner_id', class_name: 'Cliq'
has_many :cliq_memberships
has_many :cliqs, through: :cliq_memberships
.
.
.
end
class CliqsController < ApplicationController
def show
#cliq = Cliq.find(params[:id])
end
def new
#cliq = Cliq.new(params[:id])
end
def create
#cliq = current_user.build_owned_cliq(cliq_params)
#cliq.members << current_user
if #cliq.save
redirect_to current_user
else
redirect_to new_cliq_path
end
end
def destroy
end
def cliq_params
params.require(:cliq).permit(:name, :cliq_id)
end
end
class UsersController < ApplicationController
def show
#find way to use username instead of id (vanity url?)
#user = User.find(params[:id])
#uploads = Upload.all
#cliq_memberships = CliqMembership.all
#cliqs = Cliq.all
end
end
class CliqMembershipsController < ApplicationController
def show
end
def create
#cliq = Cliq.find(params[:cliq_id])
#cliq_membership = current_user.cliq_memberships.build(cliq: #cliq)
if #cliq_membership.save
flash[:notice] = "Joined #{#cliq.name}"
else
#Set up multiple error message handler for rejections/already a member
flash[:notice] = "Not able to join Cliq."
end
redirect_to cliq_url
end
def destroy
#cliq_membership = current_user.cliq_membership.find(params[:id])
if #cliq_membership.destroy
redirect_to user_path(current_user)
end
end
class CreateCliqs < ActiveRecord::Migration
def change
create_table :cliqs do |t|
t.string :name
t.references :owner
t.timestamps null: false
end
end
end
class CreateCliqMemberships < ActiveRecord::Migration
def change
create_table :cliq_memberships do |t|
t.references :user
t.references :cliq
t.timestamps null: false
end
end
end
Thanks so much for all of the incredible help on this thread!
I'm trying to attach user_id (so I can access user details) to comments that are already attached to a page called Park.
I have three tables set up up: Park, Comment, and User:
class Park < ActiveRecord::Base
has_many :comments
has_many :users
end
class Comment < ActiveRecord::Base
belongs_to :park
has_one :user
end
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 :comments
validates_presence_of :username
validates :username, uniqueness: true
def admin?
admin
end
end
As you can see above, I'm using the Devise gem for users and authorizations.
Comments show on Park and so they are nested:
park_comment GET /parks/:park_id/comments/:id(.:format) comments#show
My comment controller is set up like this:
class CommentsController < ApplicationController
before_action :authenticate_user!, only: [:create]
before_action :authorize_admin!, only: [:delete]
def create
#park = Park.find(params[:park_id])
#comment = #park.comments.create(comment_params)
redirect_to park_path(#park)
end
def destroy
#park = Park.find(params[:park_id])
#comment = #park.comments.find(params[:id])
#comment.destroy
redirect_to park_path(#park)
end
private
def comment_params
params.require(:comment).permit(:comment, :user_id, :park_id)
end
end
I've been able to oscillate from park_id to user_id, but the trade off has consistently been to receive a big fat nil on the other term.
I just tried to add a hidden field to my comment form
<%= form_for([#park, #park.comments.build]) do |f| %>
<p>
<%= f.label :comment %><br>
<%= f.text_area :comment %>
<%= hidden_field_tag(:user_id, current_user.id) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
But that didn't seem to yield any results.
I had tried some ActiveRecord joining work, but it didn't want to latch on to my create so I gave that up. Having spent a while on this now, I'm convinced there's an easy solution I'm just not seeing. Ideas?
Your hidden_field_tag isn't working. It'll create a separate param, not one nested under the param key that you want.
My suggestion would be to remove the hidden_field altogether and specify the current_user in the controller.
class CommentsController < ApplicationController
def create
#park = Park.find(params[:park_id])
#comment = #park.
comments.
create(
comment_params.
merge(user_id: current_user.id) # adding here, on creation
# or merge(user: current_user)
)
redirect_to park_path(#park)
end
def comment_params
params.
require(:comment).
permit(:comment)
end
end
Why? Because otherwise a user can potentially change the value of that hidden_field and you'll be incorrectly storing the comment's user_id value.
I'm not sure if I understood you correctly, but looking at your code I can see some problems.
first of all, you create a hidden field but not using the form helper. That's why your user_id is not visible in your comment_params, causing your
big fat nil
:) .
Try to change
<%= hidden_field_tag(:user_id, current_user.id) %>
to
<%= f.hidden_field(:user_id, :value => current_user.id) %>
But a better Idea for this is to just remove the hidden field and change your controller to
def create
#park = Park.find(params[:park_id])
#comment = #park.comments.new(comment_params)
#comment.user = current_user
if #comment.save
redirect_to park_path(#park)
else
...
end
end
You can now remove your :user_id from your comment_params like this:
params.require(:comment).permit(:comment, :park_id)
Actually, you don't even need :park_id in there
So I have a service object that submits up votes and voted users into a database:
Here's the posts model:
class Post < ActiveRecord::Base
attr_accessible :comment_count, :downvote, :id, :text, :title, :upvote, :url, :user_id, :users_voted_up_by, :users_voted_down_by
serialize :users_voted_up_by, Array
serialize :users_voted_down_by, Array
belongs_to :user
end
Here's the User model:
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation, :username, :good_karma, :bad_karma, :posts_voted_up_on, :posts_voted_down_on
serialize :posts_voted_up_on, Array
serialize :posts_voted_down_on, Array
has_many :posts
attr_accessor :password
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email
validates_presence_of :username
validates_uniqueness_of :username
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
end
Now here's my Voter class that controls up votes and down votes.
class Voter
def initialize(post, user)
#post = post
#user = user
end
def upvote
return false unless #post.users_voted_up_by
#post.upvote += 1
#post.users_voted_up_by << #user.username
#user.good_karma += 1
#post.save && #user.save
end
def downvote
return false unless #post.users_voted_down_by
#post.upvote += 1
#post.users_voted_down_by << #user.username
#user.bad_karma += 1
#post.save && #user.save
end
end
It adds and retrevies the first one fine:
User1
But when I perform another "upvote" with a different user, instead of adding it to the array it just adds it to the string like this:
User1User2
Am I not using the line correctly?
#post.users_voted_up_by << #user.username
You're trying to model a many-to-many relationship via serialized arrays. In my opinion this is a misuse of Rails serialization feature.
The more appropriate way to design your problem is to create a Vote model which belongs to User and has one Post. It is better both in design perspective and db-performance perspective.
Once you do that you won't add users to a post votes array, you will just create a new Vote instance with the voter (user) id and the post id.