How to pass hidden parameter to controller in Rails3 - ruby-on-rails

I'd like to pass the parameter recipient to controller. I can show it in my view like this:
#recipient.username
How can I pass this value to params[:message][:recipient]? Note that I do not have a model called "Message".
controllers/messages_controller.rb
def deliver
recipient = User.find_by_username(params[:recipient])
subject = params[:subject]
body = params[:body]
current_user.send_message(recipient, body, subject)
redirect_to :controller => 'messages', :action => 'received'
flash[:notice] = "message sent!"
end
views/messages/new.html.erb
<td><%= #recipient.username if #recipient %></td>
<%=form_for :messages, url: url_for( :controller => :messages, :action => :deliver ) do |f| %>
<div class="field">
<%= f.label :subject %><br />
<%= f.text_field :subject %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_field :body %>
</div>
<div class="actions">
<%= f.submit %>
<% end %>

You could do this by assigning an attr_accessible key for your Recipient and assign it to the form.
form_for :message do |f|
f.hidden_field :recipient_id, :value => #recipient.id.to_i
f.text_field :message
f.submit
end
once you pass this to your create action you are able to check params[:message][:recipient_id]
and pass this to the db.
Have fun

Related

Action Controller: Exception | undefined method `fetch_value' for nil:NilClass

I am always getting this error message:
NoMethodError in ListsController#new undefined method `fetch_value' for nil:NilClass
Extracted source (around line #8):
7 def new
8 #list = List.new
9 end
I don't get the reason for this error ^^
My routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'lists#index'
get 'home' => 'lists#index', as: 'home'
get 'new' => 'lists#new', as: 'new'
resources :lists
end
Database name:
:lists
Model name:
list
lists_controller:
class ListsController < ApplicationController
def index
#lists = List.all
end
def new
#list = List.new
end
def show
#list = List.find(params[:id])
end
def create
#list = List.new(list_params)
if(#list.save)
redirect_to #list
else
render 'new'
end
end
def edit
#list = List.find(params[:id])
end
def update
#list = List.find(params[:id])
if(#list.update(list_params))
redirect_to #list
else
render 'edit'
end
end
def destroy
#list = List.find(params[:id])
#list.destroy
redirect_to lists_path
end
private def list_params
params.require(:list).permit(:date, :class, :lesson, :subject, :teacher, :room, :info)
end
end
new.html.erb
<%= form_for :list, url: lists_path do |f| %>
<% if #list.errors.any? %>
<% #list.errors.full_messages.each do |error| %>
<div class="alert alert-danger"><%= error %></div>
<% end %>
<% end %>
<div class="alert alert-info">Please fill out all the fields below.</div>
<p>
<%= f.label :date %><br>
<%= f.text_field :date, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :class %><br>
<%= f.text_area :class, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :lesson %><br>
<%= f.number_field :lesson, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :teacher %><br>
<%= f.text_field :teacher, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :room %><br>
<%= f.text_field :room, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :info %><br>
<%= f.text_area :info, {:class => 'form-control'} %>
</p>
<p>
<%= f.submit({:class => 'btn btn-info'}) %>
</p>
<% end %>
Using the BootstrapCDN and only the default gems.
Thanks for any answers :)
In your model you have an attribute named class which is a reserved keyword which is causing issues. As I can see your code:
<p>
<%= f.label :class %><br>
<%= f.text_area :class, {:class => 'form-control'} %>
</p>
So you should never use reserved keywords as attributes because you are overriding it in that case. So when overriding it, your attribute will not consist of all the properties required by the language. That is why you are getting the error.
Rails is trying to fetch the attributes from :list which should be #list
Change the form_for in new.html.erb from
<%= form_for :list, url: lists_path do |f| %>
to
<%= form_for #list, url: lists_path do |f| %>

undefined local variable or method `email' for Contact:Class

I would like to use ruby mail_form and Heroku Sendgrid to allow users to send me an email. I have set up the following Contact class in apps/models/contact.rb
class Contact < MailForm::Base
attribute name, :validate => true
attribute email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute message, :validate => true
attribute nickname,:captcha => true
def headers
{
:subject => "Contact Form",
:to => "example#email.com",
:from => %("#{name}" <#{email}>)
}
end
end
However, when I visit the page where I have set up my form, I receive the following error message:
undefined local variable or method `email' for Contact:Class
Commenting out the email attribute defined in my Contact class produces similar errors in subsequent attributes message: and nickname:
Below is my Contacts controller, contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
#contact.request = request
if #contact.deliver
flash.now[:error] = nil
else
flash.now[:error] = "Oops! There was an error."
render :new
end
end
end
and my form, new.html.erb
<% provide(:title, "Contact") %>
<h1>Contact</h1>
<%= form_for #contact do |f| %>
<%= f.label :name %><br>
<%= f.text_field :name, required: true %>
<br>
<%= f.label :email %><br>
<%= f.text_field :email, required: true %>
<br>
<%= f.label :message %><br>
<%= f.text_area :message, as: :text %>
<div class="hidden">
<%= f.label :nickname %><br>
<%= f.text_field :nickname, hint: "Leave this field blank." %>
</div>
<%= f.submit "Send Message", class: "btn" %>
<% end %>
<ul class="pager">
<li>Previous</li>
</ul>
Any help or suggestions would be greatly appreciated!
You omitted double quotes in the from option.
def headers
{
:subject => "Contact Form",
:to => "example#email.com",
:from => %("#{name}" <#{email}>)
}
end

Rails 4 custom controller action error - "Couldn't find 'model' without an ID"

I'm trying to add a custom create action for my Book model, but i keep ending up with a "Couldn't find Book without an ID".
routes.rb:
Books::Application.routes.draw do
resources :books
resources :books do
collection do
post 'create_new_record', :action => :create_new_record
end
end
match 'create_new_record' => 'books#create_new_record', via: [:post]
The relevant controller action:
def create_new_record
#book = Book.new(book_params)
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'New book record created.' }
end
end
end
And my form (in new.html.erb). I'm looping through results that i get from goodreads.com.
<% #book_search.results.work.each do |stuff| %>
<%= form_for(#book, :url => create_new_record_books_path) do |f| %>
<div class="field">
<%= f.label :author %><br>
<%= f.text_field :author, :value => stuff.best_book.author.name %>
</div>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title, :value => stuff.best_book.title %>
</div>
<div class="field">
<%= f.label :isbn %><br>
<%= f.text_field :isbn, :value => stuff.best_book.isbn %>
</div>
<div class="field">
<%= f.label :image %><br>
<%= f.text_field :image, :value => stuff.best_book.image_url %>
</div>
<div class="field">
<%= f.label :bookid %><br>
<%= f.text_field :bookid, :value => stuff.best_book.id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<hr>
<% end %>
The error i get when submitting the form is:
ActiveRecord::RecordNotFound in BooksController#create_new_record
on the callback
def set_book
#book = Book.find(params[:id])
end
I'm pretty much stumped now, my understanding is that it doesn't even reach the action, but instead looks for a book id that doesn't exist?
Thank you!
If you use before_filter so you don't pass an id to create action. Call your before filter the following way:
before_filter :set_book, except: [:index, :new, :create]
If you use model callback, params is unavailable in the model so pass the id some other way, for example via attr_accessor.
use #book = Book.where(id: params[:id]).first

Insert recipient id to message form

I need assistance with creating code that will allow for a user to respond back to current message and automatically fill the recipient_id (from box) with the senders id.
So if I am reading a message from user 1. If I click reply the from box should have id 1 filled in as the recipient id.
So far I have only been able to fill in the recipient id based off the user id shown in the params.
new.html.erb:
<% render #message %>
<%= form_for #message, :url => user_messages_path(#user) do |f| %>
<%= f.hidden_field :parent_id %>
<p>
To:<br />
<%= f.text_field :recipient_id, :value => params[:user_id] %>
</p>
<p>
Subject:<br />
<%= f.text_field :subject %>
</p>
<p>
Message<br />
<%= f.text_area :body %>
</p>
<%= submit_tag "Send"%>
<% end %>
Controller:
def new
#new_message = Message.new
#message = Message.new
#message.parent_id = params[:parent_id]
end
def reply
#reply_message = Message.new
#message = Message.new
#message.parent_id = params[:parent_id]
end
Couldn't you just do:
<%= f.text_field :recipient_id, :value => #user.id %>

Can't get nested_form to show validation errors

I haven't had a problem with validations before but this time I am having issues with nested_form validations. I am using Twitter Bootstrap and can get flash errors to show with, say, this:
def create
#recipe = current_user.recipes.new(params[:recipe])
if #recipe.save
redirect_to my_recipes_path, :notice => "Thanks #{current_user.name} Recipe sucessfully created."
else
render :action => 'new'
end
end
For my flash messages I use this in my app/layouts
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert">×</a>
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
</div>
<% end %>
So I thought I would try and just get one of the validators working, so my model
class Recipe < ActiveRecord::Base
belongs_to :user
delegate :name, :to => :user, :prefix => :user, :allow_nil => true
belongs_to :country
has_many :ingredients
has_many :preperations
has_many :favourites
validates_presence_of :dish_name
and my form
<%= nested_form_for #recipe do |f| %>
<div class="field_with_errors">
<%= f.label :dish_name, "Dish Name" %>
<%= f.text_field :dish_name, :placeholder => "Enter Dish Name" %>
</div>
<%= f.label :country_id, "Country Of Origin" %>
<%= f.collection_select(:country_id, Country.all, :id, :name, :prompt => 'Please select country') %>
<%= f.label :category, "Category" %>
<%= f.select :category, [['Starter'], ['Main Course'], ['Desserts'], ['Vegeterian']], {:include_blank => 'Please Select'} %>
<%= f.label :difficulty, "Difficulty Level" %>
<%= f.select :difficulty, [['Beginner'],['Intermediate'],['Expert']], {:include_blank => 'Please Select'} %>
<%= f.label :preperation_time, "Preperation Time (Mins)" %>
<%= f.select :preperation_time, [['15-30 Mins'],['30-60 Mins'],['60-120 Mins']], {:include_blank => 'Please Select'} %>
<%= f.fields_for :ingredients do |ing| %>
Ingredient<br>
<%= ing.text_field :ingredient_name , :placeholder => "Enter Ingredient Here" %><br>
<% end %>
<%= f.link_to_add "Add an Ingredient", :ingredients %><br>
<%= f.fields_for :preperations do |prep| %>
Preperation Step<br>
<%= prep.text_field :prep_steps , :placeholder => "Enter step Here" %><br>
<% end %>
<%= f.link_to_add "Add a step", :preperations %><br>
<%= f.label :description, "Description of Recipe" %>
<%= f.text_area :description, :size=> "60x10" %></br>
<%= f.file_field :avatar %><br>
<%= f.submit "Submit Recipe" %>
<% end %>
I am fairly new to Rails so I may have missed something fundamental, or is it because it is a nested form and it behaves differently?
Edit
Output of <%= flash debug %>:
--- !ruby/object:ActionDispatch::Flash::FlashHash
used: !ruby/object:Set
hash: {}
closed: false
flashes: {}
now:
It seems you're not actually providing your flash hash with any messages to work with. A quick solution might be something like:
def create
#recipe = current_user.recipes.new(params[:recipe])
if #recipe.save
redirect_to my_recipes_path, :notice => "Thanks #{current_user.name} Recipe sucessfully created."
else
flash[:error] = #recipe.errors.full_messages.to_sentence
render :action => 'new'
end
end

Resources