Access chef resources inside ruby block - ruby

I've been trying to find the answer to this in the chef docs and through Google, but I've not been able to come up with anything. I'm not a ruby guy (yet), so the answer to this might stem from my approaching the problem with "just enough ruby for Chef". Here's what I want to do: in my deploy resource, in the before_migrate attribute, I want to execute a resource in my current recipe. What I am doing currently is to just stuff the resource into the block itself, but I know there must be a better way to do it.
before_migrate do
template "#{app_root}/#{applet_name}/local_settings.py" do
source "local_settings.py.erb"
owner app_config['user']
group app_config['group']
variables(
:database_name => app_config['postgresql']['database_name'],
:user => app_config['postgresql']['user'],
:password => app_config['postgresql']['password']
)
action :create
end
end
What I'm aiming for is something like
before_migrate do
"template #{app_root}/#{applet_name}/local_settings.py".execute
end
So I can re-use that template code. Thanks!

You could specify the resource outside of the "deploy" resource with an action of nothing and then, in the *before_migrate* do something like:
before_migrate do
ruby_block "notify_template" do
block do
true
end
action :create
notifies :create, "template[#{app_root}/#{applet_name}/local_settings.py]", :immediately
end
end
That way, you can notify it when you need it.

Thanks to the great guys in the #chef IRC channel, I solved my problem. The notification resource needs to be accessed directly, using
Chef::Resource::Notification.new("template[#{app_root}/#{applet_name}/local_settings.py", :create)
Which will notify the template resource to run the :create action.

Related

Creating a custom view

I am trying to create a landing page for an event for people to visit to see the events details. I have created the view, added a route to the event resources and made changes to the controller but something has been done incorrectly.
Here is my code:
routes.rb:
resources :events do
resources :guests
match '/landing_page', to:'events#landing_page', as: :landing_page, :via =>[:get, :post]
# resources :guestlists
end
event_controller:
def landing_page
#event = Event.find(params[:id])
end
When I open the landing page i get the following error:
"ActiveRecord::RecordNotFound (Couldn't find Event without an ID):"
In case anyone else runs into this, I wanted to document Sergio's last comment here which I believe leads to the outcome I think most people will be looking for. Nesting this inside of a member block should get you an ideal outcome:
resources :events do
member do
get :landing_page
end
end
Running rake routes should now show /events/:id/landing_page(.:format) so you can use the same method you use in your show method that just asks for params[:id].
I was wracking my brain for a while on this as rails resources seem to be dwindling on the interwebs.

Welcome emails in Ruby

I'm using Ruby and Devise:Confirmable. A day or so after a new user has registered and confirmed a new trial account we'd like to automatically send him or her a 'follow up email'. Is this something we should also do through devise, or is there a separate gem or process we should implement?
Since you are using Devise already, you can just overwrite the confirmation controller, try something like this.
class ConfirmationsController < Devise::ConfirmationsController
# GET /resource/confirmation?confirmation_token=abcdef
def show
super do |resource|
YourMailerClass.follow_up(resource).deliver_later(wait_until: 1.day.from_now) if resource.errors.empty?
end
end
end
You also need to update the routes.rb file, add the option controllers: { confirmations: :confirmations } at the end of the line where you define devise_for (restart your server after this).
I'm assuming you already have a background jobs proccesor, like sidekiq
Hope it helps

Send variable from one Chef recipe to another in order to trigger a resource block

In one recipe I have a rubyblock that ultimately obtains the port of a service that I'd like to restart.
Individually the recipes work fine and I am now trying to tie the two together.
I cannot seem to pass the variable to the other recipe having tried to follow a custom resource example.
my default recipe that obtains the port is:
Chef::Log.info("Port: #{port}")
Chef::Resource::Notification.new("stop-solr_#{port}", :run, self)
I'm trying to trigger the resource block of the name 'stop-solr_'portNumber'' using the notification sender.
My other recipe looks like the following and has a start/stop service purpose
solrCore = "solr_#{port}"
#define the service - does nothing
service solrCore do
action :nothing
end
#do something that triggers
execute "start-solr_#{port}" do
Chef::Log.info('triggers start')
action :nothing
notifies :start, run_context.resource_collection.find(:service => "#{solrCore}")
end
execute "stop-solr_#{port}" do
# some stuff
# on success...
Chef::Log.info('triggers restart')
notifies :stop, run_context.resource_collection.find(:service => "#{solrCore}"), :immediately
notifies :run, "execute[start-solr_#{port}]"
end
My main problem (I think) is that the variable solrCore uses 'port' which I cannot seem to obtain.
Is anyone able to help with what I need ot do in order to get this working?
Thanks in advance.
Variables in Ruby are local by default. You would have to use a global variable to share state between files, either a real Ruby global variable ($foo) or using the global node.run_state hash we expose to all recipes.
That said: there is a reason that mutable global variables have been a CS cliché for decades. Code like this is very fragile and difficult to debug. I would consider turning both of those recipes into custom resources and calling them from the same recipe with the same input port.
In the first recipe, you can save information in the node.
Sample:
node.normal['A']['B']['C']="completed"
node.save
and In second Recipe you can retrieve information from the node.
status=node.normal['A']['B']['C']
and based on the retrieved value you can take action

URL Rewrite Ruby on Rails

We have a Redmine installation on an old server and moved it to a new one with a new domain. Problem is, we need to redirect urls from the old domain to the new one. I really don't have much knowledge about ruby. I was thinking redirecting URLs on this one is as easy as some rewrite rules with .htaccess but I found it different. I've read some answers here redirect but can't figure out where to put those codes.
The scenario should be like:
from http://www.old-domain.com:3000/issues/3456
should be redirected to http://www.new-domain.com:3000/issues/3456
Can anyone help me how to do this? Or if you have better idea how to achieve this?
I'm planning on reading some ruby guides for the meantime.
Thanks guys!
Update:
I managed to create a simple redirect by doing the following:
I created a controller redirect_controller.rb:
class RedirectController < ApplicationController
before_filter :show
def show
redirect_to "http://www.new-domain.com:3000/", :status => :moved_permanently, :notice => "Notice: A redirect!!!"
end
end
And added this to routes.rb:
map.connect '/', :controller => 'redirect'
But I only managed to redirect the page after a successful login. How can I redirect all pages to the new one retaining parameters such as /issues/3456 if there are any?
You can go to your application.rb file (I found it better than place the redirection in the application controller), which is loaded to start all the rails and all engines. The key here is to use
head :moved_permanently, :location => "http://www.newdomain.com/"
To call that you can wrap it in a method I found in a blog. I added some comment
def perm_redirect_to(options)
url = case options
when String # if you pass a string url, which is your case
options
else
url_for(options) # if you pass some more complex option hash in
# `options`, which doesn't seem to be your case
end
head :moved_permanently, :location => url
end
You can call this method passing your url perm_redirect_to(your_new_url)!

Padrino, name route differently from path?

I want to be able to follow a convention closer to what Rails does with resourceful routing. For example, I'm considering "signups" to be a resource, with it's own controller containing "new" and "create" actions.
In app/controllers/signup.rb I have:
MyApp.controllers :signups do
get :index do
# ...
end
post :index do
# ...
end
end
Is there any way I can use these route names, while actually responding on a path other than '/signups'? It feels like Padrino's route naming system is very tightly coupled with the URLs the routes map to.
I've tried:
MyApp.controllers :signups, :map => '/another-path' do
# ...
end
Among various other things without success. Perhaps I should just go back to using Rails... I was just getting frustrated with the startup overhead in TDD and I'm embarking on a new project at the moment (please don't refer me to Spork... that has it's own issues).
This is how I would do what you are asking
# in app/controller/signups.rb
MyApp.controllers :'another-path' do
get '/' do
# ...
end
end

Resources