Send parameters from controller to model rails - ruby-on-rails

I'm working on the Meetup Api.
I would like to save some conferences from the API into my database.
The saving conferences depend of the parameters passing into the view to the controller :
<%= link_to 'See conferences', conferences_path(:title => "ParisRb")%> |
Then I call the good method to look for the good conferences (comparing to the params) among all the one received from the api.
I would like the methods to be very generic and to be able to save any conferences not only 'ParisRb'.
So I modify all my methods in this goal but there is one I can not modify, I don't know how.
This is my whole code. The one I'd like to modify is self.conferences_filter(data) wich is supposed to receive the params from the controller instead of 'ParisRb'. But I know that passing parameters from the controller to the model is not a good practice. So any idea is welcome :)
lib/api_meetup.rb
class ApiMeetup
BASE_URI = "https://api.meetup.com"
def events(urlname)
HTTParty.get(BASE_URI + "/#{urlname}/events")
end
end
conferences_controller.rb
def index
#call to the API
response = ApiMeetup.new.events(params[:title])
api_data = JSON.parse(response.body)
filtered_conferences = Conference.conferences_filter(api_data)
conferences = Conference.save_conferences_from_api(filtered_conferences)
#conferences = conferences.current_conferences
end
conference.rb
#Keep only requested conferences
def self.conferences_filter(data)
requested_conferences = []
data.each do |event|
if event["name"].include?('ParisRb') #This should receive params[:title] instead of 'ParisRb'
requested_conferences << event
end
end
requested_conferences
end
#Save requested conferences from the Meetup API
def self.save_conferences_from_api(conferences)
# data = data_from_api
conferences.each do |line|
conference = self.new
conference.title = line['name']
conference.date = format_date(line['time'])
conference.url = line['link']
if conference.valid?
conference.save
end
end
self.all
end

That's was actually quite obvious.
I just needed to pass to argument to my method :
filtered_conferences = Conference.conferences_filter(api_data, params[:title])
#Keep only requested conferences
def self.conferences_filter(data, title)
requested_conferences = []
data.each do |event|
if event["name"].include?(title)
requested_conferences << event
end
end
requested_conferences
end

Related

Calling model methods using a variable Rails

Rails 5.2
I have a Catalog model, with the following methods:
def current_items
....
end
def sales_items
....
end
There are more than a dozen methods, and I would like to do, in my helper, is to define an array
categories = ['current', 'sales', ....]
categories.each do |category|
m = "{category}_items"
#items = Catalog.m
...
end
But, I am getting an error:
undefined method 'm' for Catalog:Class
Any idea if this can be done?
Please try below code :-
class Catalog < ActiveRecord::Base
def self.current_items
puts "from current_items"
end
def self.sales_items
puts "from sales_items"
end
end
Then call using :-
if public
m = "#{category}_items"
#items = Catalog.public_send(m)
if private
m = "#{category}_items"
#items = Catalog.send(m)
thanks :)
Try public_send to call the public methods in class, use send if you want to call private methods as well but avoid using send if not needed
m = "#{category}_items"
Catalog.public_send(m)
Give it a try!

Ruby add variables to an existing object?

How can I add variables to an existing obejct?
I have a list of chat rooms and I want to add a new variable for each chat to use at my view:
Example I want to add total users of chat
def index
chats_all = ChatRoom.all
#chats = Array.new
chats_all.each |chat|
chat.total_users = 10
#chats << chat
end
#chats
end
total_users is not an attribute of ChatRoom class.
[EDIT - explaim better after #jvillian great awnser]
I don't want total_users as an attribute of User class.
I just want to add as a variable to use at this one single page. For json rails already let my add new attributes to objects. Just need to use as_json().map and a merge()
Example:
def index
chats = chats.as_json().map {
|chat|
chat.merge(
total_users: 10
}
response = { chats: chats }
render json: response
end
Now I got an json with chats and each chat has total_users attribute.
I want to know if I can do something like this with objects, just add a temporary variable to use at index page.
Try
class ChatRoom < ActiveRecord::Base
attr_accessor :total_users
end
You can read more in the docs.
Then, index could look like:
def index
#chats = ChatRoom.all.map do |chat|
chat.total_users = 10
chat
end
end
Alternatively, I would be tempted to do something like:
class ChatRoom < ActiveRecord::Base
TOTAL_USERS = 10
attr_accessor :total_users
def total_users
#total_users || TOTAL_USERS
end
end
And then:
def index
#chats = ChatRoom.all
end
Now, you'll get
#chats.first.total_users
=> 10
You can set total_users to something else if you like, but it will default to 10.
Here's a potential approach using OpenStruct:
def index
#chats = ChatRoom.all.map do |chat|
OpenStruct.new(
chat.
attributes.
merge!(total_users: 10)
)
end
end
Now, you can do:
#chats.each do |chat|
puts chat.total_users
end
which will return 10.
BTW and TBH, I do something like that last sort of thing (using OpenStruct or custom decorators) all the time. In my more recent apps, views never have direct access to models.
Maybe you want to send the response to the view as an array and scan to show informations?
def index
#chats = ChatRoom.all.as_json().map { |chat| chat.merge("total_users" => 10) }
end
Then access #chats, which is actually an array of hashes, view:
<% #chats.each do |chat| %>
<p><%= chat["total_users"] %></p>
<% end %>
You can check how #chats is structured by <p><%= #chats %></p>
I maybe made some syntax error.
To create temporary custom Objects without add new attributes to database Struct solve my problem.
I can create a Struct with chat room info and total users
chat_info = Struct.new(:name, :total_users, :messages)
chat_temp = []
chats = ChatRoom.where(condition)
chats.each do |chat|
chat_temp << chat_info.new("nome", 100, messages)
end

Running GET Request Through Rails on separate thread

I have a get request that retrieves JSON needed for graphs to display on a page. I'd do it in JQuery, but because of the API that I am using, it is not possible -- so I have to do it in rails.
I'm wondering this: If I run the get request on a separate thread in the page's action, can the variable then be passed to javascript after the page loads? I'm not sure how threading works in rails.
Would something like this work:
Thread.new do
url = URI.parse("http://api.steampowered.com/IDOTAMatch_570/GetMatchHistory/v001/?key=#{ENV['STEAM_WEB_API_KEY']}&account_id=#{id}&matches_requested=25&game_mode=1234516&format=json")
res = Net::HTTP::get(url)
matchlist = JSON.parse(res)
matches = []
if matchlist['result'] == 1 then
matchlist['result']['matches'].each do |match|
matches.push(GetMatchWin(match['match_id']))
end
end
def GetMatchWin(match_id, id)
match_data = matchlist["result"]["matches"].select {|m| m["match_id"] == match_id}
end
end
end
Given that the above code is in a helper file, and it then gets called in the action for the controller as such:
def index
if not session.key?(:current_user) then
redirect_to root_path
else
gon.winlossdata = GetMatchHistoryRawData(session[:current_user][:uid32])
end
end
The "gon" part is just a gem to pass data to javascript.

Assign collection to query

I have a module which returns timesheet records. When there is a scope parameter provided the items method scopes the timesheets so it only returns certain timesheets. How can I use the result of that query in another query? It is about using team_users in the super.where(user_id: team_users) query.
module Collections
class TimesheetCollection < Collection
module TeamScope
def items
if params[:scope].present?
team_users = User.from_team(#manager)
super.where(user_id: team_users)
else
super
end
end
end
attr_reader :ability, :params
def initialize(ability, params, manager)
#ability = ability
#params = params
#manager = manager
extend TeamScope
end
def items
Timesheet.unscoped
end
def paginated
extend Pagination
self
end
end
end
for active record you can pass in an array of ids/values. For your query you could try to do something like this:
team_users = User.from_team(#manager)
super.where(user_id: team_users.collect{|u| u.id})

em-mongo examples?

Looking to use em-mongo for a text analyzer script which loads text from db, analyzes it, flags keywords and updates the db.
Would love to see some examples of em-mongo in action. Only one I could find was on github em-mongo repo.
require 'em-mongo'
EM.run do
db = EM::Mongo::Connection.new.db('db')
collection = db.collection('test')
EM.next_tick do
doc = {"hello" => "world"}
id = collection.insert(doc)
collection.find('_id' => id]) do |res|
puts res.inspect
EM.stop
end
collection.remove(doc)
end
end
You don't need the next_tick method, that is em-mongo doing for you. Define callbacks, that are executed if the db actions are done. Here is a skeleton:
class NonBlockingFetcher
include MongoConfig
def initialize
configure
#connection = EM::Mongo::Connection.new(#server, #port)
#collection = init_collection(#connection)
end
def fetch(value)
mongo_cursor = #collection.find({KEY => value.to_s})
response = mongo_cursor.defer_as_a
response.callback do |documents|
# foo
# get one document
doc = documents.first
end
response.errback do |err|
# foo
end
end
end

Resources