rails: param.require(:model) ActionController::ParameterMissing OR Empty - ruby-on-rails-4

My goal is to create a new Reminder record with hardcoded values:
In the following structure:
Reminder belongs_to :deck
Deck has_one :reminder, dependent: :destroy
In deck controller I get to the view like this :
def repitition_alerts
#deck = Deck.find(params[:id])
#reminder = Reminder.new
end
On that page I want to create a new Reminder with a link_to:
<%= link_to "make alerts", deck_reminders_path(#deck, #reminder, {:action => :create}, next_alert: 'soon', interval: false), :method => :post %>
I am getting the following error in the browser:
ActionController::ParameterMissing in RemindersController#create
From terminal output:
ActionController::ParameterMissing (param is missing or the value is empty: reminder):
app/controllers/reminders_controller.rb:34:in `reminder_params'
app/controllers/reminders_controller.rb:19:in `create'
In the reminders_controller.rb I have:
def reminder_params
params.require(:reminder).permit(:deck_id, :interval, :next_alert, :alerts)
end
If I understand it correctly. Rails don't see the #reminder passed into it? But it's in the page. I can put this on the same page <%= #reminder %> and I see #<Reminder:0x007fc012fa00a8> rendered out on the page. So the object itself exists.
(Rails 4.2)

You need the params for reminder nested under :reminder. Switch your link_to to this:
<%= link_to "make alerts", deck_reminders_path(
#deck,
#reminder,
{:action => :create},
reminder: {
next_alert: 'soon',
interval: false
}
), :method => :post %>

Related

Multiple images upload using paperclip gem and update image

I'm trying to upload multiple images to my system. I'm using paperclip gem to deal with it, but I'm having 2 problems.
1 - how to save multiple images in a hash?
2 - how do I update/insert the image?
The user has to select all the products that he wants to update (check_box_tag) and select all the images that he wants to upload. If the product has the same name as the image, it saves the alteration.
This is my altprod function in product_controller. It deals with the actions, but the only part that matters is the import:
def altprod
case params[:commit]
(...)
when "Import"
slctProd = params[:selected_products]
slctProd.each do |prod|
if prod.eql? File.basename(params[:image].original_filename, ".*")
#Here is the problem :'(
Product.where(code: prod).update(image: :image)
end
end
redirect_to products_url, notice: 'Insert/update images succeeded.'
end
end
And here is the code to upload the files:
<%= form_tag altprod_products_path, multipart: true do %>
(...)
<%= file_field_tag :image, multiple: true %>
<%= submit_tag "Import", method: :post %>
<br/>
(...)
<% end %>
Thanks for the help :)
Try this.
Here avatar is image field name.I think you ran paperclip command right to generate image model.
#Product Controller
if params[:images]
params[:images].each { |image|
#product.create_image(avatar: image, user_id: current_user.id)
}
end
Form
<%= file_field_tag "images[]", type: :file,:required => true %>
Image Model
belongs_to :product
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png",
size: { in: 0..1000.kilobytes },
url: "/system/:hash.:extension",
hash_secret: "abc123"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
validates_attachment :avatar, :presence => true,
:size => { :in => 0..5000.kilobytes}
Product Model
has_many :images, dependent: :destroy
This type of hash is created by paperclip
[#<ActionDispatch::Http::UploadedFile:0x007f90b22c5340 #tempfile=#<Tempfile:/tmp/RackMultipart20170929-7646-eqf009.jpeg>, #original_filename="job_post.jpeg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"book_image[]\"; filename=\"job_post.jpeg\"\r\nContent-Type: image/jpeg\r\n">, #<ActionDispatch::Http::UploadedFile:0x007f90b22c52f0 #tempfile=#<Tempfile:/tmp/RackMultipart20170929-7646-1qhrsy8.jpeg>, #original_filename="query.jpeg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"book_image[]\"; filename=\"query.jpeg\"\r\nContent-Type: image/jpeg\r\n">]

Kaminari paginate at different controller mixing with devise (check answer)

I have 2 non nested models, User and Record. The goal is to paginate the #user.records called #records at users/show
Here is the Record part:
at app/models/record.rb
class Record < ActiveRecord::Base
default_scope lambda { order('records.created_at DESC') }
paginates_per 48
end
I am using Kaminari at records/index and works great. Problem is to use it at users/show
Here the app/controllers/users_controller.rb
def show
#user = User.find(params[:id])
#records = #user.records.page params([:page])
# Not working alternative:
# #records = #user.records.page(params[:page]).per(48)
end
Here is the view that triggers the display, is the listing rendered inside users/show...
<% #records.each do |record| %>
<%= link_to (image_tag record.thumbnail.url(:list)), record %>
<%= link_to record.name, record %>
<% end %>
<%= paginate #records %>
Errors are very interesting. As it is, error is:
No route matches {:action=>"show", :controller=>"users", :controllers=>{"registrations"=>:registrations}, :id=>"1", :page=>nil}
Meaning paginate #records is building a request to Active Record that hopes to find an action I do not have in that controller (I am using devise). So at Kaminari instructions says is possible to pass the params, like this:
<%= paginate #records, :params => { :controller => 'foo', :action => 'bar' }, :remote => true %>
Then the error becomes like this:
No route matches {:action=>"remote_records_pagination", :controller=>"records", :controllers=>{"registrations"=>:registrations}, :id=>"1", :page=>nil}
I have a remote_recors_pagination defined at records_controller, renders records_paginate_remotely.js, but the pagination method does not find it. Why it keeps showing :controllers registrations?
Finally, to change the view like this:
<%= paginate #user.records %>
<% #user.records.each do |record| %>
<%= link_to (image_tag record.thumbnail.url(:list)), record %>
<%= link_to record.name, record %>
<% end %>
<% end %>
Produces an undefined method error.
Should not the example be working with or without js file? Any help?
Thanks.
I found a solution. I am posting an answer because the problem was on routes and the mix with devise, common combo that more people may find.
So, routes was like this:
devise_for :users
resources :users, only: :show, , :controllers => { :registrations => :registrations } do
member do
get :following, :followers
end
end
To change it to this:
devise_for :users, :controllers => { :registrations => :registrations }
resources :users, only: :show do
member do
get :following, :followers
end
end
allows the paginate command interact with Active Record normally. Devise first test seems ok.

Rails comments gem Acts_as_commentable on pins

I have a rails app where users can upload pins, I want to use the [acts_as_commentable_gem][1] to allow users to comment pins, here is my config:
app/models/pin.rb
class Pin < ActiveRecord::Base
acts_as_commentable
end
app/controlers/pins_controller.rb
def show
#pin.find params[:id]
#comment = #pin.comments.new
end
app/views/pins/show.html.erb
<%= form_tag "/pins/add_new_comment" do %>
<%= hidden_field_tag "id", post.id %>
<%= text_area_tag "comment[comment]" %>
<%= submit_tag "Pin Comment" %>
<% end %>
app/models/comment.rb
class Comment < ActiveRecord::Base
include ActsAsCommentable::Comment
belongs_to :commentable, :polymorphic => true
default_scope -> { order('created_at ASC') }
# NOTE: install the acts_as_votable plugin if you
# want user to vote on the quality of comments.
#acts_as_voteable
# NOTE: Comments belong to a user
belongs_to :user
end
app/controllers/pin_controller.rb
def add_new_comment
pin = Pin.find(params[:id])
pin.comments << Pin.new(params[:comment])
redirect_to :action => :show, :id => pin
end
finally in my config/routes
get "/pins/add_new_comment" => "pins#add_new_comment", :as => "add_new_comment_to_pins", :via => [:pin]
But I run to a routing error:
undefined local variable or method `acts_as_commentable' for PinsController:Class
I am really not sure where this error come from, any ideas?
I am not really sure but you route shouldn't be like
get "/pins/:id/add_new_comment" => "pins#add_new_comment", :as => "add_new_comment_to_pins"

Rails 4 - update_attributes not updating

I have the following form:
<%= form_for #user, :html => {:class => 'edit-form' }, :url => {:action => 'add_group', :id => #user.id }, :remote => true do |f| %>
<%= f.select :group_ids, Group.all.collect {|x| [x.name, x.id]}, {}, :class => 'multiselect', :multiple => true %>
<button type="submit" id="submit_it" class="btn btn-primary">Submit</button>
<% end %>
And in my controller:
def add_group
#user = User.find(params[:id])
unless #user.update_attributes(option_params)
respond_to do |format|
format.html
format.js
end
end
end
def option_params
params.require(:user).permit!
end
And thus, when the form is submitted, I do get a response with my "update.js.erb" file, and the following shows up in the console:
Started PATCH "/user_management/add_group?id=41" for 123.45.67.89 at 2014-07-07 22:58:38 +0000
Processing by UserController#update as JS
Parameters: {"utf8"=>"✓", "user"=>{"group_ids"=>["", "3", "4"]}, "multiselect"=>"4", "id"=>"add_group"}
Rendered user/update.js.erb (0.1ms)
Completed 200 OK in 13ms (Views: 11.9ms | ActiveRecord: 0.0ms)
But, nothing actually gets updated in the database.
There are no validations in my model that would be causing this not to update.
My model relationships are such:
class User < ActiveRecord::Base
has_many :group_assignments
has_many :groups, through: :group_assignments
end
class Group < ActiveRecord::Base
has_many :group_assignments
has_many :users, through: :group_assignments
end
class GroupAssignment < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
Any ideas on why this would not be updating?
Update
I thought it might be because the form is loaded via AJAX and there is no CSRF tags. So I added <%= hidden_field_tag :authenticity_token, form_authenticity_token %> to the form. Now, the authenticity token is in the params.
And thus, when the form is submitted, I do get a response with my "update.js.erb" file, and the following shows up in the console... But, nothing actually gets updated in the database.
Well, yes. Your code says, "unless the attributes are updated successfully, respond to html and js." And since the attributes aren't updated, it renders the template that corresponds to the request format. (For this reason, I try to use if as much as possible, instead of unless. It makes the code easier to read and understand.)
One method you can use to get more information is to change the method to update_attributes!. This will make it so that, instead of simply returning false, the method will raise an exception if the record is invalid for some reason.
As a side note, you should avoid using permit!. The entire point of strong parameters is that you make conscious decisions about which attributes to allow.

Nested attributes using paperclip rails 4

I am new to rails and I am trying to work with nested attributes.
The main idea is to have a a deal(offer) model, a deal will have multiple deal_photos from paperclip.
I have already watched Ryan's Railscast for nested forms and read many articles with many tips regarding problems on the same issue but still it doesn't work for me.
Here is my Implementation:
class Deal < ActiveRecord::Base
belongs_to :user
has_many :deal_photos, dependent: :destroy
accepts_nested_attributes_for :deal_photos
end
class DealPhoto < ActiveRecord::Base
belongs_to :deal
has_attached_file :photo, :styles => { :large => "600x170", :medium => "250x250!", :thumb => "100x100>" }, :default_url => lambda { |photo| photo.instance.set_default_url}
def set_default_url
ActionController::Base.helpers.asset_path('missing.png')
end
end
In my deals controller:
class DealsController < ApplicationController
def new_deal
#deal=Deal.new()
#user= User.find(params[:id])
3.times { #deal.deal_photos.build }
end
def create
#deal = Deal.new(deal_param)
#user= User.find(params[:user_id])
if #deal.save
#user.deals << #deal
flash[:notice]="Thank you"
end
end
def edit
#deal=Deal.find(params[:deal_id])
3.times { #deal.deal_photos.build }
end
def update
#deal=Deal.find(params[:id])
if #deal.update_attributes(deal_params)
flash[:notice]="Deal updated successfully"
end
end
private
def deal_params
params.require(:deal).permit(:title, :description, :contact_num, :user_id, :deal_photos_attributes => [ :id, :caption, :photo, :deal_id])
end
Finally in my form for a new deal:
<%= form_for(:deal, :url=>{:action=>'create', :user_id=> #user.id}) do |f| %>
<label>Title<b style="color:red;">*</b>
<%= f.text_field(:title, :placeholder=>"") %>
</label>
------------more fields---------------------
<%= f.fields_for :deal_photos do |builder| %>
<div>
<%= builder.label :caption, "Image Caption" %>
<%= builder.text_field :caption %>
<%= builder.label :photo, "Image File" %>
<%= builder.file_field :photo %>
</div>
<%end%>
<%= button_tag("Create", :class=> "secondary button", :button_type => "submit") %>
(I have migrated the db for deals_photo to accept paperclip)
The above, creates a form with all fields but instead of 3 inputs for file upload shows only one. It creates 3 empty associations #deal.deal_photos but even if I choose one image to upload from the form it doesn't save it.
If you have any useful advices or another similar question please help!
What's in your deal_param method?
Do you permit deal_photos' attributes in it?
If no then do something like
def deal_params
params.require(:deal).permit(deal_attr1, deal_attr2,...., deal_photos_attributes: [:deal_photo_attr1, ...])
end
Also, do you get a deal_id in your deal_photos in view?
Finally, I was able to solve the problem in the new_deal.html.erb when I replaced the:
<%= form_for(:deal, :url=>{:action=>'create', :user_id=> #user.id}) do |f| %>
with
<%= form_for(#deal, :url=>{:action=>'create', :user_id=> #user.id}) do |f| %>
What is changed is that the second line is for the specific new deal instance. Maybe the reason that the first was not working is that the deal_photos didn't get the deal_id, as Alexphys said. But still I haven't figure out the exact reason.