Ruby on Rails Routing Similar Pages but different controllers - ruby

I'm manually writing on my routes file to redirect a 'post' request to a different action
Is there anyway to group them into 1-2 lines?
For example on my routes file, I have the following code
post "/users/new" => "users#create"
post "/users/edit/:id" => "users#update"
post "/user_data/new" => "user_data#create"
post "/user_data/edit/:id" => "user_data#update"
post "/status/new" => "status#create"
post "/status/edit/:id" => "status#update"
These are just a few and I have more than 10 controllers that uses these lines to redirect the 'new' post request to the 'create' action and the 'edit' post request to the 'update' action.
I keep repeating the same line and is there a way to create a line such like the default:
match ':controller(/:action(/:id(.:format)))', :via => [:get, :post]
something like:
match post :controller/new => ":controller#create"
match post :controller/edit/:id=> ":controller#update"

I think I found the answer on the docs:
The code I used is:
match ':controller(/new)' => '(:controller)#create', via: [:post]
match ':controller(/edit(/:id))' => '(:controller)#update', via: [:post]
In case somebody needs a sample.

Related

Mailgun::CommunicationError via nginx '301 Moved Permanently' error

I have a Ruby web app that sends email via Mailgun.
My Mailgun account & gem are properly set up and I can send emails manually (via curl, for instance).
The API key and the API base URL (https sandbox domain) are stored in environment variables.
When I attempt to send emails from the app like this:
def initialize(mailer: nil)
#mailer = mailer || Mailgun::Client.new(ENV['MAILGUN_API_KEY'])
end
then:
def call(user)
mailer.send_message(ENV['MAILGUN_SANDBOX'], {from: '...',
to: user.email,
subject: '...',
text: "..."})
end
When I run the app with Sinatra via localhost:xxxx, I get a Mailgun::CommunicationError at /.../... 301 Moved Permanently: ... nginx pointing to this line:
mailer.send_message(ENV['MAILGUN_SANDBOX'], ...
Any idea why that happens? I've researched the issue for hours but couldn't find a clue on what to do next.
Thanks!
I ran into this same issue. If you have already fixed this then hopefully this can help someone else.
I switched over to message builder for ease of use and being able to render my html but I'm pretty sure it will still send with the format you have setup with :text
When I switched over to the proper domain in the .env file I believe it solved my issue. You'll need 2 different domains to use Mailgun. The first is the full domain for your sandbox. ENV['MAILGUN_DOMAIN'] it is the sandbox domain with the full https://api.mailgun.net/v3/sandboxXXXXxxxXXXXXX.mailgun.org to send most of the mail formats.
You'll also need the last half of the full domain to send messages. That's just the sandboxXXXXxxxXXXXXX.mailgun.org which is passed into the MessageBuilder or other message .send_message method. When I had them mixed up or both the same I kept on getting this error. When I switched over to separate the two in my development.rb and some_mailer.rb is when I could send the mail without a problem.
Below is my file setup, for reference. I'm pretty new to all of this but this is how I'm setup and it's working for me so hopefully it helps.
# .env
MAILGUN_DOMAIN='https://api.mailgun.net/v3/sandboxXXXXxxxXXXXXX.mailgun.org'
MAILGUN_SEND_DOMAIN='sandboxXXXXxxxXXXXXX.mailgun.org'
# development.rb
ActionMailer::Base.smtp_settings = {
:authentication => :plain,
:address => "smtp.mailgun.org",
:port => 587,
:domain => "ENV['MAILGUN_DOMAIN']",
:user_name => "ENV['MAILGUN_USERNAME']",
:password => "ENV['MAILGUN_PASSWORD']"
}
# some_mailer.rb
def some_mail_notification(user)
#user = user
mg_client = Mailgun::Client.new ENV['MAILGUN_KEY']
mb_obj = Mailgun::MessageBuilder.new
mb_obj.from "email#testing.com", {'first' => 'Customer', 'last' => 'Support'}
mb_obj.add_recipient :to, #user.email, { 'first' => #user.first_name, 'last' => #user.last_name }
mb_obj.subject "Your Recent Purchase on Some Site"
mb_obj.body_html ("#{render 'some_mail_notification.html.erb'}")
mg_client.send_message("sandboxXXXXxxxXXXXXX.mailgun.org", mb_obj)
end
I left the send_message above to the sandbox domain but you can set that as an environment variable in the .env file.

Complex soap_header xml objects for ruby savon gem

Working on a project with this WSDL: http://developer.ebay.com/webservices/latest/ebaysvc.wsdl
$client = Savon.client(
:wsdl => "http://developer.ebay.com/webservices/latest/ebaysvc.wsdl",
:endpoint => "https://api.sandbox.ebay.com/wsapi?callname=AddItem&siteid=0&version=733& Routing=new",
:headers => { "Content-Type" => "application/soap+xml", "SOAPAction" => "AddItemRequest"},
:namespace => "urn:ebay:apis:eBLBaseComponents",
:soap_header => { CREDENTIALS GO HERE: SEE BELOW }
)
What I need is a complex type xml format. Where the first part of soap_header is RequestCredentials and has several child nodes, and one of those (Credentials) has 3 child nodes... I also need to escape the lower camel case and just use camel case.
The final result with the xml output should look something like:
<urn:RequestCredentials>
<urn:eBayAuthToken>
AUTH TOKEN HERE
</urn:eBayAuthToken>
<urn:Credentials>
<urn:DevId>DEVID HERE</urn:DevId>
ect..... (two more child nodes (AppId, and AuthCert)
</urn:Credentials>
</urn:RequestCredentials>
Here is the error I receive:
14007
Error
SOAP Authentication failed due to missing or invalid security header.
Any ideas on how to correctly format the xml with the savon gem?

Route not found when using Devise's devise_scope

I am using devise for authentication in my app. My routes file look like this:
devise_scope :user do
get "/password_reset" => "devise/passwords#new", :as => "new_user_password"
post "/password_reset/complete" => "devise/passwords#create", :as => "user_password"
get "/password_renew" => "devise/passwords#edit", :as => "edit_user_password"
put "/password_renew/complete" => "devise/passwords#update", :as => "password"
end
The full routes.rb file: http://hastebin.com/vofaluhera.coffee
running rake routes show that these route work well:
new_user_password GET /password_reset(.:format) devise/passwords#new
user_password POST /password_reset/complete(.:format) devise/passwords#create
edit_user_password GET /password_renew(.:format) devise/passwords#edit
password PUT /password_renew/complete(.:format) devise/passwords#update
However when I visit route /password_reset it rases this error:
Could not find devise mapping for path "/password_reset"
Also when I switch to devise_for it work fine but with a deprecation warning and it adds more unwanted routes. So basically, I want to stick with devise_scope
Please help me fix this errors.
Edit:
It turns out that I need to add before using devise_scope
devise_for :users, :skip => [:passwords]

HTTParty options parameter not functioning properly

I'm setting up an application which can make LastFM API Requests.
These are simple get requests and I'm using the HTTParty gem.
My function is as follows:
def get_albums
self.class.base_uri "http://ws.audioscrobbler.com/2.0/"
options = {
:user => "Gerard1992",
:method => "user.gettopalbums",
:api_key => Constants::LASTFM_API_KEY,
:format => "json"
}
puts options.to_query
self.class.get "/?#{options.to_query}", {} #options don't work
end
This piece of code that's shown above works. The get request returns a set of JSON. My problem is that this /?#{options.to_query} doesn't look that neat. And neither does the actual (now empty {}) options parameter. How do I get the HTTParty options parameter to work like it should?
This is what I've tried, but both cases failed:
self.class.get "/", options
self.class.get "/", options => options
I appreciate the help.
The correct option for query parameters in HTTParty is :query, so what you want is:
self.class.get "/", query: options
You can see all the available parameters in the docs.
Send :verify => false in options hash

Specify token options for OmniAuth OAuth2 based strategy

I'm creating custom strategy for Nimble.com API. As they're using OAuth, it's pretty simple.
require 'omniauth-oauth2'
module OmniAuth
module Strategies
class Nimble < OmniAuth::Strategies::OAuth2
option :name, "nimble"
option :client_options, {
:site => "https://api.nimble.com",
:authorize_url => '/oauth/authorize',
:token_url => '/oauth/token'
}
# option :access_token_options, {
# :mode => :query,
# :param_name => :access_token
# }
option :provider_ignores_state, true
uid { raw_info['email'] }
info do
{
'uid' => raw_info['email'],
'name' => raw_info['name'],
'email' => raw_info['email']
}
end
extra do
{ 'raw_info' => raw_info }
end
def raw_info
access_token.options[:mode] = :query
access_token.options[:param_name] = :access_token
#raw_info ||= access_token.get('/api/users/myself/', {:parse => :json}).parsed
end
end
end
end
For passing tokens, they need to use access_token parameter in URL. When I specify options in raw_info function directly, as in sample — it's OK.
When I'm trying to specify this options in access_token_options hash (like in commented section) — parameters aren't passing to token. I'm not very good in Ruby, so I didn't figure out from libraries sources — how correctly pass parameters to access_token in OmniAuth OAuth2 descendants.
I'd like to make it "right way", so access_token initialised with correct options, plese someone point me the right way.
Thank you!
I've explored several existing strategies (GitHub, 4SQ), and looks like it's normal practice to directly modify access token options.
So I'll stay with it :)

Resources