I want to ask that how can i get the selected option in my controller action in rails, so that i can save it in database. I don't want to use rails helper for select-box and options. As i have copied the select box code, and it has large number of options. I hope my question is clear enough.
I am using form_for helper though.
Regards.
You'll have code like this:
form_for #variable do |f|
f.select --------------
end
You'll want to catch the params & save them, like this:
def new
#variable = Model.new
end
def create
#variable = Model.new(post_params)
#variable.save
end
private
def post_params
params.require(:variable).permit(:select_name)
end
Just realized you're using Rails 3. My code is for Rails 4, but the process remains the same -- treat the select box as any other input, and to do that you have to ensure it's called from the form_for function
If you want to create a country select box, you could use the country_select gem with this code in your form_for:
<%= f.country_select :country, ["United States"] %> #Can write any default country
This will keep it consistent with Rails
Related
I'm pretty new to rails and I'd like to set my links for a certain page dynamically. I have a table called "Unfinished" and it has a column called "link" (corrected from "links") I'd like to be able to call the "link" record in the view to set my link_to link path.
I am trying to do this...
<%= link_to #unfinished.link(:p => #post.id) do %> FINISH <% end %>
...but that's not working.
my controller says:
def show
#post = Post.find(params[:id])
#unfinished = Unfinished.where('progress = ?', #post.progress).last
end
and the controller logic works fine...until I try to put the #unfinished.link into link_to
Edit:
Error Message:
wrong number of arguments (1 for 0)
Model
class Unfinished < ActiveRecord::Base
end
The type of links are :
step1_path
step2_path
step3_path
I am making a multipage form that you can save partway through. Based on a value in the #post.progress column (like 1, 2, 3) the correct path to complete the post will be provided (step1_path, step2_path etc...)
try this.
<%= link_to eval(#unfinished.link.to_s) do %> FINISH <% end %>
since the link you want is actually a named route, so you will need to eval it.
but with this you wouldn't be able to be able to pass in the post id, which you will need.
If the route is the same for all records (save for what part you are on based on the progress attribute) do you even need to store it in the database? You could just make the link method return the path (that you would still need to eval).
something like
def link (post)
"step#{self.progress}_path(post.id)"
end
and then eval the link on the way back. but Not sure if that will work, just thinking out loud...
There are gems that do multi-stage forms perhaps looking into them might help?
I know I've written it wrong, but I'm looking at the documentation and can't figure out how.
My model is Quote and has three fields, body, attribution, and work, all strings. The form is intended to add a new quote to a page of quotations.
on main/index.html.erb
<%= form_for(:quote, url: {action: 'create'}) do |f| %>
<%= f.text_field :body %>
<%= f.text_field :attribution %>
<%= f.text_field :work %>
<%= submit_tag "Submit" %>
<% end %>
in main_controller.rb
def create
Quote.create(body: params[:body], attribution: params[:attribution], work: params[:work])
end
The form submits, and an entry is saved to the database -- but it's a totally blank entry. I'm not sure why. Help would be appreciated!
Three things:
The way rails forms are supposed to work, you're not meant to get body, attribution, etc independently, they should be wrapped up into a quote object. But...
In your form, your not properly binding an object to the form the way rails expects. You can read more in the documentation here: http://guides.rubyonrails.org/form_helpers.html#binding-a-form-to-an-object. You could also generate a fake scaffold rails generate scaffold HighScore game:string score:integer to generate a fake model and see an example of how it's supposed to work. The default scaffolding even has simple examples of how to deal with save errors.
Finally, as #Paven suggested, when you get confused, be sure to look at what's going on in your log - i.e. what params are being posted to your create action. That is always helpful and a good way to diagnose problems quickly.
Your form does't need the action argument. The form_for helper uses ActiveRecord objects to determine the path, meaning as long as you build your object correctly, you won't need to determine your path individually:
<%= form_for #quote do |f| %>
Secondly, you'll want to look at your create method:
#app/controllers/quotes_controller.rb
def new
#quote = Quote.new
end
def create
#quote = Quote.new(quote_params)
end
private
def quote_params
params.require(:quote).permit(:body, :attribution, :work)
end
The problem is you're not sending an ActiveRecord object to your form_for helper. You can read the explanation here:
In Rails, this is usually achieved by creating the form using form_for
and a number of related helper methods. form_for generates an
appropriate form tag and yields a form builder object that knows the
model the form is about. Input fields are created by calling methods
defined on the form builder, which means they are able to generate the
appropriate names and default values corresponding to the model
attributes, as well as convenient IDs, etc. Conventions in the
generated field names allow controllers to receive form data nicely
structured in params with no effort on your side.
In order to get the form working correctly, you need to be able to provide a valid ActiveRecord object (#variable), which the helper can use to determine the url etc
My code above helps you provide a new ActiveRecord variable, and allows you to use it in the form. This should allow the form_for method to send your data to the create method, which will then create & save an object in the db for you
I'm trying to read parameters from html form and update some fields in the database...
Html is showing data from multiple "stories" and I want to be able to change Story.estimate field...
The html has text input fields for every story showing like so:
<%= text_field_tag story.id, story.estimate, :class => "input-small" %>
My idea was to name these input fields by the ID of their story and then read and update them in the controller like so:
#story.update_attribute("estimate",params[#story.id])
But this of course does not work... I need some help... There has to be a better, simpler way of doing this...
You should try
<%= text_field_tag "story[#{story.id}]", story.estimate, :class => "input-small" %>
and in your controller
you will get the params like this
if params[:story].present?
id = params[:story].keys.to_i
value = params[:story].values.first
#story = Story.where(id: id).first
#and then finally update the story
#story.update_attribute("estimate",value)
OR
#this will also update your story for the corresponding story id
Story.where(id: id).update_all(estimate: value)
end
Also, I believe update_attribute may have been removed in rails 4 in favor of update_column. So if you are running rails 4 that may be an issue. (https://github.com/rails/rails/commit/a7f4b0a1231bf3c65db2ad4066da78c3da5ffb01)
On a Content model have an attribute named slug. When creating a new record, I want to use a helper to populate this field, but on an existing record I want to use the value from the database.
Currently I have:
<% if #content.new_record? %>
<%= f.text_field :slug, :value => "#{generate_slug(6)}" %>
<% else %>
<%= f.text_field :slug %>
<% end %>
But that seems a bit verbose. Is this the best way, or is there no other way? (Rails newb just trying to find the "Rails way" on issues I'm unsure of)
Edit
I should note that the helper is currently in /app/helpers/application_helper.rb Moved to be a private action in the Contents controller. David's answer worked great.
In your controller
#content.slug ||= generate_slug(6)
This will assign a value to the slug attribute if none is present
Then, in your view you can simply use
<%= f.text_field :slug %>
Options
Try after_initialize callback in your model.
Try creating a method in your model where you set defaults and call it in your new action in the controller. Also call this method if your create fails and you render new. Remember to set default only when no value exists by using the ||= operator.
Example to follow. I'm typing on phone!
I happen to use jQuery in my projects, so when I want some functionality like this, I usually use something like labelify. Then, I'd use something like <%= f.text_field :slug, :title => generate_slug(6) %>. (Hot tip, you don't need to put the #generate_slug call inside of a string if it returns something that will resolve to a string by itself, in fact it's more performant if you don't.)
If you don't want to go with jQuery approach, you might want to wrap this piece of logic in your model.
def Content < ActiveRecord::Base
def slug
self.new_record? ? self.slug_for_new_record : attributes[:slug]
end
private
def slug_for_new_record
# I don't know what you're doing in generate_slug, but it sounds model-
# related, so if so, put it here and not in a helper
end
end
If it really belongs in the view, still another option is to just make your Ruby a little bit more concise (you'll have to judge if this is more readable):
<%= f.text_field :slug, :value => (generate_slug(6) if #content.new_record?) %>
Don't forget the parens surrounding (generate_slug(6) if #content.new_record?). If you do, the if will be applied to the text_field, which is not what you want.
But there are still more ways to do it. The above line of code isn't great if your logic might change and you're pasting this code all over your rails project. When I wanted to add a 'required' class to my text fields but only if they were a new record (we had some legacy data that we didn't want to make people clean up), I created my own form builder with a required_field method that just called text_field and added a 'required' class if the item was a new record. This might seem like a work, but we have around 20 different forms, each with potentially multiple required fields, and it's a lot easier to change the business logic in one place. So if you really think this logic belongs in the view but you've got a ton of these lines of code and you don't want to have to change it in a million places, then FormBuilder is the way to go. I think this is in most cases prettier and more appropriate than a helper, but again, beauty is in the eye of the beholder. Here's my code somewhat adapted for your case:
# config/environment.rb
ActionView::Base.default_form_builder = NamespacesAreFun::FormBuilder
# lib/namespaces_are_fun/form_builder.rb
module NamespacesAreFun
class FormBuilder < ActionView::Helpers::FormBuilder
def slug_field(method, options = {})
opts = options.to_options
opts.merge!(:value => generate_slug) if self.object.new_record?
text_field(method, opts)
end
end
end
# views/.../your_view.html.erb
<%= f.slug_field :slug %>
Hopefully in all of these different approaches is one that fits your project.
I have a calendar_date_select in a view that shows a table listing all the information on a certain phone. I want to add a To: and From: date range that a user can select and update the table in the view. The structure is like this:
Usage Controller
Detail action in the usage controller that shows the call history from a certain phone.
Inside detail I want the To and from fields with a refresh button.
What is exactly happening in this code:
<% form_for :date_range do |f| %>
<%= f.calendar_date_select :start, :time => true %>
<%= f.calendar_date_select :end, :time => true %>
<%= f.submit "Submit" %>
<% end %>
Does this pass a hash to the usage controller and look for a date_range method? My current route looks like this
usage/detail/id-of-phone
I would like it to look something like this:
usage/detail/id-of-phone#start-end
So I could then (I think) extract the start and end dates from the params with just params[:start] and params[:end]. Am I doing this right, or is there a better way to get the desired result that I want.
I haven't used the calendar_date_select plugin, but you should be getting the parameters back already.
params[:date_range][:start]
params[:date_range][:end]
What you want is the url or the smart solution to get the params?
Please set the routes.rb for the url. Or you can make many method in the 'DataRange' model.
As many programmers using, save many dates in the model. But making us terrible is using the params smartly.
Such as
class Model
def start
......
end
def end
......
end
end
You can't get the params by params[:start] if you pass the params by the form. You can see the form's html for detail.
Please use the
params[:...][:start]