Adding current location to Ruby on Rails app with photo_geoloader - html

So I've sent about 3 days researching geoip, geocoder, cookies, sessions, html5 and so forth.
I am trying to add a current location (as of the location when the user posts the photo in form). The user will not change this data, I just want it to be automatically added to the post, and then added to the view of the post (currently i am using .time_ago for the timestamp of the post). I can currently show in a map, but am lost as to adding it to the post.
I prefer to user HTML5 or
rails #lat_lng = cookies[:lat_lng].split("|").
I just need it printed to the post of each user.
I have tried using Exifr gem to extract that data but it is not precise enough. I am interested also in photo_geoloader gem yet there is little documentation.
So far i have created a model using "photo" as my model name. Currently I am validating the uploaded image through my "post" model;
class Post < ActiveRecord::Base
acts_as_votable
belongs_to :model
has_many :comments, dependent: :destroy
has_many :notifications, dependent: :destroy
validates :model_id, presence: true
validates :image, presence: true
validates :caption, length: { minimum: 3, maximum: 300 }
has_attached_file :image,
styles: lambda { |a| a.instance.check_image_type}
def check_image_type
if is_image_type?
{:medium => "640"}
elsif is_video_type?
{
:medium => { :geometry => "640x480", :format => 'flv'},
:thumb => { :geometry => "100x100#", :format => 'jpg', :time => 10}, :processors => [:transcoder]
}
else
{}
end
end
def is_image_type?
image_content_type =~ %r(image)
end
def is_video_type?
image_content_type =~ %r(video)
end
validates_attachment_content_type :image, :content_type => [/\Aimage\/.*\Z/, /\Avideo\/.*\Z/, /\Aaudio\/.*\Z/]
scope :of_followed_models, -> (following_models) { where model_id: following_models }
end
I have researched everything so I'm looking for a full process in rails 5 :)

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 cannot update column value

I have created Rails(version 3.2) application with mysql database. I have table Message with column content. I can update the following data using rails console but I can't using run same code from seeds.rb.
data: "Join **** Audio / Video Meeting. This is an online meeting by ****, the community marketplace to find products and services in your neighbourhood. http://*****.dev:3000/conferences/80"
I have following code in my seeds.rb file
all_messages = Message.all
all_messages.each do |message|
message_content = message.content
if message_content.present? && message_content[/\/(.*)\/(.*)\/conferences/,2].present?
message_content.slice! (message_content[/\/(.*)\/(.*)\/conferences/,2]+'/')
if message.update_attributes!(content: message_content)
puts message.content
else
puts "nothing"
end
end
end
It does't show any errors, but data is not updated in db and not shown any errors.
This is my model file
class Message < ActiveRecord::Base
attr_accessible :content
after_save :update_conversation_read_status
belongs_to :sender, :class_name => "Person"
belongs_to :conversation
has_one :request
validates_presence_of :sender_id
validates_presence_of :content
def update_conversation_read_status
conversation.update_attribute(:last_message_at, created_at)
conversation.participations.each do |p|
last_at = p.person.eql?(sender) ? :last_sent_at : :last_received_at
p.update_attributes({ :is_read => p.person.eql?(sender), last_at => created_at})
end
end
end
Note: content is text type in db.

Efficently querying multi language categories and category items

So I have a bit of a server response time issue - which I think is caused due to obsolete queries. One major query chain that I have takes up to 370ms, which is obviously causing an issue.
Here are the requirements:
5 Different languages
There are several Product Categories (i.e. Cat 1, Cat 2, Cat 3, etc.)
Categories displayed depend on language. For example whilst category 1 is displayed in all languages, category 2 is only displayed in Germany and France but not in the UK
Each category contains x number of items (has_many belongs_to relationship). Again some items are displayed in certain languages others are not. For example even category 2 is displayed in France and Germany, only in Germany you can buy Item 1 and hence Item 1 should not be displayed in France but Germany.
The categories and items do have boolean fields named after the locale. This way I can set via flag whether or not to display the category and item in a specific language.
My solution:
Building the solution is quiet easy. In controller I read out all the categories for the current locale:
application_controller.rb (since it is used on every single page)
#product_categories = ProductCategory.where("lang_" + I18n.locale.to_s + " = ?", true)
And in the view (the navigation) I do the following:
layouts/navs/productnav.html.haml
- #product_categories.each do |category|
...
- category.products.includes(:product_teasers).where("lang_" + I18n.locale.to_s + " = ? AND active = ?", true, true).in_groups_of(3).each do |group|
...
The issue with this solution is that each time I fire a lot of queries towards the database. Using "includes" does not solve it as I can not specify what items to pull. Furthermore I require the in_groups_of(3) in my loop to display the items correctly on the page.
I was also looking into memchached solutions to have the queries cached all together - i.e. Dalli however, this would require me to change a lot of code as I am guessing I would require to query all categories for each language and cache them. In addition to it I have to query each item for each langugage depending on language and store that somehow in an array ?!
My question:
How to approach this ? There must be a simpler and more efficient solution. How to efficiently query respectively cache this?
Thank you!
UPDATE:
As requested here are my two Models:
1.) ProductCategory
class ProductCategory < ActiveRecord::Base
translates :name, :description, :slug, :meta_keywords, :meta_description, :meta_title, :header, :teaser, :fallbacks_for_empty_translations => true
extend FriendlyId
friendly_id :name, :use => [:globalize, :slugged]
globalize_accessors :locales => [:at, :de, :ch_de, :ch_fr, :fr, :int_en, :int_fr], :attributes => [:slug]
has_paper_trail
has_many :products, :dependent => :destroy
validates :name, presence: true, uniqueness: { case_sensitive: false }
default_scope { includes(:translations) }
private
def slug_candidates
[
[:name]
]
end
end
2.) Product
And every product Category can have 0..n Products, and each Product must belongs to one category.
class Product < ActiveRecord::Base
translates :slug, :name, :meta_keywords, :meta_description, :meta_title, :teaser, :power_range, :product_page_teaser, :product_category_slider_teaser, :fallbacks_for_empty_translations => true
extend FriendlyId
friendly_id :name, :use => :globalize
before_save :change_file_name
searchable do
text :name, :teaser, :product_page_teaser, :product_category_slider_teaser
integer :product_category_id
end
belongs_to :product_category
has_many :product_teasers, :dependent => :destroy
has_many :product_videos, :dependent => :destroy
has_many :product_banners, :dependent => :destroy
has_many :product_documents, :dependent => :destroy
has_many :product_tabs, :dependent => :destroy
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
has_many :references
has_and_belongs_to_many :contacts
accepts_nested_attributes_for :product_teasers, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :product_tabs, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :product_videos, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :product_banners, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :product_documents, :reject_if => :all_blank, :allow_destroy => true
has_paper_trail
validates :name, presence: true, uniqueness: { case_sensitive: false }
default_scope {includes(:translations)}
.... a lot more going on here ...
end
Please note: That category contains language flags (booleans), i.e lang_at, lang_de, lang_fr, etc. and if set then this category is displayed in that particualar language. SAME applies to products, as certain products are not displayed in all langauges altough the category might be.
Examples:
#product_categories = ProductCategory.where("product_categories.lang_" + I18n.locale.to_s + " = ?", true)
#products = Product.where("product_categories.lang_" + I18n.locale.to_s + " = ?", true)
I skipped any includes on purpose above - it is just to demonstrate the language logic.
UPDATE
The system have spent a lot of times to loop data in nested loop. Avoid to fetch data in nested loop. You have to use join or includes to catch your data more effective. For example:
Controller
#products = Product.includes(:product_category).where("product_categories.lang_" + I18n.locale.to_s + " = ? AND product_categories.active = ?", true, true).group_by(&:category)
View
- #products.each do |category, products|
<%= category.name %>
- products.each do |product|
<%= product.title %>
It needs to fix with your necessary code. I just help the main query. For example: active = ? is for products field or product_categories field. I hope It can help you.

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

Remove extra appended characters to a text stored in 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