Ruby On Rails: post method behind a file - ruby-on-rails

I'm trying to post a integer method behind a file in a post method in ruby on rails.
For this, I use hidden_field_tag, but it send a json to controller and I don't know how can I use this json.
I try below code:
<%= form_tag import_tasks_path, multipart: true do %>
<%= file_field_tag :file %>
<%= hidden_field_tag :owner_id, :value => 1 %>
<%= submit_tag "Import" %>
<% end %>
In controller, I want use file and 1 in a function:
Task.import(params[:file], params[:owner_id])
but the value of params[:owner_id] is: {value=>1}.
how can I post just value? like:
Task.import(params[:file], 1)
I try any way, but don't find solution, like:
view:
<%= hidden_field_tag :owner_id, 1 %>
controller:
params[owner_id]
or:
params[:owner_id].dup

This should be enough :
<%= hidden_field_tag :owner_id, 1 %>
If you can't access it in your desired controller with params[:owner_id], it might have a parent. Try to do a params.inspect in your controller, it will reveal its location.
BONUS
The reason it is giving "{value=>1}" when you give :value => 1, is that it gets into the hidden_field_tag's value arg as a hash, and they should be calling to_s on it.

Related

Rails how to get query string from get action in post action?

I have a url like this http://example.com/myController?key=12345
In my controller myController, i can access the key value with params[:key], but when i submit a form, i want to get that same key in the create method, but the params[:key] is null.
How can i access params[:key] in my post action create?
You might indeed add a hidden field.
If you find yourself adding many of those because you need to have the value available in more and more actions, consider setting it within the session as (e.g.) session[:current_key]
You can pass the info along by a hidden_field_tag. So your code would be like:
<%= form_for #model do |f| %>
<%= hidden_field_tag 'key', params[:key]
# other form code
<%= f.submit %>
<% end %>
You can add a hidden field to your form and set its value to params[:key]. Then it will be available in the params you get from the form.
If you're using Simple Form:
<%= simple_form_for #model do |f| %>
...
<%= f.input :field_name, :as => :hidden, :input_html => { :value => params[:key] } %>
<%= f.button :submit %>
<% end %>
Add a new hidden field to pass via params, when you submit the form your action is changed or called again params hash is recreated; what you can do is pass the value via hidden field in the form as follow,
<%= simple_form_for #model do |f| %>
# your remaining form fields
<%= f.input :field_name, as: :hidden, :input_html: { value: params[:key] } %>
<%= f.button :submit %>
<% end %>

Rails Simpleform with non-model inputs

I have a normal form using simpleform. Now I'd like to add an input that does not have any corresponding field in the model, it will be processed by the controller. I tried
<%= simple_form_for #obj do |f| %>
<%= f.input :name %>
<%= f.input :attr, as: :string %> <-- should just send "attr" as post data
<% end %>
but this gives a Method not found: attr_not_in_obj error. I could obviously use the standard rails helpers, but then I will miss all of the simpleform HTML around the input, and copying doesn't quite seem right.
In short:
I'm looking for something like simpleform version of rails tag helpers, without any connection to a model. How do I add inputs that do not correspond to model attributes?
Why don't you add:
attr_accessor :attr
to your model's class definition? This way your code:
<%= f.input :attr %>
should work.
OR
If this solution isn't suitable, you can always pass some value to your input method directly:
<%= f.input :attr, input_html: {value: 'something'} %>
Say you wanted to use a rails form helper but still wrap it in SimpleForm goodness? You can, by calling input with a block like so:
<%= simple_form_for #obj do |f| %>
<%= f.input :name %>
<%= f.input :attr do %>
<%= text_field_tag 'attr' %>
<% end %>
<% end %>
Yes, below are quote from simple_form wiki
String Input
app/inputs/fake_input.rb:
class FakeInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
template.text_field_tag(attribute_name, nil, merged_input_options)
end
end
Then you can do <%= f.input :thing, as: :fake %>

rails - passing :params in url

I am stuck one more time ... and one more time I suspect it's a stupid syntax problem:
I want to pass 2 vaiables in the url with my super simple search form.
I was expecting a URL like this:
http://mydomain/categories/search?search=pdf&os=2
But I get this:
http://mydomain/categories/search?search=pdf&os[]=
I thought it should work like this:
<% form_tag search_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= hidden_field :os, params[#category.id] %>
<%= submit_tag "Search", :name => nil %>
<% end %>
... but well, it didn't do it ...
Does anyone know where I am going wrong?
Thanks!
Val
You need to modify the line a bit, using hidden_field_tag:
<%= hidden_field_tag :os, :value => #category.id %>
See the hidden_field_tag documentation for more information.
<%= hidden_field :os, params[#category.id] %>
Is going to access a key in the params hash with #category.id, is there such a key? Looks like not, as its returning nil.
Seems like you want something to the effect of
<%= hidden_field :os, #category.id %>

virtual model and form_for (or formtastic)

Sometimes we need form without model creation - for example search field or email, where should be send some instructions. What is the best way to create this forms? Can i create virtual model or something like this? I'd like to use formtastic, but not form_tag.
Firstly, Formtastic doesn't need a model in all cases, although it certainly works best and requires less code with a model.
Just like Rails' own built-in form_for, you can pass in a symbol instead of an object as the first argument, and Formtastic will build the form and post the params based on the symbol. Eg:
<% semantic_form_for(:session) do |f| %>
...
<% end %>
This will make the form values available to your controller as params[:session].
Secondly, a model doesn't mean an ActiveRecord model. What I mean is, Formtastic will work with any instance of a class that quacks like an ActiveRecord model.
A classic example of this that many people are using Authlogic for authentication with Formtastic. Part of Authlogic is the idea of a UserSession model, which works fine:
Controller:
def index
#user_session = UserSession.new
end
Form:
<% semantic_form_for(#user_session) do |f| %>
<%= f.input :login %>
<%= f.input :password %>
<% end %>
This will make your form data available in your controller as params[:user_session].
It's really not that hard to create a model instance to wrap up the concerns of your model. Just keep implementing the methods Formtastic is expecting until you get it working!
default_language.rb
class DefaultLanguage
attr_accessor :language_id
end
foo_controller.rb
def index
#default_language = params[:default_language] || Language.find_by_name("English")
end
index.erb
<% semantic_form_for #default_language do |form| %>
<% form.inputs :id => 'default_language' do %>
<%= form.input :id,
:as => :select,
:collection => #languages,
:required => false,
:label => "Primary Language:",
:include_blank => false %>
<% end %>
<% end %>
I used AJAX to post the form when the value changed.
Or you simply create a form with form_for and leave the model reference blank.
for example
<% form_for "", :url=>some_url do |f| %>
<%= f.text_field "some_attribute" %>
<%= submit_tag "submit" %>
You can fetch the values by simply saying params[:some_attribute] in your controller.

Multiple links on a Rails view that each perform different actions - how best to handle this?

One of the things I'm doing includes several links on the show view. For instance, I have a link (or button) for "Accepting", and another one for "Rejecting". Click on Accept, and the model updates the is_accepted field as true, click on Reject, and the is_accepted field is false.
Now, how best do I handle this? In ASP.NET, I would have simply created a LinkButton and written a handler, but Rails doesn't work that way, so I'm trying to figure out how to essentially replicate what a LinkButton would do.
Right now, I'm coding two forms on the same view, nearly identical, that look like this:
<%= form_for #thing do |f| %>
<%= hidden_field_tag 'thing[is_accepted]', '1' %>
<%= f.submit "Accept" %>
<% end %>
<%= form_for #thing do |f| %>
<%= hidden_field_tag 'thing[is_accepted]', '0' %>
<%= f.submit "Reject" %>
<% end %>
This feels weird to me, but I can't seem to find anything that says this is the wrong way to do it.
I could, I assume, dry things up by using a partial and/or a helper method, but I wanted to make sure I'm on the right track and not doing something totally wrongly.
You can give your submit tag a name.. ie
<%= form_for #thing do |f| %>
<%= hidden_field_tag 'thing[is_accepted]' %>
<%= f.submit "Accept", :name => 'accept' %>
<%= f.submit "Reject", :name => 'reject' %>
<% end %>
Then you can detect the name in params[] and skip the '1'/'0' value.
I think you're going about it the right way. One way to clean up your forms is by using the model form helpers all the way through, so you'd end up with something like
<%= form_for #thing do |f| %>
<%= f.hidden_field :accepted, :value => true %>
<%= f.submit "Accept" %>
<% end %>
<%= form_for #thing do |f| %>
<%= f.hidden_field :accepted, :value => false %>
<%= f.submit "Reject" %>
<% end %>
But other than that, it looks like the right way to go about it. I would suggest against creating new methods to do this, because you're not doing anything outside of normal web requests (updating a model in this instance).
Using the submit tag as the switch and detecting it in params[] is also a good way, but I usually prefer to keep my controllers as vanilla as possible. In the end, both of these ways would end up with the same amount of 'stuff' in the UI, so whichever style you'd rather use should be fine.
Depending on how you want your UI to work you might consider link_to_remote (part of the prototype helper) - you can specify an action, params etc, and have it return some JS that gets run.
If you're using map.resources in your routes.rb you should be able to do something like this:
map.resources :things, :member => {:accept => :get, :reject => :get}
Then in your controller:
def accept
#thing = Thing.find(params[:id])
#thing.is_accepted = true
#thing.save
end
def reject
#thing = Thing.find(params[:id])
#thing.is_accepted = false
#thing.save
end
And finally in your view:
<%= link_to 'Accept', accept_thing_url(#thing) %>
<%= link_to 'Reject', reject_thing_url(#thing) %>
Or if you are using Ajax:
<%= link_to_remote 'Accept', :url => accept_thing_url(#thing) %>
<%= link_to_remote 'Reject', :url => reject_thing_url(#thing) %>

Resources