Rails Database Query - mysql

I am trying to gather information from a database and then pass that information on to my view via flash. Unfortunately the information is formatting in an ActiveRecord::Relation and not in any format that I can read.
Controller Query
#message = Message.where(:all).limit(4).order(id: :desc).only(:order,:where)
flash[:response] = #message
redirect_to (:back)
If I do something like
#message = Message.where(:all).limit(4).order(id: :desc).only(:order,:where)
flash[:response] = #message.first.mess
redirect_to (:back)
To try and get the first returned value in the mess column, I get an undefined method error. I have been trying to find a tutorial that tells me how to take information once my query has been run but I have not had much luck with Rail's tutorials as of late. I appreciate any help that you guys can give. After I do this I am going to try to format the 4 different results on the view side.

List of messages:
#messages = Message.order(id: :desc).limit(4)
This: only(:order,:where) cancels your limit(4) (why?)
#messages is now an activerecord association, not suitable to output.... So, if you have 4 messages top you can do:
if #messages.any? # maybe no messages come out
flash[:response] = #messages.map(&:mess).join('<br>') # add an html newline between them
end
redirect_to :back

Related

Rails massive data upload and nested records

I have to update a lot of data to mysql (~100Mio records!). Some records already exists, some have to be created. I also have to create some nested resources for each record.
I know the activerecord-import gem but as far as i know it can't handle nested records (or only with ugly workarounds). The issue is that I dont know the ID's for all nested records before they are created - and creating them in single queries takes time.
So lets say there is a model called Post and can have many Comments. My current code looks like this:
Post.transaction do
import_posts.each do |import_post|
post = Post.find_or_initialize_by(somevalue: import_post['somevalue']
post.text = import_post['text']
import_post['comments'].each do |import_comment|
comment = post.comments.find_or_initialize_by(someothervalue: import_comment['someothervalue'])
comment.text = import_comment['text']
end
post.save(validate: false) #Dont need validation - saves some time
end
end
This is just an example and it works but its far away from 'damn fast'. Are there any ideas how to speed up the data upload? Am I totally wrong?
Im working with Rails5 and ruby 2.4.
Thanks in advance!

Passing parameters from form to controller using RoR

I am new to RoR development and am a little confused about how parameters are passed from a HTML view to the controller. I have seen a few examples online which use a private method like this:
private
def message_params
params.require(:message).permit(:content)
end
I have been looking for some clarification online as to what this method does and how it works, but I only encounter posts/articles which use the method rather than explain what it does.
I was hoping someone could explain how the method takes(/filters?) values passed via the form via a POST request, what the require and permit keywords mean and how would i change this method to fit my own use.
For example if i needed to get data about a new book would i do this:
private
def book_params
params.require(:book_name).require(:ISBN).require(:Author).permit(:Illustrator)
end
Would the above be valid given that my book object has those fields?
Any clarification would be appreciated.
Thank you.
here is some info (I'm using your sample model Book and BookController), that probably can help you more understand
when you submit form, rails automatically called create method, inside create method you will see Book.new(book_params), book_params will call private method and will check which field allowed, if there is another field that submitted but not listed inside your permit block then it will be not passed along to save command
class BooksController < ApplicationController
def create
#book = Book.new(book_params)
if #book.save
flash[:success] = 'Data save successfully'
redirect_to books_path
else
render :new
end
end
private
def book_params
params.require(:book).permit(
:book_name,
:isbn,
:author,
:illustrator)
end
end
This kind of function is used to whitelist params - ie say you have a message model, and through the controller actions you should only be able to change the content. Maybe there is also an author field - but even if someone were to pass that through the form, you would not want to update it.
params.require(:message)
Will return to you params[:message]. permit means you are allowing only the content field through.
See: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters
I would need to see your model setup, but I would assume given a book model you'd want something more akin to:
params.require(:book).permit(:illustrator, :author, :isbn)

How to automatically save data from API - Ruby on Rails

I have searched all over the internet, however, I cannot seem to get a clear answer on this issue. I am using Block.io API to add Bitcoin payments to my app. I receive a JSON hash which includes a new Bitcoin address for each payment, I can extract the bitcoin address, but I need it to save to my database automatically, when a user accesses a specific page the address will also be generated on that page. I am using Postgresql
The JSON looks like this:
{"status"=>"success", "data"=>{"network"=>"BTCTEST", "address"=>"2MstFNxtnp3pLLuXUK4Gra5dMcaz132d4dt", "available_balance"=>"0.01000000", "pending_received_balance"=>"0.00000000"}}
I have a controller which calls the API to generate the address:
class PaymentsController < ApplicationController
def index
#new_address = BlockIo.get_new_address
end
end
And the bitcoin address is displayed using:
<%= #new_address["data"]["address"] %>
I am thinking of creating a new function that will save the bitcoin address to the database and map the route to execute this function upon accessing the specific page, something like:
Controller:
class PaymentsController < ApplicationController
def create
#new_address = BlockIo.get_new_address
## I need assistance with the rest to auto save
end
end
routes:
match '/save_btc' => 'payments#create', via: [:get, :post]
when someone opens domain.com/save_btc the bitcoin address needs to be automatically saved to the database.
I have already generated the following migration
rails g model Payment bitcoin:string
Any comments or assistance will be greatly appreciated.
It looks like BlockIo is already parsing the JSON string for you and returning a regular Ruby hash.
I would try something like this:
new_address = BlockIo.get_new_address
Payment.create( bitcoin: new_address['data']['address'] )
You'll probably want to check the status of the response new_address['status'] and make sure that the address is present before saving. But the code above should get you started.
You'll probably want to do a redirect or something like head :ok after the payment is created.
Note: you do not need to use the # for the variable name. That is usually only used when you're passing that info to a view.

rails with MySQL AND a small redis store

I've got a Rails 3.1 app running a mysql server for storing data.
90% of the data in the app fits really well in a relational database.
The other 10% is a pretty large hash that I need to pull out, change, and put back fairly quickly. It is a fairly large query in mysql to bring all these data pieces together, across multiple tables, but once I have it once, I figured I would save it as a hash, and the user can interact with the hash and make changes. Those changes never get persisted back to mysql, as mysql doesn't need them.
so, I decided to add redis to my rails application and the redis-objects gem was recommended by a friend.
I have created my active_hash model and controller as so
class ActiveHash < ActiveRecord::Base
include Redis::Objects
end
class ActiveHashesController < ApplicationController
def show
#this is a big query with a bunch of merges, but simplified here as it isn't important
active = Game.find(params[:id])
active_hash_in_redis = ActiveHash.new()
if active_hash_in_redis.save
render :json => active_hash
else
render :text => "didn't save"
end
end
end
when I navigate to active_hashes/id, I get an error that there is no MySQL table active_hashes, which is right, because that is supposed to be my redis db, as defined in the model.
can anybody explain to me how to use both dbs in my app, and/or point me to a tutorial on doing this? I haven't been able to find anything. Is using Redis-Objects the wrong way to go with this?? Any other recommendations?
It turns out this was a bit of confusion on my part, but hopefully this helps somebody else.
I didn't end up using the redis-objects, gem, I installed redis-rb with gem redis.
Then I set-up the config file as
require 'redis'
$redis = Redis.new()
My model is actually blank at the moment, in my controller, I've used
class ActiveHashesController < ApplicationController
def show
#this is a big query with a bunch of merges, but simplified here as it isn't important
active = Game.find(params[:id])
$redis.set params[:id], active.to_json
get_game = $redis.get params[:id]
render :json => get_game
end
end
end

Can't access rails post data

I've spent the last couple of hours slowly losing my mind while trying to figure something out. I'm submitting a form in rails, everything works fine until I try to access the params. In the console I can see the following:
Parameters: {"authenticity_token"=>"3mdEW2lHhkzpZbDsJCu8ZEV/wbq2YB/ztNR0RLTMZDs=", "utf8"=>"✓", "project"=>{"name"=>"woeij", "client"=>"iwej", "description"=>"oiejdoiew woeij"}, "id"=>"13"}
As you can see I'm sending name, client, description and id. I can access ID fine with something like:
#id = params[:id]
However, when I try to access name, client, or description in the same way they're all empty.
If I do:
#project = params[:project]
I get:
namewoeijclientiwejdescriptionoiejdoiew woeij
Would someone mind explaining what I'm doing wrong? And why I can't just get "woeij" when I do:
#name = params[:name]
Sorry for the stupid question, big thanks as always.
Attributes are nested, do
params[:project][:name]
to retrieve name.
A really cool tool in the rails console is the y: if you type y params they'll be presented really nicely.
You have a hash inside a hash. After you do:
#project = params[:project]
You have all your project parameters inside that hash. You can select them like this:
#project[:name] #=> "woeij"
#project[:client] #=> "iwej"
You can also select them in one go like this:
params[:project][:description] #=> "oiejdoiew woeij"