I really can't find the solution for this. I'm trying to access a game API to fill platform (PS3 Xbox) information for the games I insert manually. All information about the game that I have (like the name of the game) is in strong params. So I use the name that I inserted manually to get platform using the API.
When I try the first example, things works just well, but the second example, I got no answer from the server. Nothing happens when I submit to the create action, not a single line on server logs :-/
The only difference between the examples is the way I save game's name to make the API request. I'm using Nokogiri Gem to parse API's XML and the code looks fine to me.
Can you help me?
Thanks,
Example 1 (works well):
def create
#game = Game.new(game_params)
firstUrl = "http://thegamesdb.net/api/GetGamesList.php?name=sonic"
# I'm hardcoding a game just for debug
gameList = Nokogiri::XML(open(firstUrl))
gameApiId = gameList.css("Game id").first.text
secondUrl = "http://thegamesdb.net/api/GetGame.php?id=" + gameApiId
gameInformation = Nokogiri::XML(open(secondUrl))
#game.platform = gameInformation.xpath("//Game//Platform").text
if #game.save
redirect_to #game, notice: 'Game was successfully created.'
else
render :new
end
end
private
def game_params
params.require(:game).permit(:name, :publisher, :year, :description, :image, levels_attributes: [:id, :name, :sort_order, :_destroy])
end
Example 2 (no response from server)
def create
#game = Game.new(game_params)
firstUrl = "http://thegamesdb.net/api/GetGamesList.php?name=" + #game.name.gsub(/\s+/, "")
# I'm hardcoding a game just for debug
gameList = Nokogiri::XML(open(firstUrl))
gameApiId = gameList.css("Game id").first.text
secondUrl = "http://thegamesdb.net/api/GetGame.php?id=" + gameApiId
gameInformation = Nokogiri::XML(open(secondUrl))
#game.platform = gameInformation.xpath("//Game//Platform").text
if #game.save
redirect_to #game, notice: 'Game was successfully created.'
else
render :new
end
end
private
def game_params
params.require(:game).permit(:name, :publisher, :year, :description, :image, levels_attributes: [:id, :name, :sort_order, :_destroy])
end
In summary, the difference is this:
firstUrl = "http://thegamesdb.net/api/GetGamesList.php?name=" + #game.name.gsub(/\s+/, "")
What you're going to get on here are tips on how to debug this issue. The problem is since you're pinging a third-party API, we have scant information on what the returned data is meant to be like, making any "solution" a case of stabbing in the dark
--
Debug
I would do several things:
Make sure this new link is accessible & returns data
Make sure the rest of the variables & data is intact
Ensure the third party API is able to provide the return you want
I suspect the issue will be with the way you're calling #game.name.gsub - have you confirmed this is indeed being called?
I just tested the url http://thegamesdb.net/api/GetGamesList.php?name=StarFox and it brought back data. Upon initial insepction, I would suspect the crux of the issue is with your calling of this url
Related
I am working on a project to do CRUD Operations to firebase. I made use of this to help facilitate and link my ruby project to firebase.
Functions:
def delete_firebase(event_params,rootpath="Events/")
query = init_firebase.delete(rootpath,event_params)
end
def new_firebase(event_params,rootpath="Events")
query = init_firebase.push(rootpath,event_params)
end
def init_firebase # Inits firebase project with URL and secret
firebaseURL = "myfirebaseprojecturl"
firebaseSecret = "myfirebasesecret"
firebase = Firebase::Client.new(firebaseURL, firebaseSecret)
end
Event params consist of my event parameters as shown below
def event_params
params.require(:event).permit(:eventID, :eventName, :attachment, :eventNoOfPpl, :eventAdminEmail, {eventpics: []})
end
I encountered an issue. When I push with push() into firebase, there is a random key like -LSFOklvcdmfPOWrxgBo. In such case, the structure of the document would look like this:
But I cannot delete anything from -LSFOklvcdmfPOWrxgBo as I do not have the value. I used delete() from Oscar's firebase-ruby gem. I would appreciate any help with this issue.
I re-read the gem docs, and got some help from my friends and came up with two solutions
The body's response has response.body # => { 'name' => "-INOQPH-aV_psbk3ZXEX" } and thus, you're able to find out the name if you'd like
Change the index, and don't use .push, instead I made use of .set and did a random number for every event
Final solution
def load_firebase(root_path = "Events")
firebase_json = init_firebase.get(root_path)
if valid_json?(firebase_json.raw_body)
#json_object = JSON.parse(firebase_json.raw_body)
end
end
def update_firebase(event_params, root_path = "Events/")
init_firebase.update("#{root_path}#{event_params["eventID"]}", event_params)
end
def delete_firebase(event_params, root_path = "Events/")
init_firebase.delete("#{root_path}#{event_params["eventID"]}")
end
def save_firebase(event_params, root_path = "Events/")
init_firebase.set("#{root_path}#{event_params["eventID"]}", event_params)
end
I have applications table with attachment field which is a file uploaded by carrierwave. I'm using SQLLite. Upon application form submit, in #create
#application = Application.new(application_params)
#application contains attachment as nil.
Interestingly,
params[:attachment] is nil also but params[:application][:attachment] = 'valid/path/of/file' and application_params is also 'same/valid/path/of/file'.
As a result #application cannot be saved as I cannot save without attachment. It has suddenly started and I cannot figure out. Can anyone please advise. TIA. #create action upto save:
def create
#application = Application.find_by_user_id_and_type_id(params[:application][:user_id], params[:application][:type_id])
if params[:application][:attachment].nil? || params[:application][:attachment].blank?
flash[:notice] = "You have to add an attachment of type - .doc/.docx/.pdf/.txt/.rtf."
end
if #application.nil?
#application = Application.new(application_params)
if #application.save
Here's the browser output from submit.
{"utf8"=>"✓","authenticity_token"=>"egFav9RYAOXJQ==","application{"user_=>"109", "type_id"=>"4", "years_of_experience"=>"", "attachment"=>"/uploads/data_attachment/attachment/93/Steps_to_be_done.docx", "message"=>""},"commit"=>"Submit"}
Now a little hack I did today morning that 'forced' it to work for sometime.Not sure, why it worked then and not now.
def application_params
params.require(:application).permit(:user_id, :type_id, :message, :years_of_experience, :attachment)
if params[:attachment].nil?
params.fetch(:application).permit(:user_id, :type_id, :message, :years_of_experience, :attachment)
end
Goal: dynamically update another Model's properties (Tracker) from Controller (cards_controller.rb), when cards_controller is running the def update action.
Error I receive : NameError in CardsController#update, and it calls out the 2nd last line in the
def update_tracker(card_attribute) :
updated_array = #tracker.instance_variable_get("#{string_tracker_column}")[Time.zone.now, #card.(eval(card_attribute.to_s))]
Perceived problem: I have everything working except that I don't know the appropriate way to 'call' the attribute of Tracker correctly, when using dynamic attributes.
The attribute of the Tracker is an array (using PG as db works fine), I want to
figure out what property has been changed (works)
read the corresponding property array from Tracker's model, and make a local var from it. (works I think, )
push() a new array to the local var. This new array contains the datetime (of now) and, a string (with the value of the updated string of the Card) (works)
updated the Tracker with the correct attribute.
With the following code from the cards_controller.rb
it's the if #card.deck.tracked in the update method that makes the process start
cards_controller.rb
...
def update
#card = Card.find(params[:id])
if #card.deck.tracked
detect_changes
end
if #card.update_attributes(card_params)
if #card.deck.tracked
prop_changed?
end
flash[:success] = "Card info updated."
respond_to do |format|
format.html { render 'show' }
end
else
render 'edit'
end
end
...
private
def detect_changes
#changed = []
#changed << :front if #card.front != params[:card][:front]
#changed << :hint if #card.hint != params[:card][:hint]
#changed << :back if #card.back != params[:card][:back]
end
def prop_changed?
#changed.each do |check|
#changed.include? check
puts "Following property has been changed : #{check}"
update_tracker(check)
end
end
def update_tracker(card_attribute)
tracker_attribute = case card_attribute
when :front; :front_changed
when :back; :back_changed
when :hint; :hint_changed
end
string_tracker_column = tracker_attribute.to_s
#tracker ||= Tracker.find_by(card_id: #card.id)
updated_array = #tracker.instance_variable_get("#{string_tracker_column}")[Time.zone.now, #card.(eval(card_attribute.to_s))]
#tracker.update_attribute(tracker_attribute, updated_array)
end
Edit: For clarity here's the app/models/tracker.rb:
class Tracker < ActiveRecord::Base
belongs_to :card
end
Your use of instance_variable_get has been corrected, however this approach is destined to fail because ActiveRecord column values aren't stored as individual instance variables.
You can use
#tracker[string_column_changed]
#card[card_attribute]
To retrieve attribute values by name. If you want to get an association, use public_send. The latter is also useful if there is some accessor wrapping the column value (eg carrierwave)
From your error it seem your issue is this:
#tracker.instance_variable_get("#{string_tracker_column}")
evaluates to this after string interpolation:
#tracker.instance_variable_get("front_changed")
which is incorrect use of instance_variable_get. It needs an # prepended:
#tracker.instance_variable_get("#front_changed")
Seems like using instance_variable_get is unnecessary, though, if you set attr_reader :front_changed on the Tracker model.
I need to modify the issue's start_date and due_date some how,
But I haven't used Rails before, so I don't know how the it run in server,
And I need to implement it in a short time.
So I add these code in the controller,
def date
issue = Issue.find(params[:id])
issue.start_date = params[:start_date]
issue.due_date = params[:due_date]
ntc_str = "Fail to save!" + params[:id]
if issue.save
ntc_str = 'Issue saved!'
end
flash[:notice] = ntc_str;
redirect_to :controller => 'gantts', :action => 'show', :project_id => params[:p_id]
end
It runs when I access it by myself
It always failed and the "ntc_str" always is "Fail to save!" if I use javascript to access it.
For example:
It runs when I input the url "http://xxx.xxx.xxx.xxx/date?id=6&project_id=test&start_date=2016-06-08&due_date=2016-06-30" by hands,
But it failed when I use javascript "window.location.href='/date?id=6&project_id=test&start_date=2016-06-08&due_date=2016-06-30'"
It runs when I input the params in the form I create and click to submit it,
But it failed when I use javascript "document.getElementById('start_date').value = '2016-06-30'; /..../ $('#test-form').submit()"
Could you tell me why it always fails and how can I use the issue model? I have be crazy now.
It would be useful, if you provide some logs with each cases you try.
Also, you can see what goes wrong with issue, when you try to save it, with:
if issue.save
ntc_str = 'Issue saved!'
else
Rails.logger.error(issue.errors.full_messages)
end
I have a rails app hosted on Heroku. Here's the situation: a user should be able to upload a PDF (an instance of Batch) to our app using s3; a user should also be able to take the s3 web address of the uploaded PDF and split it up into more PDFs using HyPDF by specifying the file path and the desired pages to be split out (to create instances of Essay).
All of this is happening in the same POST request to /essays.
Here's the code I've been working with today:
def create
if params[:essay].class == String
batch_id = params[:batch_id].gsub(/[^\d]/, '').to_i
break_up_batch(params, batch_id)
redirect_to Batch.find(batch_id), notice: 'Essays were successfully created.'
else
#essay = Essay.new(essay_params)
respond_to do |format|
if #essay.save
format.html { redirect_to #essay, notice: 'Essay was successfully created.' }
format.json { render :show, status: :created, location: #essay }
else
format.html { render :new }
format.json { render json: #essay.errors, status: :unprocessable_entity }
end
end
end
end
# this is a private method
def break_up_batch(params, batch_id)
essay_data = []
# create a seperate essay for each grouped essay
local_batch = File.open(Rails.root.join('tmp').to_s + "temppdf.pdf" , 'wb') do |f|
f.binmode
f.write HTTParty.get(Batch.find(batch_id).document.url).parsed_response
f.path
end
params["essay"].split("~").each do |data|
data = data.split(" ")
hypdf_url = HyPDF.pdfextract(
local_batch,
first_page: data[1].to_i,
last_page: data[2].to_i,
bucket: 'essay101',
public: true
)
object = {student_name: data[0], batch_id: batch_id, url: hypdf_url[:url]}
essay_data << object
end
essay_data.each {|essay| Essay.create(essay)}
File.delete(local_batch)
end
I can't get the file to show up on Heroku, and I'm checking with heroku run bash and ls tmp. So when the method is run, a blank file is uploaded to S3. I've written some jQuery to populate a hidden field which is why there's the funky splitting in the middle of the code.
Because of Heroku's ephemeral filesystem, I'd highly recommend getting that file off your filesystem as fast as possible. Perhaps using the following:
User uploads to S3 (preferably direct: https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails)
Kick off a background worker to fetch the file and do the processing necessary in-memory
If the user needs to be informed when the file is properly processed, set a "status" field in your DB and allow the front-end app to poll the web server for updates. Show "Processing" to the user until the background worker changes its status.
This method also allows your web process to respond quickly without tying up resources, and potentially triggering an H12 (request timeout) error.
Turns out using the File class wasn't the right way to go about it. But using Tempfile works!
def break_up_batch(params, batch_id, current_user)
essay_data = []
# create a seperate essay for each grouped essay
tempfile = Tempfile.new(['temppdf', '.pdf'], Rails.root.join('tmp'))
tempfile.binmode
tempfile.write HTTParty.get(Batch.find(batch_id).document.url).parsed_response
tempfile.close
save_path = tempfile.path
params["essay"].split("~").each do |data|
data = data.split(" ")
hypdf_url = HyPDF.pdfextract(
save_path,
first_page: data[1].to_i,
last_page: data[2].to_i,
bucket: 'essay101',
public: true
)
object = {student_name: data[0], batch_id: batch_id, url: hypdf_url[:url]}
essay_data << object
end
essay_data.each do |essay|
saved_essay = Essay.create(essay)
saved_essay.update_attributes(:company_id => current_user.company_id) if current_user.company_id
end
tempfile.unlink
end