Rails5 - Ordering with Class method and params - ruby-on-rails

In Rails, I want to order some tweets by number of likes desc using paramsand I am stuck..
I wrote a simple Class method in my model:
class Twit < ApplicationRecord
def self.most_liked
order(like: :desc)
end
end
And here is my method in my controller:
class TwitsController < ApplicationController
def index
if params[:filter]
#twits = Twit.most_liked(params[:filter])
else
#twits = Twit.all
end
end
end
If I only use #twits = Twit.most_liked, it works fine, but when I add my condition with params it fails.
Thank you !

It can't work, because you try use never created metod. You created
def self.most_liked
order(like: :desc)
end
But later you call 'most_liked(bla-bla)'.
You should:
Add param to your method:
def self.most_liked(var1)
Or create method:
def most_liked(var1)
Twit.where(x=>var1).order(like: :desc)
end
Or change call of this method to:
Model.query.method - so:
Twit.where(params[:filter]).most_liked

It fails because you defined method self.most_liked without parameters, and then you try to pass a parameter Twit.most_liked(params[:filter]).
You should define method
def most_liked(some_variable)
or chain it with another method like this:
Twit.where(params[:filter]).most_liked

Related

Undefined method in controller

I'm getting an error when trying to call a method in my controller. Following tutorials on how to get this to work but just a bit stuck in the mud and need some help.
NoMethodError in CatalogController#index
undefined method `art' for #<Class:0x007fbe8c338310>
My model
require 'httparty'
require 'json'
class Feed < ActiveRecord::Base
include HTTParty
base_uri 'https://www.parsehub.com/api/v2/runs'
# GET /feeds
# GET /feeds.json
def art
response = self.class.get("/tnZ4F47Do9a7QeDnI6_8EKea/data?&format=json")
#elements = response.parsed_response["image"]
#parsed = #elements.collect { |e| e['url'] }
end
end
My controller
class CatalogController < ApplicationController
def index
#images = Feed.art
end
end
I'm guessing it's something fairly simple I'm forgetting.
def art defines an instance method, not a class method.
You have two options to fix this problem:
1) Make the method a class method by adding self. to the definition:
def self.art
# ...
2) Or create a Feed instance in your controller before calling art:
def index
#images = Feed.new.art
end

How to perform a method in model only if the controller action is create?

Question is in my rails app I have method called range days I only want this to work if the controller action is create_half how can I do this? any help would be greatly appreciated!!
This is my entry model
class Entry < ActiveRecord::Base
self.primary_key = 'id'
//This is what I want to only happen when my controller action is create_half
def range_days
self.range_days = only_weekdays(leave_start.to_date..(leave_end.to_date)).to_d
end
This is my entry controller
class EntryController < ApplicationController
def half_day
#entry = Entry.new
render :half_day
end
Change your attribute name from range_days to something else. Otherwise you won't be able to get the value in range_days action.
self.range_days in range_days method will call the range_days method again instead of the range_days attribute. As a result it will become an infinite loop and you will get a Stack Level Too Deep exception.
Then you can simply do the following in your controller:
def create_half
#entry = Entry.new
#entry.range_days
...
end
I assume you are looking for a railsy way to do this. Its not needed:
class EntryController < ApplicationController
def create_half
#entry = Entry.new.range_days
#other stuff
end
end
Should do you fine.

How to pass values from method in model to another method, or controller in ruby on rails

Can i pass values between methods in model or between method and controller in ruby on rails?, here my example:
My model:
class Artist::Data < ActiveRecord::Base
def self.set1(timeline)
a = timeline
set2 << a
end
def self.set2
logger.debug "HAA #{a}"
return a
end
end
My controller:
class Feed::FeedsController < ApplicationController
def index
#get a from set2 method
#a = Artist::Data.set2 (=a)
end
end
It's just an example, I don't know how to do it in real app. I want to pass value from set1 method to set2 method, then I can show it in FeedsController. So, how can I do it??, please help me!
I assume you are familiar with class variables and instance variables. So if you want to pass data between two class methods you can use class variables.
class Artist::Data < ActiveRecord::Base
def self.set1(timeline)
#a = timeline
end
def self.set2
logger.debug "HAA #{#a}"
return #a
end
end
More Info : http://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/45-more-classes/lessons/113-class-variables

Define a method to catch a_method[] in a class

I have a lots of call to something like this :
User.active[0..5]
Which call :
class User
def active
(an ActiveRelation)
end
end
I am trying to do something like this for performance reasons :
class User
def active[limit]
(an ActiveRelation).limit(limit.to_a.size)
end
end
Unfortunately it doesn't work, any ideas to implement this ?
== EDIT
More cleaner :
class RelationWithLimit < ActiveRecord::Relation
def [] selector
case selector
when Integer
self.offset(selector).limit(1)
when Range
self.offset(selector.to_a[0]).limit(selector.to_a.size)
end
end
end
class ActiveRecord::Base
private
def self.relation #:nodoc:
#relation ||= RelationWithLimit.new(self, arel_table)
finder_needs_type_condition? ? #relation.where(type_condition) : #relation
end
end
You could have your own special subclass of ActiveRelation
class UserReturnRelation < ActiveRecord::Relation
def [] lim
self.limit lim
end
end
class User
def active
# Without knowing exactly what relation you are using
# One way to instantiate the UserReturnRelation for just this call
UserReturnRelation.new(self, arel_table).where("state = active")
end
end
Then User.active[5] should work as expected.
EDIT: Added instantiation info. You may want to look at Base#scoped and Base#relation for more info
Can you try it as params instead of array-indices? eg:
class User
def active(the_limit)
(an ActiveRelation).limit(the_limit)
end
end
User.active(5)
(note: not tested on any actual ActiveRelations...)
You can do it like this:
class User
def active
Limiter.new((an ActiveRelation))
end
class Limiter
def initialize(relation)
#relation = relation
end
def method_missing(method, *arguments, &block)
#relation.send(method, *arguments, &block)
end
def respond_to?(method, include_private = false)
#relation.respond_to?(method, include_private) || super
end
def [](value)
offset = value.to_a.first
limit = value.to_a.last - offset
#relation.offset(offset).limit(limit)
end
end
end
Well, you are defining the method in the wrong class. User.active[0..5] calls the class method active in User and the method [] in whatever class User.active is returning, I'll assume that it is returning an array of users, and Array has already defined the method [] so no worries about that.
You may be getting confused thinking that brackets are some kind of parenthesis for passing arguments to a function while they're not. Try this:
class User
class << self
def [](values)
self.find(values)
end
end
end
So, if you wanna use find with an arrays of ids, you may just use User[1,2,3].

define method in model that can be accessed in controller

I have defined a problems method in my Report model. I need to use the value of Report.problem in the report's controller while defining the action show. But i keep getting the error message 'undefined method problem'. How do i solve this? Any assistance would be greatful.
I have a report model and a problem model that contains a list of all problems.
In report model
def problems1
Problem.find(:all, :conditions => )
end
In the reports controller i need something like
def show
#report = Report.problems1
end
you have to assign self.method_name to use as a class method
Follow following rule for Model methods
Class Method
def self.problem
end
in controller
Report.problem
Instance method
def problem
end
in controller
report = Report.new
report.problem
If you define method as class method
class Report < ActiveRecord :: Base
def Report.problem
puts 1
end
end
Report.problem
>1
But if you define method as object
class Report < ActiveRecord :: Base
def problem
puts 1
end
end
This method call
report = Report.new
report.problem
>1

Resources