I have an ordinary form to create a Package object at /packages/new:
<%= form_for #package do |f| %>
<%= f.text_field :name %>
<%= f.text_field :address %>
...
<% end %>
The package model belongs_to :partner.
I am looking for a way to associate a new package form to a specific partner, preferably without any input from the user filling it in.
For example, if partner A sends a link to the form, I want the form to include partner_id:A.id.
How can I connect forms to partners?
You can send partner_id param with the link which your partner will send.
Something like
http://website.com/packages/new?partner_id=3
And use the param as hidden_field in the form
<%= form_for #package do |f| %>
<%= f.text_field :name %>
<%= f.text_field :address %>
<%= f.hidden_field :partner_id, value: params[:partner_id] %>
...
<% end %>
Alternatively you can also make use of Nested Resources
you can have, hidden field which passes partner_id to controller
http://apidock.com/rails/ActionView/Helpers/FormHelper/hidden_field
If the partner needs to be logged in, in order to create a package, you could simply link the package to the partner in the controller right before saving it.
As mentioned before, use params. And don't forget to allow the required params in the controller if necessary (via link, scroll down a little). documentation: params
Check out what e.g. .build() does for you. more about relations and how to set them up correctly
Related
How do I pass those arguments which are not of model to a controller?
script.rb
class Script < ActiveRecord::Base
attr_accessor :directory
attr_accessor :xmlFile
end
show.html.erb
<h1><%= #script.Name %></h1>
<%= simple_form_for #script, :url => script_execute_path(script_id: #script.id) do |f| %>
<%= f.input :directory %>
<%= f.input :xmlFile %>
<%= f.button :submit, 'Run' %>
<% end %>
Here directory and xmlFile are used for taking inputs but it is not a part of Script model. Now I need to pass values contained in directory and xmlFile to my execute controller action
def execute
#script = Script.find(params[:script_id])
#something like this -- #xmlFile = params[:xmlFile]
end
how do I access it here?
They are indeed part of the Script model, because they are defined as attributes of the model. The fact they are not persisted is irrelevant.
You access them from the hash of params that represent the model itself. You can determine the exact name inspecting the logs of the request, you'll see how the parameters are structured.
Assuming the name of the model is Script, the hash key that contains the script attributes should be called script, therefore:
params[:script][:directory]
Please note that Ruby doesn't use camelCase, therefore the name xmlFile doesn't follow the conventions and may cause you issues. The name should be xml_file, not xmlFile.
For arbitrary fields that aren't part of a model, you can use Rails' standalone tag helpers, such as text_field_tag:
<%= simple_form_for #script, :url => script_execute_path(script_id: #script.id) do |f| %>
<%= text_field_tag :directory %>
<%= text_field_tag :xmlFile %>
<%= f.button :submit, 'Run' %>
<% end %>
If you want to pre-fill them with an existing value, you can pass that in as well:
<%= text_field_tag :directory, 'some default value' %>
It looks like you've actually already figured it out. By declaring
attr_accessor :directory
attr_accessor :xmlFile
in your Script model, you've effectively made them a part of the model. They just won't be persisted to the database when the object is saved. But as long as the object is in memory, those attributes will be available.
And since you've already got those attributes defined in your view:
<%= f.input :directory %>
<%= f.input :xmlFile %>
they'll be available to you in your controller via the params hash via params[:directory] and params[:xmlFile].
I would really like to add a form field "invite_code" to the user sign up form, but I don't know how to add the invite_code to the controller so that the application knows how to look for it?
The form in the sign up on the template would read:
<% form_for User.new do |f| %>
<span>Email:</span> <% f.email %><br>
<span>Name:</span> <% f.name %><br>
<span>Invite Code:</span> <% f.invite_code %><br>
<% end %>
The "invite_code" isn't part of the database or anything, but in the user registration model, I want to put a:
before_save :invite_promo
def invite_promo
if #invite_code.present? && #invite_code == "special_person"
self.special_key = true
end
end
Is there an easy way to look for form fields in the template using the model or controller?
So sorry...I'm new to Rails. Thank you so much in advance!
You need to define a virtual attribute invite_code in User model:
attr_accessor :invite_code
Your form should look as follows:
<%= form_for User.new do |f| %>
<span>Email:</span> <%= f.email_field :email %><br>
<span>Name:</span> <%= f.text_field :name %><br>
<span>Invite Code:</span> <%= f.text_field :invite_code %><br>
<% end %>
if you don't want to create a field inside your table, you can use hidden field in view like, <%= hidden_field_tag :invite_code, 'code' %>
I have an application that deals with user rotas - and I'm currently adding the ability for admin approvals. If the user updates their own rota the params hash looks something like:
Parameters: {id:1, role_id: 1, team_id:1, rota: [startDate: 01/01/2014, endDate:02/02/2014]}
and these are submitted using a form with:
<%= form_for [#team,#role,#rota] do |f| %>
form code
<% end %>
We need to access the attributes outside the rota: object but currently can't find a way to as:
params.require requires you to pass an object in.
My team members have decided to add hidden fields to submit the attributes within the rota object but that seems redundant seeing as they are quite clearly there, we just can't find a way to access them, and ideas?
I was talking about something like
def user_rota_params
params.require(:user)
.permit(:role_id, :team_id, :rota => [:startDate, :endDate])
end
Then, for your nested attributes you could use fields_for.
Your form, thus, should look something this (omitting labels and keeping it basic):
<%= form_for #user do |f| %>
<%= f.text_field :role_id %>
<%= f.text_field :team_id %>
<%= f.fields_for :rota do |ff| %>
<%= ff.date_field :startDate %>
<%= ff.date_field :endDate %>
<% end %>
<% end %>
I have an existing form which is tied to a model named 'Order', but i want to add new form fields that will capture Credit Card info such as name, cc number, etc to be processed on a 3rd party payment gateway.
But since i don't want to save CC info in our database, there are no corresponding columns of that in my order table. And this gives me an error when submitting the form that those Credit card input fields are not 'part' of the order model.
If I understand your answer correctly, what you want to do is explained in the official wiki page here: Create a fake input that does NOT read attributes. You can use a field not related to any real database column by Edward's suggestion, however you don't need to define an attribute in your model if the form field is nothing to do with the model.
In summary, the trick explained in the page is defining a custom input called 'FakeInput' and use it like this:
<%= simple_form_for #user do |f| %>
<%= f.input :agreement, as: :fake %>
....
Do not forget to restart your rails server after adding/modifying a custom input as Fitter Man commented.
UPDATE: Please note that the official wiki page has updated and the sample code on the wiki page is not working for those which use older versions of SimpleForm. Use code below instead if you encounter an error like undefined method merge_wrapper_options for.... I'm using 3.0.1 and this code works well.
class FakeInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input
template.text_field_tag(attribute_name, input_options.delete(:value), input_html_options)
end
end
You can use attr_accessor
class Order < ActiveRecord::Base
attr_accessor :card_number
end
Now you can do Order.first.card_number = '54421542122' or use it in your form or whatever else you need to do.
See here for ruby docs http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-attr_accessor
and here for a useful stackoverflow question What is attr_accessor in Ruby?
Don't get it mixed up with attr_accessible! Difference between attr_accessor and attr_accessible
The best way to handle this is to use simple_fields_for like so:
<%= simple_form_for #user do |f| %>
<%= f.input :first_name %>
<%= f.input :last_name %>
<%= f.input :email %>
<%= simple_fields_for :other do |o| %>
<%= o.input :change_password, as: :boolean, label: 'I want to change my password' %>
<% end %>
<% end %>
In this example, I have added a new field called change_password which is not part of the underlying user model.
The reason this is a good approach, is that it lets you use any of the simple form inputs / wrappers as fields. I don't care for the answer by #baxang, because it doesn't allow you to use different types of inputs. This seems more flexible.
Notice though for this to work, I had to pass :other to simple_fields_for. You can pass any string/symbol as long as there is not a model with that same name.
I.e. unfortunately I can't pass :user, as simple_form would try to instantiate a User model, and we'd get the same error message again...
Also if you're just trying to add something and get it into the params, but leaving it out of the model's hash, you could just do FormTagHelpers. http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html
Example:
<%= simple_form_for resource, :as => resource_name, :url => invitation_path(resource_name), :html => {:method => :post} do |f| %>
<%= devise_error_messages! %>
<% resource.class.invite_key_fields.each do |field| -%>
<%= f.input field %>
<%= hidden_field_tag :object_name, #object.class.name %>
<%= hidden_field_tag :object_id, #object.id %>
<% end -%>
I found a very simple (and somewhat strange) workaround.
Just add the input_html option with any value key inside. E.g:
= simple_form_for #user do |f|
= f.input :whatever, input_html: {value: ''}
Tested simple_from versions: 3.2.1, 3.5.1
What is the difference between form_for and form_tag? Is anything different for form_remote_for and form_remote_tag?
You would use form_for for a specific model,
<% form_for #person do |f| %> # you can use f here
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
<% end %>
Form_tag create basic form,
<%= form_tag '/person' do -%>
<%= text_field_tag "person", "first_name" %>
<% end -%>
form_for prefers, as its first arg, an activerecord object; it allows to easily make a create or edit form (to use it in a "new" view you should create an empty instance in controller, like:
def new
#foo = Foo.new
end
It also passes a form variable to the block, so that you don't have to repeat the model name within the form itself. it's the preferred way to write a model related form.
form_tag just creates a form tag (and of course silently prepare an antiforgery hidden field, like form_for); it's best used for non-model forms (I actually only use it for simple search forms or the like).
Similarly, form_remote_for and form_remote_tag are suited for model related forms and not model related forms respectively but, instead of ending in a standard http method (GET, POST...), they call an ajax method.
All this and far more are available for you to enjoy in the FormHelper and PrototypeHelper reference pages.
EDIT 2012-07-13
Prototype has been removed from rails long ago, and remote forms have completely changed. Please refer to the first link, with reguard to the :remote option of both form_for and form_tag.
These should be similar:
<% form_for #person do |f| %>
<%= f.text_field :name %>
<% end %>
and:
<%= form_tag '/person' do %>
<%= text_field_tag "person[name]" %>
<% end %>
If you want to submit the same params to the controller, you would have to define this explicitly.