Publish method doesn't work properly - ruby-on-rails

I have an Entry model with a boolean column published, which is set to false by default. I wrote the following method in the model:
def self.publish
self.update(published: true)
end
and in my controller I have
def publish
#entry = Entry.find(params[:id]
#entry.publish
redirect_to entries_path
end
(I thought to make it similar to the calling of destroy method in the model). Finally, in my view I have this:
<%= link_to "Publish", entries_path, method: :publish %>
But when I click the link, the request is processed by create method and returns me the following error:
ActionController::ParameterMissing in Multiflora::EntriesController#create
param is missing or the value is empty: entry

The method is wrong in link_to as per the API so you have to mention one of valid Http methods (patch preferred in your case) , and then edit your route.rb file to transfer this patch request to your specified function like this:
patch'/entries/publish', to: 'entries#publish'
then change the "entries_path" to "entry_path"
so link code should look like this:
<%= link_to "Publish", entry_path, method: :patch%>

First thing, there is no HTTP method called :publish it should be :put or :patch
Second you need to pass id as parameter
<%= link_to "Publish", publish_entry_path(#entry) %>
Also you will need to add route for publish action
resources :events do
member do
put :publish
end
end
publish method should be instance method
def publish
self.update(published: true)
end

Thanks for all the answers, I've figured out what was my mistake, but I took a little think and decided to make it much more simple: I just added a checkbox to edit form, that sets :published attribute of entry true. Here it is:
<%=form_for(#entry, as: :entry, url: content_entry_path(#entry)) do |f| %>
# ...
<p>
<%= f.label "Publish" %> <br />
<%= f.hidden_field :published, value: '' %>
<%= f.check_box :published, checked: true %>
</p>
<% end %>
Anyways a lot of thanks for your answers! That was my lack of knowledge and I'll remember what have I done wrong

Related

Strong params and action mailer issues

I have tried to create a mailer using the following code:
routes code
resources :listings do
member do
put :lead
end
end
mailer controller code
def lead(listing)
#listing = listing
mail(to: #listing.leadrecepient, subject: "test")
end
standard controller code
def lead
Enquiry.lead(#listing).deliver
end
view
<%= form_for lead_listing_path(#listing), method: :put do |listing| %>
<%= listing.text_field :name %>
<%= listing.submit %>
<% end %>
In the context of a business directory, I want it so that there is a enquiry form on each listing page that when filled out and submitted, the information is sent to the relative listing email.
The problem however is that when I type into the form and click submit, I get the following error:
param is missing or the value is empty: listing
This seems to be because I have it in the "listing" controller which controls the showing and creation of the business listing itself. I therefore have strong params for a new listing which contains all the new listing variables:
def listing_params
params.require(:listing).permit(:fullname, :jobtitle, :email, :franchisename, :leadrecepint, :shortdescription, :longdescription, :website, :branchcount, :scale, :mininvestment, :investmentrange, :category, :hexbg, :logourl, :facebook, :twitter, :linkedin, :googleplus, :approved)
end
How do I go about fixing this? I'm a beginner if I'm honest, could really do with some help to get this mailer working! Thanks.
Strong params are for when you are submitting new resources or modifications to resources. To protect against people adding extra parameters that may circumvent security or other aspects of your application unexpectedly.
If you are adding an action to an existing resource that the user is authorized to access, which this appears to be, you want to just find the object by ID, and use it. So instead of finding it using the params filtered through listing_params, just find it like this in the controller:
def lead
listing = Listing.find(params[:id])
Enquiry.lead(listing).deliver
redirect_to listing
end
And invoke it using a simple link, instead of this:
<%= form_for lead_listing_path(#listing), method: :put do |listing| %>
<%= listing.text_field :name %>
<%= listing.submit %>
<% end %>
Just use this in your view:
= link_to 'Go!', lead_listing_path(#listing), method: :put
Nothing more to it.

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.

Rails Controllers - Adding a Custom Action

I have an Article resource and have defined resourceful routes for it. I want to create a simple page that shows the articles of the current user. I am aware that it is possible to do so by adding another action, for example 'search' to articles controller which will contain the custom code that searches for articles that have the same user id. And for the routes:
resources :articles do
get 'search'
end
But I'm not sure if adding a custom action is a good idea in this case. I'm thinking I can still use the index action (which shows all articles) and pass some sort of parameter from the url so that it can distinguish if the user wants to see all articles or just his own. But I'm not sure exactly how this can be done. Any help would be great. Thanks!
You can use the query string to pass parameters. see here
So you can pass something like .../articles?user_id=2
In your controller, just change the behavior according to the user_id parameter.
you don't need to create a new action/view for it.
You can add a small form to filter all articles or only my articles, for example:
<%= form_tag articles_path, method: :get do %>
<%= radio_button_tag :search, "all", :checked => true %>
<%= label_tag :all %><br />
<%= radio_button_tag :search, "my" %>
<%= label_tag :my_articles %><br />
<%= submit_tag "filter", name: nil %>
<% end %>
than in your controller:
def index
if params[:search] == 'my'
#articles = current_user.articles
else
#articles = Article.all
end

Why is the form posting to the wrong url?

My form looks like:
<%= form_for [:admin, #post] do |f|%>
<div style="width:660px;">
<%= f.text_field :title, :size => 150 %>
<br/>
<%= f.text_area :body, :id => "body", :rows => 15 %>
<br/>
<%= f.submit %>
</div>
<% end %>
the url currently is:
http://localhost:3000/admin/posts/21/edit
my rake routes for the admin post edit is:
edit_admin_post GET /admin/posts/:id/edit(.:format)
for some reason the edit_admin_post_path is returning:
/admin/post/the-post-title/edit
so I manually changed the post title to the id.
when I perform the update, i redirect:
if #post.update_attributes(params[:post])
redirect_to edit_admin_post_path #post
end
But again it is redirecting with the 'post-title' instead of the id.
why is this?
this is rails 3
NOTE:
For the show url, I wanted /post/my-post-title and not /post/234 so I'm not sure where I changed that b/c I see no reference for it in my code!
It sounds like you have something along these lines defined in your post model:
class Post < ActiveRecord::Base
def to_param
#{name}"
end
This will cause it to return just the name instead of the ID. Remove any to_params you have defined in your post model and see if that resolves it.
Change it to something like this:
def to_param
"#{id}-#{name}".downcase.gsub(/\W+/, "-").gsub(/^[-]+|[-]$/,"").strip
end
This will give you fairly clean URLs, such as: http://localhost:3000/admin/posts/21-my-post-title/edit and Post.find(21-my-post-title) works the same, essentially, as Post.find(21).

Routing problem with calling a new method without an ID

I'm trying to put together a form_tag that edits several Shift objects. I have the form built properly, and it's passing on the correct parameters. I have verified that the parameters work with updating the objects correctly in the console. However, when I click the submit button, I get the error:
ActiveRecord::RecordNotFound in ShiftsController#update_individual
Couldn't find Shift without an ID
My route for the controller it is calling looks like this looks like this:
map.resources :shifts, :collection => { :update_individual => :put }
The method in ShiftsController is this:
def update_individual
Shift.update(params[:shifts].keys, params[:shifts].values)
flash[:notice] = "Schedule saved"
end
The relevant form parts are these:
<% form_tag( update_individual_shifts_path ) do %>
... (fields for...)
<%= submit_tag "Save" %>
<% end %>
Why is this not working? If I browse to the url: "http://localhost:3000/shifts/update_individual/5" (or any number that corresponds to an existing shift), I get the proper error about having no parameters set, but when I pass parameters without an ID of some sort, it errors out.
How do I make it stop looking for an ID at the end of the URL?
I think that you need to tell the form tag helper you want to use PUT instead of POST
<% form_tag( update_individual_shifts_path, :method => :put) do %>
... fields ....
<%= submit_tag "Save" %>
<% end %>
Amazingly, it turns out that I was able to fix this by a combination of renaming the method and passing a dummy variable. Changes were to the lines:
form.html.erb:
<% form_tag( poop_individual_shifts_path ) do %>
routes.rb:
map.poop_individual_shifts "poop_shifts", :controller => 'shifts', :action => "poop_individual", :method => "put", :id => 4
map.resources :shifts
There I pass it an ID of 4 every time, it doesn't matter, it's not actually doing anything with the shift object it goes and grabs, it's just ... I don't know, a hack, I guess.
shifts_controller.rb:
def poop_individual

Resources