create new object with params from other object - ruby-on-rails

I have in my controller a action with #post = Post.new
and in my view the next form:
<%= form_for(#post, :method => :get, :remote => true, :url => { :controller => "posts", :action => "new_posts_from_web" }) do |f| %>
<%= f.text_field :remote_posted_url%>
<%= f.submit "Find Images" %>
I want create in action new_posts_from_web a new post with params sent by the previous form, and I have this in new_posts_from_web action:
def new_posts_from_web
#post = Post.new(params[:id])
end
but I get a new post without params.
How can I get params from a form in other action without save in database the object?

#post = Post.new(params[:post])
should work fine.

Related

Rails form rendering wrong URL after validation errors (not keeping passed parameter)

On a project show page, I pass a very simple parameter on my 'create new task' that stores which project its from:
#project.id), :class => "btn btn-info col-md-12" %>
so that when i create a new task for it, it stores it in the URL on my new task form like this:
http://localhost:3000/task/new?project_id=5
My New form is as follows:
<div class="container sign-in-register">
<div class="authform">
<%= form_for #task, :html => {:multipart => true} do |f| %>
<h3>Add a task for this project...</h3><br/>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= hidden_field_tag 'project_id', #project_id %>
<%= f.fields_for :taskrelationships do |ff| %>
<%= ff.hidden_field :taskproject_id, value: #project_id %>
<%= ff.label :task_url %>
<%= ff.text_field :task_url, class: 'form-control' %>
<% end %>
<br clear="all">
<%= f.submit "Save Task", class: "btn btn btn-info" %>
<% end %>
</div>
</div>
As you can see i'm using nested attributes in the form (I am creating both a task and a TaskRelationship. Now, when I try to save without filling out all the required fields a validation is thrown but for some reason it redirects me to:
http://localhost:3000/tasks
instead of the original:
http://localhost:3000/tasks/new?project_id=5
I have read many posts and none seem to answer this particular case. The stackO post below was close but when I try it with task instead of user it still cannot find the task_ID
Render error on new page with customize url like http://localhost:3000/education_informations/new?user_id=10
How can I have rails simply render the same exact url as I started with - it seems like this should be easy so must be missing something small.
My controller actions:
def new
#project_id = params[:project_id]
#task = Task.new
#task.taskrelationships.build
end
def create
#project = Project.find(params[:project_id])
#task = Task.new(task_params)
if #task.save
flash[:success] = "This task has been added."
#task.taskrelationships.create!(#taskrelationships_params)
redirect_to tasks_project_path(#project)
else
#task.taskrelationships.build(#taskrelationships_params)
flash[:alert] = #task.errors.full_messages.to_sentence
render :new
end
end
private
def task_params
#taskrelationships_params = params.require(:task).permit(taskrelationships_attributes: [
:task_url,
:taskproject_id
])[:taskrelationships_attributes]["0"]
params[:task].delete(:taskrelationships_attributes)
params.require(:task).permit(
:name,
:user_id,
taskrelationships_attributes: [
:task_url,
:taskproject_id
]
).merge(owner: current_user)
end
UPDATE W / ROUTES
resources :projects do
resources :reviews, except: [:destroy]
member do
get :tasks
end
end
resources :tasks
resources :taskrelationships, only: [:create, :destroy] do
post :vote, on: :member, controller: "task_relationships"
end
thanks for any assistance...
Ok firstly an explanation as to what is going on here:
When you invoke http://localhost:3000/task/new?project_id=5 you are actually being routed to the new action on the task controller (with a project_id param).
Your new action then sets the variables and rails will render the new.html.erb which contains your new task form.
When you submit the form it actually is doing a http POST to /tasks, which routes to the create action of your tasks controller. That url and http method is a result of what is generated from the form_for helper:
<%= form_for #task, :html => {:multipart => true} do |f| %>
This is why the url changes from /tasks/new?project_id=5 to /tasks
Now the create action if it fails the validation simply renders the new form - it is not redirecting anywhere - the url remains unchanged from what it was when it entered this action - meaning, it remains as /tasks.
You do not actually need to navigate to /tasks/new?project_id=5 to render the new form but what you do need to do is set #project_id in the controller so the view has access to that variable (just as it does in the new action):
def create
#project = Project.find(params[:project_id])
#task = Task.new(task_params)
if #task.save
flash[:success] = "This task has been added."
#task.taskrelationships.create!(#taskrelationships_params)
redirect_to tasks_project_path(#project)
else
#task.taskrelationships.build(#taskrelationships_params)
#project_id = #project.id
flash[:alert] = #task.errors.full_messages.to_sentence
render :new
end
end
So, to clarify the change in url is not a redirection it's just that the form is posting to a different url than /tasks/new, and this is actually just a cosmetic issue.
Now if it is a concern to you, you can change the routing to something like the following:
resources :tasks, except: [:create, :new]
post 'new_task' => 'tasks#create'
get 'new_task' => 'tasks#new'
This is mapping the POST and GET http methods to /new_task so the url appears the same for the new and create action invocations. Note you do need to change the url in the form_for helper to use this new route:
<%= form_for #task, url: 'new_task', multipart: true do |f| %>
Since Rails default behaviour in forms is with remote: true, you can move the content of the form to a partial(let's name it _my_form.html.erb), add to the controller action (let's say in create action):
respond_to do |format|
format.js {}
end
Then add a create.js.erb file where you will render the form partial
$("#form").html(
"<%= j render partial: 'my_form', locals: { entity: #entity } %>"
);
Thus, validation errors and all attributes will be accessible inside the form and there is no need to hack the "Rails approach"
I had to adapt and experiment with the currently accepted answer,
and the following ended up working well (using schools rather than tasks):
In config/routes.rb:
resources :schools do
...
end
post 'schools/new' => 'schools#create'
And create the form like:
= simple_form_for [#school], url: 'new' do |f|
Thus the path /schools/new was preserved on validation :)

Why is the Photo Id not being passed to create action?

I'm implementing likes for photos, and the id isn't being passed. I don't know why. Could someone please explain why? I feel it would help me understand rails better.
I get this error, after clicking like: "Couldn't find Photo without an ID"
On the photo show page I have this:
<%= form_for(#photolike, :url => {:controller => :photolikes, :action => 'create'}) do |f| %>
<%= f.hidden_field :photo_id, :value => #photo.id %>
<%= f.submit "like", class: "btn postbtn right" %>
<% end %>
this is the controller for photos
def show
if user_signed_in?
#comment = current_user.sent_photocoments.new(params[:photo_comment])
end
#photo = Photo.find(params[:id])
#photolike = Photolike.new
end
And in the photolikes controller, I have this:
def create
#photo = Photo.find(params[:id])
#photolike = Photolike.new(:photo_id => #photo.id, :user_id => current_user.id)
#photolike.addlike
#photolike.save
redirect_to #photo
end
def create
#photo = Photo.find(params[:photolike][:photo_id])
#photolike = Photolike.new(:photo_id => #photo.id, :user_id => current_user.id)
#photolike.addlike
#photolike.save
redirect_to #photo
end
Your submit is submitting the photo_id labeled as photo_id (in your hidden field). So your controller needs to retrieve it via params[:photo_id] rather than params[:id].

Keep params after render Ruby on Rails

I have a Project that belongs to User. In my user view I have a link to add a new project, with the parameter for the user I want to add the project to.
<%= link_to 'Add new project', :controller => "project", :action => "new", :id => #user %>
Url: /projects/new?id=62
Adding a project to a user works. The problem is when the validation fails while adding a new project and I do a render.
def create
#project = Project.new(params[:project])
if #project.save
redirect_to :action => "show", :id => #project.id
else
render :action => "new"
end
end
view:
<%= form_for #project do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.hidden_field :user_id , :value => params[:id] %>
<%= f.submit "Create project" %>
<% end %>
routes
resources :users do
resources :projects
end
How can I keep the parameter for the user after the render? Or is there some better way to do this? Been looking at a lot of similar questions but can't get it to work.
try
render :action => "new", :id => #project.id
if its not works for you, then try alternate way to pass the parameter to your render action.
This can also help you->
Rails 3 Render => New with Parameter
You shouldn't use params[:id] to assign value to this form field. Instead, add this to your #new action in controller:
def new
#project = Project.new(user_id: params[:id])
end
and then just write this in your form:
<%= f.hidden_field :user_id %>
Because #project was defined in your #new and #create actions and because it already contains a Project instance with a user_id assigned to it, the value would automatically be added to this field.

RoR differences between :url, :action, :method in form_for

There might be answers in documentation, but i don't seem to find good answers.
So among the three :url, :action, :method, what are their differences when used in form_for in Rails?
Difference between :url, :action and :method
:url
If you want to submit your form for any particular controller, any particular action and want to pass some extra parameter (use action that define in controller that you pass on controller )
for example
<%= form_for #post, :url => {:controller => "your-controller-name", :action => "your-action-name"} do |f| %>
In the above code the form is submitted to that controller(that you pass on url) and goto that (you pass on action) action. it will take defaults to the current action.
now suppose you want to pass extra parameter then for example
form_for #post, :url => { :action => :update, :type => #type, :this => #currently_editing } do |f| ...
you can pass extra parameter like :type => #type
so :url is The URL the form is submitted to. It takes the same fields you pass to url_for or link_to. In particular you may pass here a named route directly as well.
:action
form_for #post, :url => { :action => :update, :type => #type, :this => #currently_editing } do |f| ...
In the above example we pass :action if we want to submit the form in different action then we pass :action and your-action-name the form is post to that action
:method
method is used for which method you want to pass for that action. There are several methods like put,post,get ...
for example
form_for #post, :url => post_path(#post), :method => :put, ....
In the above form_for we pass :method => :put when this form is submit it will use put method
form_for is basically used on object. For example:
<% form_for #person do |f| %>
...
<% end %>
When you click submit it will go to default action like from :new to :create, :edit => :update. If you want to specify your own action then you have to use :url and :method is used to force to post or get. For example:
<% form_for #person :url => {:action => "my_action"}, :method => "post" do |f| %>
...
<% end %>
URL:
Url is the path where your form data should go.
whatever you write inside the :url symbol is considered as the path where your data should go when u click a submit button in the form.
Action:
Action is the method in your controller, in your form_for #user (where #user is a object of User model), if you say :action => create then it sumbit the data to users_controller 'create' function (def create).
You will mention this inside :url to tell that the data should go to the specifiled action.
Method:
Is http method, there are 'get', 'post', 'update', 'patch' and 'delete' method. You can learn about this in google.

Form submit says Unkown Action?

Im trying to create a form that submits to a certain action within the current controller (results_controller).
My form code is:
<%= form_tag(:controller => "results", :action => "filter", :id => "filter") do %>
And in the results_controlle.rb i have :
def filter
#setting dispatches
#dispatches = Dispatch.find_by_message_ids(params[:message_ids]) unless params[:message_ids].blank?
unless #dispatches.blank? || #input_messages.blank?
#output_messages = OutputMessage.find_by_dispatch_ids(
#dispatches.collect{|d| d.id }.uniq
)
end
respond_to do |format|
format.html #default rendering
end
end
Yet i get the error:
Unknown action
The action 'filter' could not be found for ResultsController
Any suggestions?
UPDATE
On the same page, i have a form that does work:
<%= form_tag(:controller => "results", :action => "show", :id => "show") do %>
try instead
<% form_tag(filter_result_path(), :method => :get) do %>
and add to your route table
resources :results do
member do
get 'filter'
end
end

Resources