I have function in a module in the lib dir of my Sinatra app, that I want to be able to pass
a variable back to a view.
Trying to pass it like :
#errorMessage = params["testing error"]
erb :error
Bring the error erb that's in ../views from the lib directory, but does not show the errorMessage var.
erb code :
<p> Error message : <% #errorMessage %></p>
Anyone have any idea?
It should be <%= #errorMessage %> and not <% #errorMessage %>.
You can try using :locals
erb :error, :locals => {:errorMessage => "My message"}
And then use errorMessage as a variable inside your template.
Related
I recently started using Handlino's Fire.app with SCSS and ERb pre-processors, and I need a way to build a nav bar that knows what page you're on. Either using <%= render :partial => "nav" %>, or just inline html, to give a cue as to what page the user is currently on, such as a class change, etc.
You can try to pass local variables into partials:
#on some page
<%= render :partial => "nav", :locals => { :current_page => 'some_page' } %>
#_nav.html.erb
<% if current_page == 'some_page' %>
I'm on a some page.
<% end %>
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.
I'm using updated pre Ruby on Rails on Ruby 1.9.2 (with rvm), and made a new test application with
$ rails generate scaffold Project name:string
and
class Project < ActiveRecord::Base
validates_presence_of :name
end
I change
<%= form_for #project do |f| %>
to
<%= form_for #project, :remote => true do |f| %>
I can now still (without any changes in the controller) add new items to the project. If I try to add with empty in the name field, it will not add anything (validates_presence_of :name stops this), but I don't get any validation error messages. I have tried the same on an application converted from 3.0 I'm working on with same results. Here I had:
class KursController < ApplicationController
# GET /kurs
# GET /kurs.xml
respond_to :js, :html
and:
def update
#kur = Kur.find(params[:id])
#kur.update_attributes(params[:kur])
flash[:notice] = "Lagret" if #kur.save
respond_with( #kur, :layout => !request.xhr? )
end
In 3.1 I get no validation error messages. Is this because of a bug in Ruby on Rails 3.1 or something I should do different?
You are missing to call these errors. Do something like this:
<%= form_for #project do |f| %>
<%= render :partial => 'my_error_messages_for', :locals => {:collection => #project} %>
In "_my_error_messages_for.html.erb":
<% if collection.errors.any? %>
<ul>
<% collection.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
You can create a helper for this work.
I don't believe that Ruby on Rails will automatically include the partial that you've requested. You'll need to add some JavaScript code to get it to work correctly. Something like this I imagine:
// Application.js
$("form").bind("ajax:success", function (event, data, status, xhr) {
$(event.target).replaceWith(data);
});
In my rails app have a partial that contains a form shared between the new and edit action:
<%= form_for #customer do |f| %>
....
<% end %>
These action are of a controller (called customers) namespaced (called admin), if try to run the code show the error when execute form_for:
undefined method `customer_path'
Have resolved this using:
<%= form_for :customer, #customer do
|f| %>
....
<% end %>
Now the form is generated with correct url when is called by new action but when generated by edit the form url is "/admin/customers/1/edit" instead of update. If submit the form show the error:
No route matches "/admin/customers/1/edit"
but in routes.rb have:
namespace :admin do
resources :customers
end
and rake:routes show all the REST urls:
admin_customers GET /admin/customers(.:format) {:action=>"index", :controller=>"admin/customers"}
POST /admin/customers(.:format) {:action=>"create", :controller=>"admin/customers"}
new_admin_customer GET /admin/customers/new(.:format) {:action=>"new", :controller=>"admin/customers"}
edit_admin_customer GET/admin/customers/:id/edit(.:format){:action=>"edit",:controller=>"admin/customers"}
admin_customer GET /admin/customers/:id(.:format) {:action=>"show",:controller=>"admin/customers"}
PUT /admin/customers/:id(.:format) {:action=>"update", :controller=>"admin/customers"}
DELETE /admin/customers/:id(.:format) {:action=>"destroy",:controller=>"admin/customers"}
Any idea?
Try this
<%= form_for [:admin, #customer] do |f| %>
Wondering how to do this.
I have a month helper and want to render a list of each month.
If you click on the month it would then pass the number value . I want to produce a list like this
Choose a month
January - February - March - April - May.....
That are links. My helper looks like this.
MONTHLIST = [
[ "January", "1" ],
[ "February", "2" ],
[ "March", "3" ]
].freeze
How do I use link_to to get the names and link be the value. i.e #3 for march.
Here's a simple approach: pass the view to the helper
in your view
<%= your_helper(self, other_params) %>
.
.
in your helper
def your_helper(view, other_params)
do_something_with_params
view.raw view.link_to(.... link to params)
end
If I understand you completely, you mean that you want to call the link_to method in your helper module, right? Then the helper method, when called, will return the result of the link_to method to whichever view called it.
If that's what you want, I'm butting my head against a similar problem because the helper module cannot access the link_to method except through the ActionView::Helpers::URLHelper instance that was created in response to your service request. I assume that this object can be accessed through a Rails system variable, but I am at a loss as to what that might be. Thoughts?
For the interrim, my answer is to use the link_to method only within your view file. Your helper file would look something like this:
module MyHelper
def MyHelper.my_helper_method
MONTHLIST = [ [ "January", "1" ], [ "February", "2" ], [ "March", "3" ] ].freeze
end
end
Then your view file would call the helper method thus:
<% require '[path to helper file]' %>
<% months = MyHelper.my_helper_method %>
<% months.each do |month_name, month_num| %>
<%= link_to(month_name, month_num) %>
<% end %>
(Yes, that was probably a more verbose code than you needed. It could have been abbreviated.)
An alternative! Here goes:
Make a Proc object out of the link_to method, then pass it from your view to the helper as an argument. Here's how it will look...
Your view file:
<% require 'app/helpers/myhelper.rb' %>
<% proc_object = Proc.new( { |anchor_text, args| link_to(anchor_text, args) } )
<%= MyHelper.my_helper_method(proc_object) %>
Your helper file:
module MyHelper
def my_helper_method(proc_object)
months.each do |name, num|
proc.call(name, :action => 'show', :id => num)
end
end
end
For the second arg in your proc.call statement, use what you'd normally use to set the url in your link_to method, e.g. :controller => [x], :action => [y].
To recap, what you're doing is making a Proc that wraps your method, then sending that wrapped method to your helper, which will return html code for your hyperlink, which your .html.erb file will print to your html page.
<% monthlist.each do |month| %>
<%= link_to month[0], your_route(month[1]) %>
<% end %>