Rails form for model function - ruby-on-rails

I need to run this function on my View somehow, and i cannot figure out how to make it, everywhere are forms with controllers. How to make it work?
models/feed.rb
class Feed < ActiveRecord::Base
def self.update_from_feed(feed_url, category)
add_feed(feed_url, category)
end
end
views/feeds/new.html.erb
<%= form_for Feed.update_from_feed(feed_url, category) do |f| %>
<%= f.text_field :feed_url %>
<%= f.text_field :category %>
<%= f.submit "Create" %>
<% end %>

Make a route in config/routes.rb file. This is where your request will go upon some event like button click or form submit. Then when you submit the form(form action will be this route's url) or when you click a button a request should go to the controller method. In the controller you can call the model methods.
For example,
I have a products controller. In the Products controller there is an action called 'search'. I will set up a route in config/routes.rb file to map to this controller action 'search'. So Rails will route all requests on this url to my Products controller's search method.
You need to setup a similar action in one of your controllers(based on design) and send request to the route that maps to this controller action
Please refer http://guides.rubyonrails.org/ for better understanding.
http://guides.rubyonrails.org/form_helpers.html

Related

How to update an existing record?

I have a Books model and it has CRUD operations. In config/routes.rb, I have declared
map.resources :books
My new.html.erb looks like as:
<%= form_for :book, url: books_path do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.submit :Add %>
<% end %>
My create method in controller looks like as:
def create
book = Book.new(authorized_params)
book.save
end
So, when I submit my form from views, request would go to the 'create' method and an record for the book gets created in database. Fair enough. Now, I want to have an edit page for book. So, my edit method in controller look like as:
def edit
#book = Book.find_by(params[:id])
render :new
end
When I go to my edit view, it automatically show the value of title in the text box, which is what I expected.. But when I try to submit the form again(ofcourse after changing the title value) it again creates a new record instead of updating it..
Something basic which I missed out in my reading? I googled about it though but did not find satisfactory answer.
The issue is that you are using the 'new' view where form has the post method. If you will check the generated routes, post will be for create method, that is adding a new record. You will have to create a new view for edit where the form target URL will be edit_book_path(#book) and method will be patch. Patch method will route to 'update' function in your controller where you will call #book.update. I am not writing the exact code, but these directions should help you achieve what you want

Rails Call Custom Controller Action from Custom Form

In a Rails project, I have the following controller action for the controller exchanges.rb:
def update_ordid
# Get the active exchange
#exchange = Exchange.find(params[:id])
# Decide which order ID field to update
active_order_field = params[:ordfld]
# Save the order ID
order_id = params[:ordid]
if active_order_field == 1 then
#exchange.order_id_1 = order_id
else
#exchange.order_id_2 = order_id
end
#active_exchange.save
respond_with(#exchange)
end
I've set up a route to this controller action:
resources :exchanges do
collection do
get 'update_ordid'
end
end
I want to call this action that accepts an order ID from a form on an exchanges show.html.erb page. I need to pass three values:
The ID of the current exchange, such as the integer in this example URL localhost:3000/exchanges/2 (This is the page the form is on)
The order ID as input from a text-field
Which of the two possible exchange fields the action should update
Next I need to create a custom form which will pass these values as parameters to the action. I haven't been able to find a good tutorial on how to do this yet, but my first thought was to set up the following:
<%= form_for(#exchange) do |f| %>
<div class="field">
<%= f.label :ordid, "Order ID" %><br>
<%= f.text_field :ordid, class: "form-control" %>
</div>
<% if #isrequestor == true %>
<%f.hidden_field :ordfld, :value => "1" %>
<% else %>
<%f.hidden_field :ordfld, :value => "2" %>
<% end %>
<div class="actions">
<%= f.submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
This gives me a NoMethodError stating the method 'ordid' is undefined. I'm guessing I need to modify the first line of code to associate the form with the custom action I've set up, but have no idea how to do so properly.
Yah, I got your point. So you wanted the following thing:
You wrote an custom action
You wanted to submit a form that action
You have registered your action in the router.
So let me answer the following solutions and find some mistakes you made in your code.
# in route.rb
resources :exchanges do
patch :update_ordid, on: :member # this is the best practice I would say,
#when you are trying to modify an existing record. So this action will only
#be reached with patch http methods
# on :member action an parameter id is required.
end
now if you generate your routes by running:
bundle exec rake routes
you will see a path like:
update_ordid_exchange /exchange/:id/update_ordid # :id parameter for exchange record
in your form set the url:
<%= form_for(#exchange, url: update_ordid_exchange_path) do |f| %>
or
<%= form_for(#exchange, url: url_for(controller: :exchange, action: update_ordid)) do |f| %>
Now then you will this form can submit this values within the parameter in your desire field.
So let me summarize things up here:
1. Setup your route properly
2. Check the url based on your route by generating rake routes command as shown above
3. Set the proper url and check if http method is correctly define in your form helper. For member actions, form helper by default use patch as http method. you just have to set the url.
Hope you understand my flow.

Trying to fire an action in my controller when a selection in a drop down menu is made but getting a no route matches error

I'm building a web interface to accompany a mobile app I'm building. I have a drop down select menu that lists a bunch locations.
On selection of a location I want to make a call to a method in my controller and grab some destinations within the location that was selected (each location has several destinations).
I then would like to render my show template with these results allowing the user to select a destination and make a booking.
This is what I have so far:
My view with a list of resorts:
<%= form_tag :url => { :action => :show } do %>
<%= select_tag :resort , options_for_select(#resorts), :prompt => 'Select Resort', :onchange => 'submit()' %>
<% end %>
Controller:
class HomeController < ApplicationController
def index
#resorts = ["A","B", "C", "D", "E"]
end
def new
end
def edit
end
def create
end
def show
#activities = Parse::Query.new("Activity").tap do |a|
a.eq("resort", params[:resort])
end.get
end
end
Just slightly confused. Using form_for makes more sense to me with CRUD in mind and also because the form is object based.
I'd like to just take the selected resorted and pass it into a method in my controller that goes into a database and grabs a bunch of destinations. I then want to list these destinations on my show page where a user can click and be taken to another page where they can make a booking at that destination.
My above code doesn't work. I have resources :home in my routes file.
However when I try to load my page with the form I get:
No route matches {:action=>"show", :controller=>"home"} missing required keys: [:id]
How do I pull this off?
I went on my lynda account and pulled up a rails essential tutorial which I'll have to use to refresh my memory some time tomorrow but the tutor doesn't cover use of select_tag.
Would appreciate some help here
Thanks for your time
So a few thoughts. Not sure why you are using form_tag and also not sure why you aren't using Rails idiomatic conventions.
Declare a resource in your routes for #resorts, like so:
resources :resorts
Then just use Rails form_for helper like:
<%= form_for #resorts, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.select :resort, (insert your other options) %>
<%= f.submit "Create" %>
<% end %>
I have not tested the above code, so play around with it, but that should work.
However, let me save you some headache. Checkout SimpleForm.
For your models, you would want to setup an association between your locations and destinations.
class Location < ActiveRecord::Base
belongs_to :resort # or whatever the relation is
has_many :destinations
end
class Destination < ActiveRecord::Base
belongs_to :location # This assumes there is just a one-to-many relationship between Location and Destination
end
Make sure you have a LocationsController with all the actions.
In this case, your SimpleForm form would look something like this:
<%= simple_form_for #locations do |f| %>
<%= f.input :name %>
<%= f.association :password %>
<%= f.button :submit %>
<% end %>
That approach will make your life much easier. Take a look at the collections methods in Simple Form. Rails can make your life difficult with the built in form helpers.
Hope that helps!
In your routes, add
get '/choose_resort' => 'home#show' #you can name the get whatever
Then in your form...
<%= form_tag choose_resort_path do %>
That being said... you should have your query at a separate endpoint, and redirect to the show page. That should get you moving, methinks.
The show action needs an id of the object you are showing. Change your controller:
class HomeController < ApplicationController
def index
#resorts = [["A",1], ["B",2], ["C",3], ["D",4], ["E",5] ]
end
And your view
<%= select_tag :id , options_for_select(#resorts), :prompt => 'Select Resort', :onchange => 'submit()' %>
That gives your show action the proper resort id. You'll have to adjust that action to find the right activities relevant to the resort.

How do I link to the create function in my controller in Ruby on Rails?

I've got this line in my routes.db file:
map.resources :things
I'm trying to create a link that will create a new thing. So far I've got
<%= link_to "add thing", things_path (:thingName => key)%>
But I'm getting this error message:
Unknown action
No action responded to index. Actions: create and new
How do I do the link_to line so that it links to the create method instead of the index method? Thanks for reading.
Do you want to link to the new or the create action? The new action is:
<%= link_to "add thing", new_thing_path %>
The create action would not make sense here, since you don't have any data to inject into the new object? Unless I'm missing something...
You probably dont want to create a resource through a link like that. Links are HTTP GET requests, which can be cached, and search engines will follow that link, resulting in database records being created incorrectly. You should only use HTTP POST requests to create a resource. To do that you need a form. If you already know the data to pass, you can use hidden_field to pass additional data
<% form_for Thing.new(:thing_name => key ) do |f| %>
<%= f.hidden_field :thing_name %>
<%= f.submit %>
<% end %>

embeddable component in views or how to call a different controller

Let's say you have a form that has its own controller. Is there any way to embed this form in different views (governed by other controllers)? As far as I understand partial templates carry only logic in the Ruby code that is inside the template. I am thinking more of a full-blown component where maybe you can call its controller.
The form is not driven that directly by the controllers. Yeah this is the price of all this magic.
To clarify a bit:
You type in your browser http://yourhost/posts
Your request (GET /posts) hits the router, then your router says that the /post urls belongs to the PostsController and the action is index
Then your controller executes the index method, do your business logic (loads the posts from the database, for example)
loads the view (views/posts/index...) and run it by 'substituting' all the instance variables and stuff defined in your controller (eg #posts = Post.all) that you have in it
then you see the view rendered with a list of posts (if in the view you have something similar to #posts.map{|p| p.title}.join(", ") )
yes I know it's not the best /posts view in the world but it's only to grasp the idea
The same goes for form, your form tag (for example form_for) gets an instance from the controller (let's say #post) and (in edit mode) gets filled with your Post attributes.
Then when you (edit something and) click the submit button it makes a request (by default a PUT to /posts) passing all the values in the form, then your controller gets the (POST) values of the requests (the ones you see in the server log) and makes his work (like saving the post's datas)
and because of this in a controller you can use the method
render :controller => :foo, :action => :bar
to render another controller action different from the default one
Hope this will be useful!
You can create a form in any view to call any controller. In a RESTful app, you can usually just pass an empty object (using the Posts/Commments example from makevoid)
<% form_for #new_comment do |f| %>
<%= f.text_area :text %>
<%= f.submit %>
<% end %>
This form should route to the create action on CommentsController. From there, you could use redirect_to :back in order to get back to the view that triggered this controller. This does have some validation issues I think though.
If you are non-RESTful, you can use the old form_for style:
<% form_for :comment, #new_comment, :url => { :controller => "comments", :action => "create" } do |f| %>
<%= f.text_area :text %>
<%= f.submit %>
<% end %>
For either of these examples, you need to have the #new_comment, which you would create in your PostsController:
def show
#post = Posts.find(params[:id])
#new_comment = #post.comments.build
end

Resources