Show list of attachments using Paperclip in Rails Application - ruby-on-rails

I am having issues with paperclip in my rails application. I am able to attach multiple files (PDFs) to my form, but when I try to show more than 1 attachment in the show.html.erb file I get errors.
The code that works in the edit and new views:
<%= f.fields_for :assets do |asset| %>
<% if asset.object.new_record? %>
<%= asset.file_field :document %>
<% end %>
<% end %>
</div>
<div class="existingPaperclipFiles">
<% f.fields_for :assets do |asset| %>
<% unless asset.object.new_record? %>
<div class="thumbnail">
<%= link_to( image_tag(asset.object.document.url(:thumb)), asset.object.document.url(:original) ) %>
<%= asset.check_box :_destroy %>
</div>
<% end %>
<% end %>
</div>
I have created a separate assets model to keep all the attachments related to my equipment model. When I create a "link_to asset.object.document.url" in the show view I get NoMethod errors. I want to attach both .doc, PDF, and image files to my application if there is a better way than paperclip please help!
The assets model:
class Asset < ActiveRecord::Base
belongs_to :equipment
has_attached_file :document, :styles => {:thumb => '150x150#', :medium => '300x300#', :large => '600x600#' }
end
The equipment model:
class Equipment < ActiveRecord::Base
validates :equipment_id, presence: true
validates :location, presence: true
has_many :assets, :dependent => :destroy
accepts_nested_attributes_for :assets, :allow_destroy => true
end
My equipment_controller:
class EquipmentController < ApplicationController
def index
#equipment = Equipment.paginate(page: params[:page])
end
def show
#equipment = Equipment.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #equipment }
end
end
def new
#equipment = Equipment.new
5.times {#equipment.assets.build}
end
def create
#equipment = Equipment.new(params[:equipment])
respond_to do |format|
if #equipment.save
format.html { redirect_to #equipment, notice: 'Equipment was successfully added.' }
format.json { render json: #equipment, status: :created, location: #equipment }
else
format.html { render action: "new" }
format.json { render json: #equipment.errors, status: :unprocessable_entity }
end
end
end
def edit
#equipment = Equipment.find(params[:id])
5.times {#equipment.assets.build}
end
def update
#equipment = Equipment.find(params[:id])
respond_to do |format|
if #equipment.update_attributes(params[:equipment])
format.html { redirect_to #equipment, notice: 'Equipment was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #equipment.errors, status: :unprocessable_entity }
end
end
end
def destroy
#equipment = Equipment.find(params[:id])
#equipment.destroy
respond_to do |format|
format.html { redirect_to equipment_url }
format.json { head :no_content }
end
end
private
def correct_user
#Equipment = Equipment.find(params[:id])
redirect_to(root_path) unless current_user?(#Equipment)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
Any help is greatly appreciated.

You didn't give the code for the show view where you're having the error, but you should be able to do something like this to show thumbnails with links to the original files:
<% #equipment.assets.each do |asset| %>
<%= link_to image_tag(asset.document.url(:thumb)), asset.document.url(:original) %>
<% end %>
I'm not sure why you have "object" in your Paperclip URLs, as I haven't seen that format used for Paperclip.

I actually was able to figure this out by doing the following:
<% for asset in #equipment.assets %>
<p>
<%= link_to asset.document_file_name,
asset.document.url(:original) %>
</p>
<% end %>

Related

collection_select is not creating the association table

I'm currently trying to add a collection_select of ranches to my staff
And I saw that it's better to create an extra table to make this association.
And I follow some tutorial, but is not working on my side
This is my code :
Staffs/_form :
<%= form_for(#staff) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= fields_for(#staff_ranch) do |x| %>
<div class="field">
<%= x.collection_select(:ranch_id, #all_ranch, :id, :name, { }, {:multiple => true}) %>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My models :
- Ranch :
has_many :ranchstaffs
has_many :staffs, :through => :ranchstaffs
- Staff :
has_many :ranchstaffs
has_many :ranches, :through => :ranchstaffs
-Ranchstaff :
belongs_to :ranch
belongs_to :staff
Staff controller :
class StaffsController < ApplicationController
before_action :set_staff, only: [:show, :edit, :update, :destroy]
# GET /ranches
# GET /ranches.json
def index
#staffs = current_user.staffs
end
# GET /ranches/1
# GET /ranches/1.json
def show
end
# GET /ranches/new
def new
#staff = Staff.new
#all_ranch = current_user.ranches
#staff_ranch = #staff.ranchstaffs.build
end
# GET /ranches/1/edit
def edit
end
# POST /ranches
# POST /ranches.json
def create
#staff = Staff.new(staff_params)
#staff.update(user_id: current_user.id)
respond_to do |format|
if #staff.save
format.html { redirect_to #staff, notice: 'Staff was successfully created.' }
format.json { render :show, status: :created, location: #staff }
else
format.html { render :new }
format.json { render json: #staff.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /ranches/1
# PATCH/PUT /ranches/1.json
def update
respond_to do |format|
if #staff.update(staff_params)
format.html { redirect_to #staff, notice: 'Staff was successfully updated.' }
format.json { render :show, status: :ok, location: #staff }
else
format.html { render :edit }
format.json { render json: #staff.errors, status: :unprocessable_entity }
end
end
end
# DELETE /ranches/1
# DELETE /ranches/1.json
def destroy
#staff.destroy
respond_to do |format|
format.html { redirect_to staffs_url, notice: 'Ranch was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_staff
#staff = Staff.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, :ranch_id)
end
end
Can you explain me why the model ranchstaff was not created after a creation of a new staff ?
As you are using fields_for you are using nested form but you are not permitting the parameters properly. First make change in your form:
<%= f.fields_for(#staff_ranch) do |x| %>
<div class="field">
<%= x.collection_select(:ranch_id, #all_ranch, :id, :name, { }, {:multiple => true}) %>
</div>
<% end %>
And then in your controller:
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, ranchstaff_attributes: [ranch_id: []])
end
And in your Staff model write:
accepts_nested_attributes_for :ranchstaffs
Then your ranchstaff should be created when the User is being created.
Your ranch_id is coming in an array. So u have to specify that ranch_id would be array in strong parameters.
so your staff_params method would look like this
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, :staff_ranch_attributes =>[:ranch_id => []])
end

Storing Carrierwave as json into an existing jsonb column

I'm not sure if this is even possible using Carrierwave, I'm still learning my way around Ruby and Rails so bear with me.
I have a simple form to record observations. Each observation has data that can be recorded against it and I store this in a JSONB column within the observation (I will eventually store multiple sets of data against an observation). I want to be able to upload an image through Carrierwave and store it with the data within the JSONB column rather than saving it to its own column. So my saved data for this column would be like this for example...
{
"ph":"",
"ecoli":"",
"nitri":"Less than 0.5",
"oxygen":"",
"clarity":"bottom visible",
"nitrates":"Less than 0.5",
"conditions":[
"Wildlife Death",
"Shoreline Alterations",
"Water Quality"
],
"observed_on":"2015-06-21T04:45",
"invasive_species":[
"Phragmites",
"Loosestrife",
"Dog-Strangling Vine"
],
"phosphates_threshold":"less than 0.2",
"image":[
"url": "the/url",
"thumbnail: "the/thumbnail/url",
"medium":"the/thumbnail/url"
.....
]
}
Some of the supporting code for reference...
observation.rb
class Observation < ActiveRecord::Base
belongs_to :user
has_many :comments
serialize :observation_data, HashSerializer
store_accessor :observation_data
end
observation_data.rb - tableless model
class ObservationData < ActiveRecord::Base
belongs_to :observation
mount_uploader :image, ImageUploader
end
_form.html.erb
<%= form_for #observation do |f| -%>
...Other form items
<fieldset>
<legend>Observation data</legend>
<%= render "observation_data", :f => f %>
</fieldset>
<div class="actions">
<%= f.submit "Submit", class: "button" %>
</div>
<% end %>
_observation_data.html.erb
<%= f.fields_for :observation_data, OpenStruct.new(#observation.observation_data) do |o| %>
...Other form items
<div class="field">
<%= o.label :image, "Upload an image" %>
<%= o.file_field :image %>
</div>
...Other form items
<% end %>
observations_controller.rb
class ObservationsController < ApplicationController
before_action :set_observation, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#observations = Observation.all
#user = current_user.id
end
def show
#observations = Observation.find_by(id: params[:id])
#observation_data = #observation.observation_data
#comments = #observation.comments.all
#comment = #observation.comments.build
#user = User.find_by(id: #observation.user_id)
end
def new
#observation = Observation.new
end
def edit
end
def create
#observation = Observation.new(observation_params)
#observation.user_id = current_user.id
respond_to do |format|
if #observation.save
format.html { redirect_to #observation, notice: 'Observation was successfully created.' }
format.json { render action: 'show', status: :created, location: #idea }
else
format.html { render action: 'new' }
format.json { render json: #observation.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #observation.update(observation_params)
format.html { redirect_to #observation, notice: 'Observation was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #observation.errors, status: :unprocessable_entity }
end
end
end
def destroy
#observation.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_observation
#observation = Observation.find(params[:id])
end
def observation_params
params.require(:observation).permit(:user_id, :lat, :lng, :name, :description, :comment, observation_data: [:observed_on, :image, :ph, :oxygen, :ecoli, :phosphates_threshold, :clarity, :nitri, :nitrates, wildlife: [], conditions: [], invasive_species: []])
end
end
The problem for me is mount_uploader :image, ImageUploader is always looking for an :image column, how can I merge the Carrierwave response this with JSON in another column? Is it even possible?

Rails: One_to_one relationship and form_for sending format instead of ID and params

I'm pretty new to rails and I'm having a bit of a though time to register my employeur.
Here are my routes:
resources :users do
resource :prestataire
resource :employeur
end
I have a has_one relationship between my employeur and user resources:
class User < ActiveRecord::Base
has_one :prestataire
has_one :employeur
has_secure_password
end
class Employeur < ActiveRecord::Base
belongs_to :user
validates :siren, :societe, :code_postal, presence: true
end
And here's where I think the issue is:
<%= form_for [#user,#employeur], url: user_employeur_path(#user) do |f| %>
<% if #employeur.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#employeur.errors.count, "error") %> prohibited this employeur from being saved:</h2>
<ul>
<% #employeur.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :siren, 'Siren: ' %><br>
<%= f.text_field :siren %>
</div>
.
.
.
<div class="actions">
<%= f.submit %>
</div>
<% end %>
When I fill in this issue, I'm redirected to /users/193/employeur.84 and I get this error: Couldn't find Employeur without an ID
Those are the only two params that are send after the form, even though I've indicated :siren, :societe, :code_postal
{"user_id"=>"193",
"format"=>"84"}
I guess that this might also come from my Emmployeur controller:
class EmployeursController < ApplicationController
before_filter :set_user
def index
#employeurs = #user.employeur.all
end
def show
#employeur = Employeur.find(params[:id]) #This is where the error happens since no id is sent.
end
def new
#employeur = #user.build_employeur
end
def edit
#employeur = Employeur.find(params[:id])
end
def create
#employeur = #user.build_employeur(employeur_params)
respond_to do |format|
if #employeur.save
format.html { redirect_to [#user, #employeur], notice: 'Employeur was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #employeur.errors, status: :unprocessable_entity }
end
end
end
def update
#employeur = Employeur.find(params[:id])
respond_to do |format|
if #employeur.update_attributes(employeur_params)
format.html { redirect_to [#user, #employeur], notice: 'Employeur was successfully created.' }
format.json { render action: 'show', status: :created, location: #employeur }
else
format.html { render action: 'new' }
format.json { render json: #employeur.errors, status: :unprocessable_entity }
end
end
end
def destroy
#employeur = Employeur.find(params[:id])
#employeur.destroy
respond_to do |format|
format.html { redirect_to #user }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:user_id])
end
def employeur_params
params.require(:employeur).permit(:siren, :societe, :code_postal)
end
end
Any help would be more then welcome.
In order to give an example of singular and nested resource working, I'll add a little more of my code:
class Employeur < ActiveRecord::Base
model_name.instance_variable_set(:#route_key, 'employeur')
belongs_to :user
has_many :projets, as: :projetable
has_many :prestataires, through: :projets
has_many :offres, through: :projets
has_many :feedbacks, through: :projets
validates :siren, :societe, :code_postal, presence: true, uniqueness: true
validates :code_postal, presence: true
validates_associated :user
end
Here's mu User controller that leads me from the user form to the employeur once filled:
class UsersController < ApplicationController
#TODO index user doit être suprimé quand inutile pour dev
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
if params[:commit] == 'Employeur'
format.html { redirect_to new_user_employeur_path(user_id: #user), notice: "Renseignez vos informations d'employeur" }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { redirect_to new_user_prestataire_path(user_id: #user), notice: "Renseignez vos informations de prestataire" }
format.json { render action: 'show', status: :created, location: #user }
end
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update(user_params)
if params[:commit] == 'Prestataire'
format.html { redirect_to new_user_prestataire_path(user_id: #user), notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { redirect_to new_user_employeur_path(user_id: #user), notice: "User was successfully updated." }
format.json { head :no_content }
end
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :surname, :forename, :civility, :phone)
end
end
And finally, my User form:
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :civility, 'Titre de civilité: ' %><br>
<%= f.text_field :civility %>
</div>
<div class="field">
<%= f.label :forename, 'Prénom: ' %><br>
<%= f.text_field :forename %>
</div>
<div class="field">
<%= f.label :surname, 'Nom de famille: ' %><br>
<%= f.text_field :surname %>
</div>
<div class="field">
<%= f.label :email, 'Email: ' %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password, 'Mot de passe: ' %><br>
<%= f.password_field :password, size: 40 %>
</div>
<div class="field">
<%= f.label :password_confirmation, 'Confirmation de mot de passe: ' %><br>
<%= f.password_field :password_confirmation, size: 40 %>
</div>
<div class="field">
<%= f.label :phone, 'Numéro de téléphone: ' %><br>
<%= f.text_field :phone %>
</div>
<div class="actions">
<%= f.submit "Employeur" %>
<%= f.submit "Prestataire" %>
</div>
<% end %>
Hope this will help someone as much as it would have helped me. Cheers !
You are not passing in the #employeur to your nested route user_employeur_path. Try this on your form_for line:
user_employeur_path(#user, #employeur)
But you shouldn't have to specify url; this should work:
<%= form_for [#user,#employeur] do |f| %>
See creating paths and urls from objects.
You don't have your EmployeursController setup correctly. Since employeur is a singular resource, you cannot reference it by id. Instead you need to change your show action to this:
def show
#employeur = User.find(params[:user_id]).employeur
end
The reason is that user_employeur_path(#user) creates a path like /users/193/employeur where you can access the user id in the controller via params[:user_id]
Also, since employeur is a singular resource, there is no index action defined for it. You can remove the index action entirely from your controller.
For people like me who were desperate to find an example of nested and singular resource working, I post my controller corrected thanks to the help of Hamed:
class EmployeursController < ApplicationController
before_filter :set_user
def new
#employeur = #user.build_employeur
end
def show
#employeur = #user.employeur
end
def edit
#employeur = #user.employeur
end
def create
#employeur = #user.build_employeur(employeur_params)
respond_to do |format|
if #employeur.save
format.html { redirect_to [#user, #employeur], notice: 'Employeur was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #employeur.errors, status: :unprocessable_entity }
end
end
end
def update
#employeur = #user.employeur
respond_to do |format|
if #employeur.update_attributes(employeur_params)
format.html { redirect_to [#user, #employeur], notice: 'Employeur was successfully created.' }
format.json { render action: 'show', status: :created, location: #employeur }
else
format.html { render action: 'new' }
format.json { render json: #employeur.errors, status: :unprocessable_entity }
end
end
end
def destroy
#employeur = #user.employeur
#employeur.destroy
respond_to do |format|
format.html { redirect_to root_path }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:user_id])
end
def employeur_params
params.require(:employeur).permit(:siren, :societe, :code_postal)
end
end

Cannot access model method inside its controller in Rails

In my Rails app, I have a controller tickets_controller.rb and model ticket.rb. For creating a ticket I have the following form,
<%= form_for(#ticket) do |f| %>
<% if #ticket.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#ticket.errors.count, "error") %> prohibited this ticket from being saved:</h2>
<ul>
<% #ticket.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :ref_no, "Reference Number"%><br/>
<%= f.text_field :ref_no%><br />
<%= f.label :category, "Type of Request"%><br/>
<%= f.text_field :category_id %><br />
<%= f.label :issue, "Issue"%><br/>
<%= f.text_area :issue%><br />
<%= f.label :ticket_priority, "Priority level"%><br/>
<%= f.text_field :ticket_priority_id %><br />
<%= f.label :ticket_status, "Current Status"%><br/>
<%= f.text_field :ticket_status_id %><br />
<%= f.label :project, "Project"%><br/>
<%= f.text_field :project_id %><br />
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I want to create a unique random reference number on the form_load (ticket/new), and it should be appended to Reference Number text field. While creating a new reference number, it should check the tickets table for duplication. So I have the following model,
ticket.rb
class Ticket < ActiveRecord::Base
attr_accessible :issue, :ticket_status_id, :ticket_priority_id, :ref_no, :category_id, :project_id
has_many :ticket_statuses , :through => :ticket_histories
has_one :ticket_priority
belongs_to :user
before_create :generate_token
protected
def generate_num
self.token = loop do
random_token = random(1000000000)
break random_token unless Ticket.exists?(:ref_no => random_token)
end
end
end
and
tickets_controller.rb
class TicketsController < ApplicationController
before_filter :authenticate_user!
#load_and_authorize_resource
def index
#tickets = Ticket.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #tickets }
end
end
def show
#ticket = Ticket.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #ticket }
end
end
def new
#ticket = Ticket.new
#ref_no = Ticket.generate_num
#categories = Category.all
#status = TicketStatus.first
#priorities = TicketPriority.all
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #ticket }
end
end
def edit
#ticket = Ticket.find(params[:id])
end
def create
#ticket = Ticket.new(params[:ticket])
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, :notice => 'Ticket was successfully created.' }
format.json { render :json => #ticket, :status => :created, :location => #ticket }
else
format.html { render :action => "new" }
format.json { render :json => #ticket.errors, :status => :unprocessable_entity }
end
end
end
def update
#ticket = Ticket.find(params[:id])
respond_to do |format|
if #ticket.update_attributes(params[:ticket])
format.html { redirect_to #ticket, :notice => 'Ticket was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => #ticket.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
respond_to do |format|
format.html { redirect_to tickets_url }
format.json { head :no_content }
end
end
end
When I run my app, I am getting the following error. Can anyone help?
NoMethodError in TicketsController#new
undefined method `generate_num' for #<Class:0x7f5cdc1f21c0>
Rails.root: /home/local/Rajesh/ticket_system
Application Trace | Framework Trace | Full Trace
app/controllers/tickets_controller.rb:27:in `new'
Change your model method generate_num to self.generate_num.
def self.generate_num
token = loop do
random_token = random(1000000000)
break random_token unless Ticket.exists?(:ref_no => random_token)
end
end
You have defined and instance method and you are calling it using Class
Call method using object
#ticket.generate_num

Can't mass-assign protected attributes: product, user

Hello I'm working in a application where you can vote for a product and from the New action of my vote view I get this error:
ActiveModel::MassAssignmentSecurity::Error in VotesController#create
Can't mass-assign protected attributes: product, user
I make a test on rails console and it works. So I don't know what it's going on.
Here are the models:
class Product < ActiveRecord::Base
attr_accessible :title
has_many :votes
has_many :users, :through => :votes
has_attached_file :photo, :styles => { :medium => "300x300" }
before_save { |product| product.title = title.titlecase }
validates :title, presence: true, uniqueness: { case_sensitive: false }
validates :photo, :attachment_presence => true
end
class User < ActiveRecord::Base
has_many :votes
has_many :products, :through => :votes
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end
class Vote < ActiveRecord::Base
attr_accessible :product_id, :user_id
belongs_to :product
belongs_to :user
end
Here is the vote controller
class VotesController < ApplicationController
# GET /votes
# GET /votes.json
def index
#votes = Vote.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #votes }
end
end
# GET /votes/1
# GET /votes/1.json
def show
#vote = Vote.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #vote }
end
end
# GET /votes/new
# GET /votes/new.json
def new
#vote = Vote.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #vote }
end
end
# GET /votes/1/edit
def edit
#vote = Vote.find(params[:id])
end
# POST /votes
# POST /votes.json
def create
#vote = Vote.new(params[:vote])
respond_to do |format|
if #vote.save
format.html { redirect_to #vote, notice: 'Vote was successfully created.' }
format.json { render json: #vote, status: :created, location: #vote }
else
format.html { render action: "new" }
format.json { render json: #vote.errors, status: :unprocessable_entity }
end
end
end
# PUT /votes/1
# PUT /votes/1.json
def update
#vote = Vote.find(params[:id])
respond_to do |format|
if #vote.update_attributes(params[:vote])
format.html { redirect_to #vote, notice: 'Vote was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #vote.errors, status: :unprocessable_entity }
end
end
end
# DELETE /votes/1
# DELETE /votes/1.json
def destroy
#vote = Vote.find(params[:id])
#vote.destroy
respond_to do |format|
format.html { redirect_to votes_url }
format.json { head :no_content }
end
end
end
and here is the new vote view
<%= form_for(#vote) do |f| %>
<% if #vote.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#vote.errors.count, "error") %> prohibited this vote from being saved:</h2>
<ul>
<% #vote.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :product %><br />
<%= f.text_field :product %>
</div>
<div class="field">
<%= f.label :user %><br />
<%= f.text_field :user %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Please I really need your help to solve this issues, it was very difficult to find a tutorial with has_many :through that include the complete MVC example, I think my problem is on the view, but I don't know.
Thanks!
That error message tells you everything you need to know if you look closely at it.
ActiveModel::MassAssignmentSecurity::Error in VotesController#create
Can't mass-assign protected attributes: product, user
you may not be familiar with the term "mass-assignment". its the assignment of 1 or more of an objects attributes at the time of creation. i.e. in VotesController#create.
when unprotected, mass-assignment opens you up to hackers assigning values to any and all of an objects attributes in your site's forms wether you meant to give access or not.
thats where attar_accessible comes in. it forces you to be explicit about what attributes of a model your users should have access to. any not passed as symbols into the macro will be protected attributes as in Can't mass-assign protected attributes: product, user.
the scaffolding set attr_accessible :product_id, :user_id when it created your model but it didnt know you were going to assign these with objects rather than id values.
you can fix this one of 2 ways.
change your form so that the hash-like params variable assigns like this
params[vote][product_id]
or change your model like
attr_accessible :product, :user

Resources