How to pass parameters between controller actions without using sessions? - ruby-on-rails

For example, if in my 'edit.html.erb' file I have this:
<%= form_for(#pjt_user) do |f| %>
...
<%= fields_for(:new_pjt_user) do |b| %>
<%= b.label :new_password %>
<%= b.text_field :new_password %>
<% end %>
...
<% end %>
How can I "pre-populate"/"fill" the field 'new_password' (in 'fields_for(:new_pjt_user)') passing a parameter with a render action? I aim to avoid to store password in session.

Instead of render :action you have to use render :template so you can use the :locals hash:
render :template => "pjt_users/new", :locals => { :default_password => DEFAULT_PASSWORD }
and
<%= fields_for(:new_pjt_user) do |b| %>
<%= b.label :new_password %>
<%= b.text_field :new_password, :value => default_password %>
<% end %>

Related

Rails 4 partial with form not rendering

I have partial file _form.erb.html:
<p>Name: </p><%= f.text_field :name %>
<p>Description: </p><%= f.text_field :description %>
<p>Price: </p><%= f.text_field :price %>
<p>Weight: </p><%= f.text_field :weight %>
and view file items/new.html.erb:
<h1>New item</h1>
<%= form_for #item do |f| %>
<% render partial: 'form', locals: { :f => f} %>
<p><%= f.submit 'Create' %></p>
<% end %>
But, when I go to the 0.0.0.0:3000/items/new I see a page without a form and no errors displayed. What I'm doing wrong?
You are missing the =. It should be <%= render partial: 'form', locals: { :f => f} %>

Rails sending AJAX response with a textarea

I am using the following form:
<%= form_for(#document, :remote => true) do |f| %>
<%= f.label :asset, "Document to Upload" %><br />
<%= f.file_field :asset, :class => "behaves", "data-behave" => "passValueOnChange", "data-recipient" => "#campaign_document_name" %>
<%= f.label :name, :class => 'required' %><br />
<%= f.text_field :name, :required => true %>
<%= f.submit "Upload Document", :class => "button" %>
<% end %>
to submit to the following controller:
def create
#document = CampaignDocument.new(params[:campaign_document])
#campaign.documents << #document
respond_to do |format|
format.js
end
end
which should return the following create.js.erb:
<%= remotipart_response do %>
<% unless #document.errors.any? %>
$('.tablewrapper').html( '<%= escape_javascript(render :partial=>'documents_table') %>' );
alertify.success("File Updloaded");
<% else %>
<% #document.errors.each do |attr, msg|%>
alertify.error("<%= msg %>",10000);
<% end %>
<% end %>
<% end %>
but the response is wrapped in a textare tag. Which is pretty odd:
<textarea data-type="text/javascript" response-code="200">
$('.tablewrapper').html('{code for HTML ommited for brevity}');
alertify.success("File Updloaded");
</textarea>
Note
Other, similar styled AJAX functions on the same installation are not behaving this way.

passing variable into partial

I have the following for and partial setup but i keep on getting an error, that the partial does not recognise the variable |builder|.
Form
<%= simple_form_for #firm do |f| %>
<%= f.fields_for :events do |builder| %>
<%= render 'event_fields', :builder => builder %>
<% end %>
<%= end %>
_events_fields partial
<fieldset>
<%= builder.input :name, :collection => ['Applications Open', 'Applications Close', 'Traineeship Starts'] %>
<%= builder.text_field :start_at, :class => 'datepicker' %>
<%= builder.hidden_field :all_day, :value => true %>
<%= link_to "remove", '#', class: "remove_fields" %>
any idea how i should be padding the variable across? or if in fact this is the correct way of doing it? It would be really helpful is someone could help me understand a little more about how and why you need to do this.
You need to tell it that it is a partial view and pass in a hash to the locals option. Like so:
<%= simple_form_for #firm do |f| %>
<%= f.fields_for :events do |builder| %>
<%= render partial: 'event_fields', locals: {builder: builder} %>
<% end %>
<% end %>
If you're using Ruby 1.8 then:
<%= simple_form_for #firm do |f| %>
<%= f.fields_for :events do |builder| %>
<%= render :partial => 'event_fields', :locals => { :builder => builder } %>
<% end %>
<% end %>
partial_name would be replace with actual partial name or partial name with directory name.
We would provide the data_object object to the partial, available under the local variable data_variable in the partial and is equivalent to:
<%= render partial: "partial_name", locals: { data_variable: data_object } %>

rails ignores my redirect

Rails is ignoring my redirect.
Use Case:
user navigates to his account and selects the option to display his subscription status
app lists his current subscription and the option to cancel it
user cancels the subscription
app updates the subscription record and should redirect the user back to the subscriptions action
-> but rails ignores this last step... any ideas what I am doing wrong?
Routes
map.resources :users, ..., :member => { ..., :subscriptions => :get, :subscribe => :post, :unsubscribe => :put}
Controllers:
def subscriptions
#tradesman = User.find_by_id(params[:id])
#subscription = #tradesman.current_subscription || Subscription.new
#all_subscriptions = Subscription.find(:all)
end
def subscribe
#tradesman = User.find_by_id(params[:id])
#subscription = current_user.subscriptions.build(params[:subscription])
#subscription.update_attributes(:started_at => Time.zone.now)
#subscription.save
redirect_to :action => 'subscriptions', :id => #tradesman.id
end
def unsubscribe
#tradesman = User.find_by_id(params[:id])
#subscription = #tradesman.current_subscription
#subscription.update_attributes(:ended_at => Time.zone.now)
#subscription.save
redirect_to :action => 'subscriptions', :id => #tradesman.id
end
View:
<div class = 'wrapper'>
<%= render :partial => "my_account_leftbar" %>
<% form_for #subscription, :url => subscribe_user_path(current_user) do |f| %>
<% #all_subscriptions.each do |subscription| %>
<div class="field">Start: <%= subscription.started_at %></div><br><br>
<% end %>
<% if #subscription.new_record? %>
<div class="field">
<%= f.check_box :subscription_type %>
<div class="actions">
<%= f.submit "Subscribe", :class => "button mr8" %>
</div>
</div>
<% else -%>
<%= f.check_box :subscription_type, :value => #subscription.subscription_type, :disabled => true %>
<% form_for #subscription, :url => unsubscribe_user_path(current_user) do |f| %>
<div class="actions">
<%= f.submit "Unsubscribe", :class => "button mr8" %>
</div>
<% end %>
<% end %>
<% end %>
</div>
Use redirect_to instead of render (last method call in your unsubscribe action).
Found the bug in the view where I nested the 'unsubscribe' form within the 'subscribe' form - what didn't make sense.
I rearranged my view (separated those two forms, one in the 'if' part and the other in the 'else' part. Works fine now:
<div class = 'wrapper'>
<%= render :partial => "my_account_leftbar" %>
<% #all_subscriptions.each do |subscription| %>
<div class="field">Start: <%= subscription.started_at %></div><br><br>
<% end %>
<% if #subscription.new_record? %>
<% form_for #subscription, :url => subscribe_user_path(current_user) do |f| %>
<div class="field">
<%= f.check_box :subscription_type %>
<div class="actions">
<%= f.submit "Subscribe", :class => "button mr8" %>
</div>
</div>
<% end %>
<% else -%>
<% form_for #subscription, :url => unsubscribe_user_path(current_user) do |f| %>
<%= f.check_box :subscription_type, :value => #subscription.subscription_type, :disabled => true %>
<div class="actions">
<%= f.submit "Unsubscribe", :class => "button mr8" %>
</div>
<% end %>
<% end %>
</div>

How can I make three partials into just one in rails where the :collection is the same?

I have three partials that I'd like to consolidate into one. They share the same collection, but each gets passed its own :local variable. Those variables are used for specific Models, so as a result, I have three different calls to the partial and three different partials.
Here's the repetitive code:
<% for email in campaign.emails %>
<h4><%= link_to email.title, email %> <%= email.days %> days</h4>
<% #contacts= campaign.contacts.find(:all, :order => "date_entered ASC" )%> <!--contacts collection-->
<!-- render the information for each contact -->
<%= render :partial => "contact_email",
:collection => #contacts,
:locals => {:email => email} %>
<% end %>
Calls in this Campaign:
<% for call in campaign.calls %>
<h4><%= link_to call.title, call %> <%= call.days %> days</h4>
<% #contacts= campaign.contacts.find(:all, :order => "date_entered ASC" )%> <!--contacts collection-->
<!-- render the information for each contact -->
<%= render :partial => "contact_call",
:collection => #contacts,
:locals => {:call => call} %>
<% end %>
Letters in this Campaign:
<% for letter in campaign.letters %>
<h4><%= link_to letter.title, letter %> <%= letter.days %> days</h4>
<% #contacts= campaign.contacts.find(:all, :order => "date_entered ASC" )%> <!--contacts collection-->
<!-- render the information for each contact -->
<%= render :partial => "contact_letter",
:collection => #contacts,
:locals => {:letter => letter} %>
<% end %>
An example of one of the partials is as follows:
<
div id="contact_email_partial">
<% if from_today(contact_email, email.days) < 0 %>
<% if show_status(contact_email, email) == 'no status'%>
<p> <%= full_name(contact_email) %>
<% unless contact_email.statuses.empty?%>
(<%= contact_email.statuses.find(:last).status%>)
<% end %>
is <%= from_today(contact_email,email.days).abs%> days overdue:
<%= do_event(contact_email, email) %>
<%= link_to_remote "Skip Email Remote",
:url => skip_contact_email_url(contact_email,email),
:update => "update-area-#{contact_email.id}-#{email.id}" %>
<span id='update-area-<%="#{contact_email.id}-#{email.id}"%>'> </span>
<% end %>
<% end %>
</div>
And here is the other partial...similar, eh? Need help making it DRY!
<% if (from_today(contact_call, call.days) < 0) %>
<% if show_status(contact_call, call) == 'no status'%>
<p> <%= full_name(contact_call) %>
<% unless contact_call.statuses.empty?%>
(<%= contact_call.statuses.find(:last).status%>)
<% end %>
is <%= from_today(contact_call,call.days).abs%> days overdue:
<%= do_event(contact_call, call) %>
<%= contact_call.phone %>
</p>
<% end %>
<% end %>
For the local variables, the key you select when passing the locals hash is the name the variable will have in the partial. So you could do this in your repetitive code:
<% for email in campaign.emails %>
<h4><%= link_to email.title, email %> <%= email.days %> days</h4>
<% #contacts= campaign.contacts.find(:all, :order => "date_entered ASC" )%> <!--contacts collection-->
<!-- render the information for each contact -->
<%= render :partial => "contact",
:collection => #contacts,
:locals => {:objt => email,
:url_method => "skip_#{class}_url".to_sym } %>
<% end %>
Calls in this Campaign:
<% for call in campaign.calls %>
<h4><%= link_to call.title, call %> <%= call.days %> days</h4>
<% #contacts= campaign.contacts.find(:all, :order => "date_entered ASC" )%> <!--contacts collection-->
<!-- render the information for each contact -->
<%= render :partial => "contact",
:collection => #contacts,
:locals => {:objt => call,
:url_method => "skip_#{class}_url".to_sym } %>
<% end %>
Letters in this Campaign:
<% for letter in campaign.letters %>
<h4><%= link_to letter.title, letter %> <%= letter.days %> days</h4>
<% #contacts= campaign.contacts.find(:all, :order => "date_entered ASC" )%> <!--contacts collection-->
<!-- render the information for each contact -->
<%= render :partial => "contact",
:collection => #contacts,
:locals => {:objt => letter,
:url_method => "skip_#{class}_url".to_sym } %>
<% end %>
Since in the partial we don't really know the class of the object we need to render, I'm creating a symbol representing the method you need to call to build the URL. We'll invoke this in the partial using a bit of send magic.
Notice the partial has been renamed simply "contact" (_contact.html.erb), and I'm assigning email, call and letter in turn to a variable called objt, that will be accessible from the partial.
For the partial (_contact.html.erb):
<div id="contact_partial">
<% if from_today(contact, objt.days) < 0 %>
<% if show_status(contact, objt) == 'no status'%>
<p> <%= full_name(contact) %>
<% unless contact.statuses.empty?%>
(<%= contact.statuses.find(:last).status%>)
<% end %>
is <%= from_today(contact,objt.days).abs%> days overdue:
<%= do_event(contact, objt) %>
<%= link_to_remote "Skip Email Remote",
:url => send(url_method,contact,objt),
:update => "update-area-#{contact.id}-#{objt.id}" %>
<span id='update-area-<%="#{contact.id}-#{objt.id}"%>'> </span>
<% end %>
<% end %>
</div>
Notice how, instead of calling the skip_email_url method directly, we use "send" to invoke a method named in the first parameter (in this case, url_method, a local passed from the invoking view), and further, we pass this method the additional parameters (in this case, contact and objt). Just make sure the method named in url_method does effectively take two parameters.

Resources