Remove extra appended characters to a text stored in MySQL - mysql

I have an api controller that collects information from the api users. However, some user information when sent and stored in the MySQL database sometimes its appears with added underscores like this "this is a test ________" instead of this is a test. However when run through the browser it stores just fine.
What could be the problem.
Controller extract;
#message.message = CGI.unescape(params[:message]).strip
As a temporary fix, any ideas how i can strip away all the 6 underscores that are being added to the message either in storage or when it comes.
class Api::V1::Json::MessagesController < ApplicationController
before_filter :authenticate
require 'uri'
require 'cgi'
def sms
#message = Message.new
##message.to = decoded_to.gsub(/[^\d]/,"")
#message.to = CGI.unescape(params[:to]).strip.gsub("+","").gsub(/\s+/, "")
#message.from = CGI.unescape(params[:from])
#message.message = CGI.unescape(params[:message]).strip
#message.user_id = current_user.id
#message.status = 'Queued'
if #message.save
MessageWorker.perform_async(#message.id, [""], current_user.id)
render json: {status: "Success"}
else
render json: {status: "Failed" }
end
end
private
def authenticate
error!('Unauthorized. Invalid token.', 401) unless current_user
end
def current_user
# find token. Check if valid.
user_token = params[:token]
token = ApiKey.where(:access_token => user_token).first
if token
#current_user = User.find(token.user_id)
else
false
end
end
end
and the model is;
class Message < ActiveRecord::Base
attr_accessible :message, :phone, :status, :to, :from, :user_id
attr_accessor :schedule
validates :message, :presence => true
validates :from, :presence => true
validates :to, :presence => true
validates :status, :presence => true
validates_length_of :message, :maximum => 1600, :allow_blank => true
validates_length_of :from, :maximum => 11, :allow_blank => false
belongs_to :user

Change your Model like this
class Message < ActiveRecord::Base
before_save :strip_underscore
def strip_underscore
self.message.gsub("______","")
end
end

Related

Need help creating a GET route

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

Rails 5 not saving to my table using nested forms in Ruby-on-Rails using Cocoon gem

RAILS 5 PROBLEM. I have a project and I wanted the user to have the option to add extra items to the form. My code renders correctly and it the link to add more fields does add more text field. The problem I have is that is not saving the to my database. I am using mysql2 gem on a MySQl database. I posted the console output. This is what I have:
forms_controller
# forms_controller.rb
def new
#form = Form.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #form }
end
end
def create
#form = Form.new(form_params)
respond_to do |format|
if #form.save
format.html { redirect_to(#form, :notice => 'form was successfully created.') }
format.xml { render :xml => #form, :status => :created, :location => #form }
else
format.html { render :action => "new" }
format.xml { render :xml => #form.errors, :status => :unprocessable_entity }
end
end
end
def form_params
params.require(:form).permit(:name, items_attributes: [:id, :item_name, :_destroy])
end
models
# form.rb
class Form < ApplicationRecord
has_many :items
accepts_nested_attributes_for :items, reject_if: :all_blank, allow_destroy: true
validates_presence_of :name
end
# item.rb
class Item < ApplicationRecord
belongs_to :form
end
views
<!-- _form.html.haml -->
= form_for #form do |f|
.field
= f.label :name
%br
= f.text_field :name
%h3 items
#items
= f.fields_for :items do |item|
= render 'item_fields', f: item
.links
= link_to_add_association 'add item', f, :items
= f.submit
.nested-fields
.field
= f.label :item_name
%br
= f.text_field :item_name
= link_to_remove_association "remove item", f
console
tarted POST "/forms" for 127.0.0.1 at 2016-09-08 23:04:17 -0600
Processing by FormsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FmYPwlXy93iwBMkWvfyd3QJ+NKDcYnraUaKmMISbUIX3+KRL7KtpD33FW3CK+jxvn4AoUUMhx4zrGncJej5BOw==", "form"=>{"name"=>"sfsf", "items_attributes"=>{"1473397456358"=>{"item_name"=>"sfsf", "_destroy"=>"false"}}}, "commit"=>"Create Form"}
(0.2ms) BEGIN
(0.3ms) ROLLBACK
Rendering forms/new.html.haml within layouts/application
Rendered forms/_item_fields.html.haml (1.5ms)
Rendered forms/_item_fields.html.haml (1.2ms)
Rendered forms/_form.html.haml (8.5ms)
Rendered forms/new.html.haml within layouts/application (10.1ms)
Completed 200 OK in 68ms (Views: 54.5ms | ActiveRecord: 0.5ms)
in your permit/require line (in your controller), item_attribute should probably be item_attributes (there's more than one) ie:
def form_params
params.require(:form).permit(:name, :date_sent, :quantity, :comment, item_attributes: [:id, :name, :form_id, :_destroy])
end
In Rails 5, whenever we define a belongs_to association, it is required to have the associated record present by default after this change.
It triggers validation error if associated record is not present.
class User < ApplicationRecord
end
class Post < ApplicationRecord
belongs_to :user
end
post = Post.create(title: 'Hi')
=> <Post id: nil, title: "Hi", user_id: nil, created_at: nil, updated_at: nil>
post.errors.full_messages.to_sentence
=> "User must exist"
****Opting out of this default behavior in Rails 5****
We can pass optional: true to the belongs_to association which would remove this validation check.
class Post < ApplicationRecord
belongs_to :user, optional: true
end
post = Post.create(title: 'Hi')
=> <Post id: 2, title: "Hi", user_id: nil>
The reason it wouldn't save is because I was using Rails 5 and I needed to add optional: true to the belongs_to in the item model.
# form.rb
class Form < ApplicationRecord
has_many :items
accepts_nested_attributes_for :items, reject_if: :all_blank, allow_destroy: true
validates_presence_of :name
end
# item.rb
class Item < ApplicationRecord
belongs_to :form , optional: true
end

Rails search a model based on multiple parameters using a form

So... I've been working on creating a search form for a rails application. I've gone through the railscast episodes 37, 111, and 112.
While the simple text search with a text input field works. I need to be able to define more parameters to refine the search.
I've found a few other methods, some using scopes...I keep running into issues getting any of these working in my application....
What I have right now is a simple form defined on my home index that points at my assets index:
<% form_tag assets_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= collection_select(:type_id, :type_id, Type.where("type_for = 'asset'"), :id, :name) %>
<%= submit_tag "Search", :search => nil %>
<% end %>
my asset.rb model:
class Asset < ActiveRecord::Base
has_many :children_assets, :class_name => "Asset"
has_and_belongs_to_many :groups, :join_table => "assets_groups"
belongs_to :parent_asset,
:class_name => "Asset",
:foreign_key => "parent_asset_id"
belongs_to :asset_type,
:class_name => "Type",
:conditions => "type_for = 'asset'"
belongs_to :asset_status,
:class_name => "Status",
:conditions => "status_for = 'asset'"
belongs_to :location
belongs_to :funding_source
has_many :transactions
def self.search(search)
if search
find(:all, :conditions => ['nmc_name LIKE ? AND type_id = ?', "%#{search}%", "%#{search}"])
else
find(:all)
end
end
end
in the asset_controller.rb
def index
unless params[:search].nil?
#title = "Assets"
#search = params[:search]
#assets = Asset.search(params[:search]).paginate(page: params[:page], per_page: 25)
else
#title = "Assets"
#assets = Asset.where('').paginate(page: params[:page], per_page: 25)
end
end
I just dont understand what it is that I'm not seeing here. I can run a similar mysql query and get the result I want. I just dont know how to format this in rails...
Any guidance on this would be amazing right now. Thanks!
It looks as though you're trying to search for a specific type of asset, but your search method in the Asset model is only using one of the user supplied parameters.
Judging by the form you're using, your controller will be receiving the params
params = {
search: 'Search Text',
type_id: 1
}
In your controller, you're only using search, so I'd change your method to include this:
#assets = Asset.search(params[:search], params[:type_id]).paginate(page: params[:page], per_page: 25)
Then amend the Assets model to use it
def self.search(search, type_id)
if search
find(:all, :conditions => ['nmc_name LIKE ? AND type_id = ?', "%#{search}%", "%#{type_id}"])
else
find(:all)
end
end

Rails create and update array in database

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.

How to check all checkboxes when the user visits the page for the first time?

I want the checkboxes to be checked when the user visits the page for the first time.
This file is app/views/movies/index.html.haml
%h1 All Movies
= form_tag movies_path, :method => :get, :id => 'ratings_form' do
Include:
- #all_ratings.each do |rating|
= rating
= check_box_tag "ratings[#{rating}]", "1", #checked_ratings.include?(rating), :id => "ratings_#{rating}",
= submit_tag 'Refresh', :id => 'ratings_submit'
%table#movies
%thead
%tr
%th{:class => ("hilite" if #sort == "title")}= link_to "Movie Title", movies_path( :sort => "title", :ratings => #checked_ratings), :id => "title_header"
%th Rating
%th{:class => ("hilite" if #sort == "release_date")}= link_to "Release Date", movies_path( :sort => "release_date", :ratings => #checked_ratings), :id => "release_date_header"
%th More Info
%tbody
- #movies.each do |movie|
%tr
%td= movie.title
%td= movie.rating
%td= movie.release_date
%td= link_to "More about #{movie.title}", movie_path(movie)
= link_to 'Add new movie', new_movie_path
#This is my Controller
class MoviesController < ApplicationController
def show
id = params[:id] # retrieve movie ID from URI route
#movie = Movie.find(id) # look up movie by unique ID
# will render app/views/movies/show.<extension> by default
end
def index
#get all the ratings available
#all_ratings = Movie.all_ratings
#checked_ratings = (params[:ratings].present? ? params[:ratings] : [])
#sort = params[:sort]
#movies = Movie.scoped
if #sort && Movie.attribute_names.include?(#sort)
#movies = #movies.order #sort
end
id #checked_ratings.empty?
#checked_ratings = #all_ratings
end
unless #checked_ratings.empty?
#movies = #movies.where :rating => #checked_ratings.keys
end
end
def new
# default: render 'new' template
end
def create
#movie = Movie.create!(params[:movie])
flash[:notice] = "#{#movie.title} was successfully created."
redirect_to movies_path
end
def edit
#movie = Movie.find params[:id]
end
def update
#movie = Movie.find params[:id]
#movie.update_attributes!(params[:movie])
flash[:notice] = "#{#movie.title} was successfully updated."
redirect_to movie_path(#movie)
end
def destroy
#movie = Movie.find(params[:id])
#movie.destroy
flash[:notice] = "Movie '#{#movie.title}' deleted."
redirect_to movies_path
end
end
In the controller, I set the #checked_rating to be #all_rating if the #checked.rating is empty but it does not do anything.
I tried putting :checked => true in the index.html.haml on the check_box_tag but that makes the checkboxes checked everytime the page is refreshed.
Everytime I check a particular checkbox and hit refresh button the page loads with all the checkboxes checked.
You can use localstorage + JavaScript to achieve this. On page load, check for the value of a property from the localstorage. If the value is set, don't check the boxes. If the values is not set, check all the boxes and set the value in localstorage.
Varun