Return time difference in method as JSON - ruby-on-rails

I return all information in a scream as JSON.
I want to return how long ago it was created.
include ActionView::Helpers::DateHelper
def as_json(options={})
super(:only => [:id, :yell_type, :status, :payment_type],
:include => {
:trade_offer => {:only => [:id, :title, :description, :price],
:include => [:photos => {:only => [:id, :url]}]
},
:categories => {:only => [:id, :name]},
:user => {:only => [:id, :name, :avatar]}
},
:methods => [ times_ago(:create_at) ]
)
end
def times_ago(create_at)
time_ago_in_words(create_at)
end
This returns an error:
comparison of Symbol with Time failed
How should I do that?

You can add methods on the same level as include and only. So the return value of the method will be passed in the JSON too. In this case, you should implement a method times_ago in the model that returns what you want.
def as_json(options={})
super(
:only => [:id, :yell_type, :status, :payment_type],
:include => {
:trade_offer => {:only => [:id, :title, :description, :price],
:include => [:photos => {:only => [:id, :url]}]
},
:categories => {:only => [:id, :name]},
:user => {:only => [:id, :name, :avatar]}
},
:methods: [ :times_ago ]
)
end

Related

How to convert mongoid criteria to array?

I have a mongoid criteria categories and I need to convert to an array. I'm using categories.to_a but this dont works and always that the mongoid criteria is iterate by .map it's doing a .find a new query.
How can I fix this?
def self.mapOffers (array, user)
array.map { |u|
{
:id => u.id.to_s,
:name => u.name,
:description => u.description,
:price => u.price,
:url => u.url,
:categories => Category.mapCategories(u.categories.to_a, user),
:picture => u.picture.url,
:accepts_cash => u.accepts_cash_transactions,
:location => {
:longitude => u.longitude,
:latitude => u.latitude,
:street => u.street,
:neighborhood => u.neighborhood,
:number => u.number,
:zip => u.zip,
:city => u.city,
:state => u.state,
:complement => u.complement,
:country => u.country,
},
:fixedMeetingPoint => u.fixedMeetingPoint,
:meetingPoint => {
:street => u.meetingPointStreet,
:neighborhood => u.meetingPointNeighborhood,
:number => u.meetingPointNumber,
:zip => u.meetingPointZip,
:city => u.meetingPointCity,
:state => u.meetingPointState,
:complement => u.meetingPointComplement,
:country => u.meetingPointCountry,
:latitude => u.meetingPointLatitude,
:longitude => u.meetingPointLongitude,
},
:notes => u.notes,
}}
end
def self.mapCategories (array, user)
array.map { |u| {
:id => u.id.to_s,
:name => u.name,
:selected => !user.nil? && u.users.include?(user),
:picture => u.picture.url,
}}
end
Starting from criteria:
scope = Band.where(name: 'foo')
... retrieve the complete result set from the database and store in an array:
bands = scope.to_a
... then iterate the array any number of times:
bands.each { |band| ... }
bands.each { |band| ... }

Ruby on Rails render array of objects plus number of elements

I have a rails method with this render:
render :json => #boats, :include => { :mainPhoto => {:only => [:id, :mime]},
:boat_model => { :only => :name, :include => {:boat_type => { :only => :name}}}}
Can I include a numTotal variable in this response?
You'll need to use the as_json method to serialize #boats in separated JSON key:
render :json => { numTotal: boats.size, boats: #boats.as_json(:include => { :mainPhoto => {:only => [:id, :mime]},
:boat_model => { :only => :name, :include => {:boat_type => { :only => :name}}}})

Nested Include Rails Only One Shows

I am attempting to nest some as_json includes. However, only the first shows up. My code is below. In the below case, only the product is rendered. However, if I switch the order of order_pad and product, only the order_pad renders.
#Renders json
def as_json(options={})
super(
:except => [:created_at, :updated_at, :order_pad_id, :product_id],
:include => [
:product => {
:except => [:created_at, :updated_at]
},
:order_pad => {
:except => [:created_at, :updated_at, :user_id],
:include => [
:user => {
:only => [:id, :name_first, :name_last, :company]
}
]
}
]
)
end
You need to send those as two separate hashes:
:include => [
{
:product => {
:except => [:created_at, :updated_at]
}
},
{
:order_pad => {
:except => [:created_at, :updated_at, :user_id],
:include => [
:user => {
:only => [:id, :name_first, :name_last, :company]
}
]
}
}
]

Fuzzy String Matching with Rails (Tire) and ElasticSearch

I have a Rails application that is now set up with ElasticSearch and the Tire gem to do searching on a model and I was wondering how I should set up my application to do fuzzy string matching on certain indexes in the model. I have my model set up to index on things like title, description, etc. but I want to do fuzzy string matching on some of those and I'm not sure where to do this at. I will include my code below if you would like to comment! Thanks!
In the controller:
def search
#resource = Resource.search(params[:q], :page => (params[:page] || 1),
:per_page =>15, load: true )
end
In the Model:
class Resource < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
belongs_to :user
has_many :resource_views, :class_name => 'UserResourceView'
has_reputation :votes, source: :user, aggregated_by: :sum
attr_accessible :title, :description, :link, :tag_list, :user_id, :youtubeID
acts_as_taggable
mapping do
indexes :id, :index => :not_analyzed
indexes :title, :analyzer => 'snowball', :boost => 40
indexes :tag_list, :analyzer => 'snowball', :boost => 8
indexes :description, :analyzer => 'snowball', :boost => 2
indexes :user_id, :analyzer => 'snowball'
end
end
Try creating custom analyzers to achieve other stemming features, etc.
Check out my example (this example also uses Mongoid & attachments, don't look at it if you don't need it):
class Document
include Mongoid::Document
include Mongoid::Timestamps
include Tire::Model::Search
include Tire::Model::Callbacks
field :filename, type: String
field :md5, type: String
field :tags, type: String
field :size, type: String
index({md5: 1}, {unique: true})
validates_uniqueness_of :md5
DEFAULT_PAGE_SIZE = 10
settings :analysis => {
:filter => {
:ngram_filter => {
:type => "edgeNGram",
:min_gram => 2,
:max_gram => 12
},
:custom_word_delimiter => {
:type => "word_delimiter",
:preserve_original => "true",
:catenate_all => "true",
}
}, :analyzer => {
:index_ngram_analyzer => {
:type => "custom",
:tokenizer => "standard",
:filter => ["lowercase", "ngram_filter", "asciifolding", "custom_word_delimiter"]
},
:search_ngram_analyzer => {
:type => "custom",
:tokenizer => "standard",
:filter => ["standard", "lowercase", "ngram_filter", "custom_word_delimiter"]
},
:suggestions => {
:tokenizer => "standard",
:filter => ["suggestions_shingle"]
}
}
} do
mapping {
indexes :id, index: :not_analyzed
indexes :filename, :type => 'string', :store => 'yes', :boost => 100, :search_analyzer => :search_ngram_analyzer, :index_analyzer => :index_ngram_analyzer
indexes :tags, :type => 'string', :store => 'yes', :search_analyzer => :search_ngram_analyzer, :index_analyzer => :index_ngram_analyzer
indexes :attachment, :type => 'attachment',
:fields => {
:content_type => {:store => 'yes'},
:author => {:store => 'yes', :analyzer => 'keyword'},
:title => {:store => 'yes'},
:attachment => {:term_vector => 'with_positions_offsets', :boost => 90, :store => 'yes', :search_analyzer => :search_ngram_analyzer, :index_analyzer => :index_ngram_analyzer},
:date => {:store => 'yes'}
}
}
end
def to_indexed_json
self.to_json(:methods => [:attachment])
end
def attachment
path_to_file = "#{Rails.application.config.document_library}#{path}/#{filename}"
Base64.encode64(open(path_to_file) { |file| file.read })
end
def self.search(query, options)
tire.search do
query { string "#{query}", :default_operator => :AND, :default_field => 'attachment', :fields => ['filename', 'attachment', 'tags'] }
highlight :attachment
page = (options[:page] || 1).to_i
search_size = options[:per_page] || DEFAULT_PAGE_SIZE
from (page -1) * search_size
size search_size
sort { by :_score, :desc }
if (options[:facet])
filter :terms, :tags => [options[:facet]]
facet 'global-tags', :global => true do
terms :tags
end
facet 'current-tags' do
terms :tags
end
end
end
end
end
Hope it helps,

inner methods on attributes in respond_with

I'm rendering a serialized JSON response with the following code:
respond_with(#posts, :only => [:id, :content, :created_at],
:include => { :user => { :only => [:id, :name] },
:comments => { :only => [:content, :created_at] }})
the response is parsed in JAVA code so I want to convert the created_at value to a format that I can use, how do i run a method on each created_at value (even .to_i for example) ?
I would do it defining a new method inside comments model e.g.
class Comment < ActiveRecode::Base
...
def created_at_to_i
created_at.to_i
end
...
end
and while rendering
respond_with(#posts, :only => [:id, :content, :created_at],
:include => { :user => { :only => [:id, :name] },
:comments => { :only => [:content, :created_at_to_i] }})
Define method in each model like :
def formated_created_at
self.created_at.strftime(FORMAT_AS_YOU_LIKE)
end
At the time of rendering use it like :
respond_with(#posts, :only => [:id, :content, :formated_created_at
,
:include => { :user => { :only => [:id, :name] }, :comments => { :only => [:content, :formated_created_at
] }})
EDITED :
Instead of using the :only in respond_with , you can create your own hash and pass it to respond_with .
Like :
post_hash= { :post => [{:id => 1, :content => "abc", :created_at => self.formated_created_at,:user => {:id => 1, :name => 'Vik' }, :comments => { :content => "comment text", :created_at => self.comment.formated_created_at}] }
respond_with(post_hash)
And I think u can format the created_at at the time of displaying , via javascript, jQuery .

Resources