How to handle dependencies in puppet from parent class - include

Main problem: I have some dynamic code in parent class, in subclass I am including additional resource. I want to add the resource to catalog from child before executing parent level.
Could you propose me good dependency command or a tip how to write it another way.
Sample code may be helpful here.
Manifest file
class class1 {
file {'C:/Temp/test1':
content => 'test1',
}
}
class parent {
file {'C:/Temp/test2':
content => template('parent/test2.erb')
}
}
class parent::child {
file {'C:/Temp/test3':
content => 'test3'
}
}
Class['class1']->Class['parent::child']
include class1
include parent::child
test2.erb
<% scope.catalog.vertices.each do |resource| -%>
<%= resource -%>
<% end -%>
Result: test2
Stage[main] Class[Settings] Class[main] Class[Class1] File[C:/Temp/test1] Class[Parent]
I want it also to include
File[C:/Temp/test3]

It is not answer, since I didn't get all information for your question.
First I simplify your code, if you think that makes sense, we can start the discussion from it.
Manifest file:
class class1 {
file {'C:/Temp/test1':
content => 'test1',
}
}
->
class parent {
file {'C:/Temp/test2':
content => template('parent/test2.erb')
}
}
include class1
include parent
test2.erb
<% scope.catalog.vertices.each do |resource| -%>
<%= resource -%>
<% end -%>

Related

Rendering partial template after redirect to another url

My goal is to display a welcome message for the user after they create a new account and are redirected to their profile page; i.e., have the message be displayed on their profile page.
With the following code, I'm able to display the message but only for a split second - before the redirect occurs, which is nevertheless successful.
In my controller, I create the message and use an Ajax call to render my JavaScript template:
def create_user
# ...
#welcome_msg = "WELCOME"
format.js { render template: "layouts/message.js.erb" }
# ...
end
message.js.erb
$(window.location.replace("<%= profile_url %>"));
$("#welcome_message_placeholder").html("<%= j render partial: 'layouts/welcome_message', locals: { :user => #user, :welcome_msg => #welcome_msg } %>");
_welcome_message.html.erb
<%= #welcome_msg %>
application.html.erb
<div id="welcome_message_placeholder"></div>
What do I need to add/change to ensure that the user sees the message only after being redirected?
Turns out that one way to do this involves a slightly different approach from what I had above.
What I did (and what worked, thankfully) was I created a new flash type in my users controller that I then defined in all of my controllers (to avoid it being undefined in my application template) like so:
add_flash_types :custom_notice # included in all controllers
def create_user
# ...
format.js {render js: "window.location.href='#{profile_url}'"} # to replace message.js.erb
flash[:custom_notice]="WELCOME"
# ...
end
Now the message can essentially be treated as a traditional notice in the base template, and the partial can be rendered directly (without a JS template middleman):
application.html.erb
<% if custom_notice %>
<%= render partial: "layouts/welcome_message" %>
<% end %>
_welcome_message.html.erb
<%= custom_notice %>
Note that add_flash_types (registering custom flash types) isn't supported in Rails 3.

Not showing created blog entries

I'm fairly new to Rails and learning to create a blog using this tutorial. On step 10, once I define create and show, after creating a new post in browser I don't see any entries on show with id page. All I see is heading and and blank title and post header.
Following is my controller -
class PostController < ApplicationController
def index
end
def new
end
def create
#post = Post.new(params[:posts])
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
end
Show view ---
<h1>Show a post</h1>
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
Route ---
RailsBlog::Application.routes.draw do
resources :post
root :to => "post#index"
end
Form ---
<%= form_for :post, url: {action: 'create'} do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit 'Submit' %>
</p>
<% end %>
May be this is just a spelling mistake, but since I've recently started learning Rails, I'm unable to resolve this.
Update: I can go to particular id using
http://localhost:3000/post/1
but am only seeing blank page with view headers
The problem is here:
#post = Post.new(params[:posts])
It should be params[:post] - singular, not plural.
Also note that the best practice with form_for is to pass an object instead of symbol:
form_for #post do |f|
Then:
You don't need to specify url
You can reuse the same form for an edit action or create action (if object creation failed due to failing validation)
This however requires to initialize new object in your new action:
def new
#post = Post.new
end
UPDATE:
Also your routes are incorrect. When defining plural resources, you need to use plural form (it's more the convention than requirement, but since you're learning stick with it). So change your routes to:
resources :posts
And rename your controller to PostsController (remember to rename file name as well). restart the server and all should work.
ANOTHER UPDATE:
You also need to rename folder app/views/post to app/view/posts.
AND YET ANOTHER UPDATE:
In rails 4, you are not allowed to mass assign any params which has not been whitelisted using strong parameters. You need to tell rails which fields you allow to be assigned first - this is a security thing. You need to make some changes to your controller:
class PostsController < ApplicationController
...
def create
#post = Post.new(post_params)
...
end
...
private
def post_params
params.require(:post).permit(:title, :text)
end
end
This is the way to tell your controller that you are expecting those attributes from your form and they can be safely assigned.
I had just similar problem on the same tutorial.
The code spelling was correct and clearly accorded to examples in tutorial and BroiSatse's answer above.
The mistake was in order of private method definition.
How it was:
...
private
def post_params
params.require(:post).permit(:title, :text)
end
def show
#post = Post.find(params[:id])
end
...
The working order:
def show
#post = Post.find(params[:id])
end
private
...
Anyway, this topic was rather helpful. Thak you for your answers!

Rails 4: Routing and sharing actions between controllers? What's the proper convention?

I'm building a Todo list in rails trying to learn how it all works. I'm having an issue with calling the action of a controller from the view of another controller.
I have a TodoList has_many TodoItem and TodoItem belongs_to TodoList.
TodoList#Model
has_many :todo_items
def has_completed_items?
todo_items.complete.size > 0
end
def has_incompleted_items?
todo_items.incomplete.size > 0
end
TodoItem#Model
belongs_to :todo_list
scope :complete, -> { where("completed_at is not null") }
scope :incomplete, -> { where(completed_at: nil) }
def completed?
!completed_at.blank?
end
Routes
resources :todo_lists do
resources :todo_items do
member do
patch :complete
end
end
end
Patch generates this route:
complete_todo_list_todo_item PATCH
/todo_lists/:todo_list_id/todo_items/:id/complete(.:format)
todo_items#complete
Now I can call this path from my TodoItem views without a problem like this: <%= link_to "Mark", complete_todo_list_todo_item_path(todo_item), method: :patch %>
After adding complete/incomplete scope to my TodoItem I added the following to my TodoList show view:
TodoList#Show
<% #todo_list.has_incompleted_items? %>
<% #todo_list.todo_items.incomplete.each do |item| %>
<li><%= item.content %></li>
<% end %>
This is properly displaying the incomplete items, so I tried to put a link to mark the item complete from within this view like this:
<% #todo_list.has_incompleted_items? %>
<% #todo_list.todo_items.incomplete.each do |item| %>
<li><%= item.content %>
<%= link_to "Mark", complete_todo_list_todo_item_path(item), method: :patch %></li>
<% end %>
Now this is where I get the following error:
NoMethodError in TodoLists#show undefined method
`complete_todo_list_todo_items_path' for #<#:0x000001071cf540>
Why is this complete#action undefined from my TodoList#show view?
What is the proper convention to share actions between controllers?
Thank you for your help.
I was able to solve this problem by removing the member block from the routes file:
resources :todo_lists do
resources :todo_items do
patch :complete
end
end
Now my action route was updated to: todo_list_todo_item_complete
So from my view I had to call the new route with it's nested resource:
link_to "Mark", todo_list_todo_item_complete_path(#todo_list, item), method: :patch
Lastly I had to update my controller to locate the proper todo_item#id in the complete block:
#todo_item = #todo_list.todo_items.find(params[:todo_item_id])

Multiple Contact Forms - Rails 3

I am relative newbie to all this, so sorry if this sounds mad!
I have used this tutorial: http://www.railsmine.net/2010/03/rails-3-action-mailer-example.html
And I have a new contact form working great.
The controller is at app/controllers/support_controller.rb
class SupportsController < ApplicationController
def new
# id is required to deal with form
#support = Support.new(:id => 1)
end
def create
#support = Support.new(params[:support])
if #support.save
redirect_to('/', :notice => "Support was successfully sent.")
else
flash[:alert] = "You must fill all fields."
render 'new'
end
end
end
And the model at /app/models/support.rb
class Support
include ActiveModel::Validations
validates_presence_of :email, :sender_name, :support_type, :content
# to deal with form, you must have an id attribute
attr_accessor :id, :email, :sender_name, :support_type, :content
def initialize(attributes = {})
attributes.each do |key, value|
self.send("#{key}=", value)
end
#attributes = attributes
end
def read_attribute_for_validation(key)
#attributes[key]
end
def to_key
end
def save
if self.valid?
Notifier.support_notification(self).deliver!
return true
end
return false
end
end
The views however only work in views/supports/new.html.rb (rendered - views/supports/_form.html.erb)
So I can call the Model / Controller from localhost:3000/support/new but if I try and render the same form in another view from the root directory e.g. app/view/contact.html.erb I get:
undefined method `model_name' for NilClass:Class
I think this is because it is calling the support model away from the supports directory.
Do I have to create an instance on #support so it can be called? If so what is the best way of doing that? I think I am nearly there. I just want the contact form on multiple pages not just in suppport/new
Thanks
Charlie
Yes, you would need to create a #support variable in each action you wish to render your form.
Another option would be to refactor the form to take a parameter, that way you're a bit more flexible. For example, from your view:
<%= render :partial => "supports/form", :locals => {:support => #support} %>
Now, instead of referring to #support in your _form.html.erb, you'd refer to simply support as it's a local_assign.
Yet another option would be to refactor the form a little further, and worry about creating the actual form tag outside of the partial.
Such as:
app/views/supports/new.html.erb
<%= form_for #support do |form| %>
<%= render :partial => "suppports/form", :object => form %>
<% end %>
app/views/supports/_form.html.erb
<%= form.text_field :foo %>
<%= form.text_field :bar %>
...
In this case, when you render a partial with the object option, you will get a local variable in your partial with the same name as the partial. You maintain a little bit more flexibility in the path of your form, but can still render the meat of what a Support object is inside of the form while remaining consistent across your app.
To clarify, you could use this somewhere else by doing something like:
app/views/foos/_create_foo_support.html.erb
<%= form_for #foo.support do |form| %>
<%= render :partial => "supports/form", :object => form %>
<% end %>
You have to pass #support object wherever you use your contact form. It's working in SupportsController#new because you initialize the variable there. In all other places where you want to use the form, you'll have to do the same.

How to check for resource file existence at run-time [grails]?

I need to test whether a resource file (an image, for instance) exists and if not, I will display another image.
My GSP view code looks like:
<% if (resExists(dir: "images", file:"img.jpg")) {%>
<img src="${g.resource(dir:'images',file: 'img.jpg')}">
<% else { %>
<img src="${g.resource(dir:'images',file: 'noimg.jpg')}">
<%}%>
How can I test for a file existence in Grails? What is the code of the method boolean resExists()
I found out the answer:
def resExists(resPath) {
def resFile = grailsApplication.parentContext.getResource(resPath)
resFile?.exists()
}
or
def resExists(resPath) {
def resFile = request.servletContext.getResource(resPath)
resPath
}
And you call it with resExists('images/img.jpg')
I've done the following in GSP:
<g:set var="flag" value="${new File(grailsApplication.mainContext.servletContext.getRealPath("images/sgs-geosol/sign/${sec.username()}.gif")).exists()}"></g:set>
<g:if test="${flag}">
</g:if>
The code below returns the real path of the Grails app:
grailsApplication.mainContext.servletContext.getRealPath("")
The above answer did not work for me when used from within a plugin, packaged as a production war. I now use the following:
GrailsConventionGroovyPageLocator groovyPageLocator
def resExists(resPath) {
def resource = groovyPageLocator.findTemplateByPath(resPath)
resource
}

Resources