I have this sort of function in a browser game i'm making :
def sendAllianceInvitationMessage(invited_user, alliance)
subject = 'Alliance Invitation'
body = 'You have received an invitation to join the alliance ' + alliance.name + '.'
body += ' Please visit the Alliance Menu in order to accept or reject alliance invitations.'
current_user.sendMessage(invited_user, subject, body, 'alliance invitation')
end
I'm really not comfortable with the idea of loading the body in this way. Is it possible to have a partial that receives parameters (like alliance.name in this code), produces the body content and pass es it to a string variable to be used in sendMessage?
You can render a partial and do a view to do that
body = render_to_string('send_alliance_invitation_message')
You just need pass your args like a view and you get the result in your body object
Related
Would it be best practice to create some sort of 'general api controller' for shared methods among different models in my RoR application? For example I'm including email validation for Customers - once the user finishes typing in the email address (before submit), an $.ajax POST request is sent to the customers_controller where an external API is being called. After parsing the response I return a response back depending on certain conditions. The validation is handled in real time on the front end before submitting so that the user can know if an email address is valid or not before submitting. The controller method is below.
def validate_email_address
response = ValidateEmailAddressJob.perform_now(params[:email], "Agentapp")
data = JSON.parse response.body
if data['result']['verdict'] == "Valid" || data['result']['verdict'] == "Risky"
html = "<div class='text-success'><i class='fa fa-check'></i> This email appears to be valid</div>"
render json: {html: html, result: data['result']}, status: 200
elsif data['result']['verdict'] == "Invalid"
html = "<div class='text-warning'><i class='fa fa-exclamation'></i> This email may be invalid</div>"
render json: {html: html, result: data['result']}, status: 200
else
render json: {}, status: 503
end
end
I'm trying to keep my code as DRY as possible, so if I wanted to share this email_validation controller method with VendorContacts for example, I'm thinking I could just point the other VendorContact API call to /customers/validate_email_address endpoint even if it's not technically a customer that's needing the validation? Or I could just copy and paste the controller method into the vendor_contacts_controller? Or I could create a separate general api controller with an endpoint such as /validation/emailaddress.
Thanks ahead of time for any help, I'm just trying to learn what the appropriate way to handle this situation would be.
I don't know if this would be considered "best practice" but as a long-time Rails dev, my approach would be to create an EmailController controller, with a single action create, and an Email model (not inheriting from ActiveRecord::Base).
class EmailController < ApplicationController
def create
email = Email.new(params[:email])
if email.valid?
render partial: :valid_email_response
else
render partial: :invalid_email_response
end
end
end
So the Email model has an initialize method, and a valid? method, and the html response is contained in separate view files. Of course, nothing is saved to the database here. The EmailController#create action is invoked any time you wish to validate an email address.
My rationale is that controllers should implement CRUD methods, and in this case a model should handle the validation. I believe this is entirely consistent with the "Rails Way".
IMHO Rails controllers can become catch-all classes for all kinds of application logic, and that coercing the logic into MVC format makes the cleanest code.
i want to pass a query to url like
http:/localhost:3000/saldo/;1010917745800000015?1
in my routes i have:
get 'saldo/:nomor' => 'kartus#show_saldo' , as: :show_saldo
and controller:
def show_saldo
#kartu = Kartu.find_by_nomor(params[:nomor])
end
but instead i get this params
Parameters {"1"=> nil,"nomor"=>";1010917745800000015"}
how can i get my param as {"nomor"=>";1010917745800000015?1"}
<%= link_to 'xyz' show_saldo_path(:nomor => 'nomor', :def => 'def'......) %>
In get everything you passed other than url parameter will become your query parameter. def will become your url parameter. More information here.
? is a special character in urls. If you want to include it in the value of a parameter then you should Uri Encode, eg with CGI.escape(), the parameter before submitting it: this will convert "?" to "%3F", and will similarly convert any other special characters (spaces, brackets etc). So, the parameter that is actually submitted will become "%3B1010917745800000015%3F1".
At the server side, rails will call CGI.unescape on the params, so it should show up in your controller as ";1010917745800000015?1" again.
This should happen automatically with form inputs - ie, if someone writes ;1010917745800000015?1 into a text field then it should actually be sent through as "%3B1010917745800000015%3F1"
If you want people to diagnose why this isn't happening then you should include the html (of the form or link which is submitting this value) to your question.
I am using a form to filter records with fields not linked to an AR object. When form is submitted, I want to show records and populate the form with previously entered values so the user can see filtering parameters.
Form example:
= form_tag businesses_path, method: 'get' do
.field
= label_tag :title, 'Title'
= text_field_tag :title, params[:title]
= button_tag do
'Submit'
I'm thinking of using params to populate form inputs but not sure if it's safe? Or maybe there is a better solution?
Since we're dealing with RESTful interfaces with Rails the params hash is in essence the data in the message between the front end (browser) and the back end. It is there to be used to relay data between the user front end and your controller at the back-end. The params hash is one of the most important and versatile tools in RoR.
From the Rails guide: http://guides.rubyonrails.org/action_controller_overview.html#hash-and-array-parameters
You will probably want to access data sent in by the user or other parameters in your controller actions. There are two kinds of parameters possible in a web application. The first are parameters that are sent as part of the URL, called query string parameters. The query string is everything after "?" in the URL. The second type of parameter is usually referred to as POST data. This information usually comes from an HTML form which has been filled in by the user. It's called POST data because it can only be sent as part of an HTTP POST request. Rails does not make any distinction between query string parameters and POST parameters, and both are available in the params hash in your controller:
So use the params hash; it is a sound method for caching user input and re-displaying it, as was your question.
Caveat
Of course, if you're displaying from the hash and not the database store itself, you may encounter data synchronization problems. But as far as your specific question, I'd say use the params hash without a second thought.
It's absolutely fine. Rails will sanitise anything on it's own. Just don't call params[:title].html_safe when you printing "raw" user input.
You can store that params in a instance variable in respective controller action like flowing in controller.
def test_action
#title = params[:title]
end
And then set #title as field value as flowing
= text_field_tag :title, #title
okay, I'm sure this is simple but I'm running out of hair to pull out. I'm posting a ajax request to my controller and trying to get the response in CoffeeScript. I tried moving to pure JS, but didn't make a difference.
the jQuery document implies that my newImage() should be newImage(data) but if i do that i get the error data undefined. With this code i just get undefined for my alert.
jQuery ->
$('select[data-type=scene]').change ->
i_num= $(this).attr('data-num').toString()
i_value= $(this).find(':selected').text()
request= 'new image for :'+ i_num + ': get :' + i_value + ': image'
$.post('/new_image', {request: => request}, newImage())
newImage= (new_url) ->
alert new_url
the controller is providing a response that i can see in the console, but the ajax callback doesn't seem to grab it.
the controller code is .
def new_image
request= params['request'].split(':')
#url= get_thumb_url(request[3])
#img_num= request[1]
reply= #img_num + '::' + #url
render json: reply, content_type: 'text/json'
end
the response is
3::https://bnacreations.s3.amazonaws.com/g/thumbnails/image.jpg
any suggestions of where i'm off track?
This calls the newImage function while building the argument list for $.post:
$.post('/new_image', {request: => request}, newImage())
# --------------------------------- function call --^^
If you only want to give $.post a reference to a function (which is what you want to do), then leave off the parentheses. Also, $.post just wants some data in the second argument whereas request: => request has a function as the value for request. You probably want this instead:
$.post('/new_image', { request: request }, newImage)
The => (fat-arrow) in CoffeeScript is for defining a bound function, it isn't a Ruby-style hashrocket for building hashes.
BTW, CoffeeScript has Ruby-ish string interpolation so you can say:
request = "new image for :#{i_num}: get :#{i_value}: image"
I have a string template as shown below
template = '<p class="foo">#{content}</p>'
I want to evaluate the template based on current value of the variable called content.
html = my_eval(template, "Hello World")
This is my current approach for this problem:
def my_eval template, content
"\"#{template.gsub('"', '\"')}\"" # gsub to escape the quotes
end
Is there a better approach to solving this problem?
EDIT
I used HTML fragment in the sample code above to demonstrate my scenario. My real scenario has set of XPATH templates in a configuration file. The bind variables in the template are substituted to get a valid XPATH string.
I have thought about using ERB, but decided against as it might be a overkill.
You can do what you want with String's native method '%':
> template = "<p class='foo'>%s</p>"
> content = 'value of content'
> output = template % content
> puts output
=> "<p class='foo'>value of content</p>"
See http://ruby-doc.org/core/classes/String.html#M000770
You can render a string as if it were an erb template. Seeing that you're using this in a rake task you're better off using Erb.new.
template = '<p class="foo"><%=content%></p>'
html = Erb.new(template).result(binding)
Using the ActionController methods originally suggested, involves instantiating an ActionController::Base object and sending render or render_to_string.
I can't say I really recommend either of these approaches. This is what libraries like erb are for, and they've been throughly tested for all the edge cases you haven't thought of yet. And everyone else who has to touch your code will thank you. However, if you really don't want to use an external library, I've included some recommendations.
The my_eval method you included didn't work for me. Try something like this instead:
template = '<p class="foo">#{content}</p>'
def my_eval( template, content )
eval %Q{"#{template.gsub(/"/, '\"')}"}
end
If you want to generalize this this so you can use templates that have variables other than content, you could expand it to something like this:
def my_eval( template, locals )
locals.each_pair{ |var, value| eval "#{var} = #{value.inspect}" }
eval %Q{"#{template.gsub(/"/, '\"')}"}
end
That method would be called like this
my_eval( '<p class="foo">#{content}</p>', :content => 'value of content' )
But again, I'd advise against rolling your own in this instance.
This is also a nice one:
template = "Price of the %s is Rs. %f."
# %s - string, %f - float and %d - integer
p template % ["apple", 70.00]
# prints Price of the apple is Rs. 70.000000.
more here
To late but I think a better way is like ruby-style-guide:
template = '<p class="foo">%<content>s</p>'
content_text = 'Text inside p'
output = format( template , content: content_text )