Ruby / Rails - Paperclip::Error in ModificationsController#create - ruby-on-rails

Paperclip::Error in ModificationsController#create Modification model missing required attr_accessor for 'image_file_name'
Error:
Model: modification.rb
class Modification < ActiveRecord::Base
has_attached_file :image,
styles: { thumb: ["64x64#", :jpg],
original: ['500x500>', :jpg] },
convert_options: { thumb: "-quality 75 -strip",
original: "-quality 85 -strip" }
validates_attachment :image,
content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
end
Controller: modifications_controller.rb
class ModificationsController < ApplicationController
def index
#modifications = Modification.order('created_at')
end
def new
#modifications = Modification.new
end
def create
#modifications = Modification.new(modification_params)
if #modifications.save
flash[:success] = "Modification contributed!"
redirect_to collection_path
else
render 'new'
end
end
private
def modification_params
params.require(:modification).permit(:image, :title)
end
end
Migration: _create_modifications.rb
class CreateModifications < ActiveRecord::Migration
def change
create_table :modifications do |t|
t.string :title
t.string :image_file_name
t.string :image_content_type
t.integer :image_file_size
t.timestamps null: false
end
end
end
Migration: _add_attachment_modification_to_profiles.rb
class AddAttachmentModificationToProfiles < ActiveRecord::Migration
def self.up
change_table :profiles do |t|
t.attachment :modification
end
end
def self.down
remove_attachment :profiles, :modification
end
end
Schema.rb
create_table "modifications", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
...
create_table "profiles", force: :cascade do |t|
t.integer "user_id"
t.string "first_name"
t.string "last_name"
t.string "location"
t.string "modifications"
t.string "website"
t.text "bio"
t.datetime "created_at"
t.datetime "updated_at"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.string "modification_file_name"
t.string "modification_content_type"
t.integer "modification_file_size"
t.datetime "modification_updated_at"
end

You declared twice has_attached_file :image method in your Model: modification.rb
Try to delete very first one has_attached_file :image and let me know if that works for you.

Related

ActiveRecord query with multiple joins not recognizing the relations

I am trying to write an ActiveRecord Query that returns all students enrolled in a certain course with the following query:
def self.students_enrolled_in(course_id)
Student
.joins(:enrollments)
.joins(:sections)
.joins(:courses)
.where(sections: { course_id: course_id })
end
the result in the rails console is:
ActiveRecord::ConfigurationError: Can't join 'Student' to association named 'sections'; perhaps you misspelled it?
it seems that the association is made. what am I doing wrong? does the query actually mean that all the join() statements have to relate back to Student, or should ac trace out the relational links?
Professor show page:
<div class="col-md-8">
<h2 class="card-title"><%= #professor.name %></h2>
<% #courses_taught.each do |course| %>
<div class="card mb-4 card-header">
<img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap">
<h3 class="card-text"><%= course.title %></h3>
</div>
<div class="card-body">
<% course.sections.enrollments.students.each do |student| %>
<p><% student.name %></p>
<% end %>
</div>
<% end %>
</div>
models:
enrollment
class Enrollment < ApplicationRecord
belongs_to :section
belongs_to :student
end
Student:
class Student < ApplicationRecord
has_many :enrollments
end
Professor:
class Section < ApplicationRecord
has_many :enrollments
belongs_to :professor
belongs_to :course
validates_uniqueness_of :professor_id, scope: :course_id
scope :by_professor_id, ->(prof_id) { where('professor_id = ?', prof_id) }
end
Course:
class Course < ApplicationRecord
enum status: { planning: 0, offered: 1 }
scope :offered, -> { where(status: 1) }
scope :planning, -> { where(status: 0) }
belongs_to :department
has_many :sections
has_many :professors, through: :sections
validates :title, :number, :status, :description, presence: true
validates :description, length: { in: 10..500 }
validates :title, :number, uniqueness: { case_sensitive: false }
def self.search(term)
if term
where('title LIKE ?', "%#{term}%").order('title DESC')
else
order('title ASC')
end
end
def self.taught_by(professor_id)
Course
.joins(:sections)
.joins(:professors)
.where(sections: { professor_id: professor_id })
.select('distinct courses.*')
end
end
Schema:
ActiveRecord::Schema.define(version: 20171013201907) do
create_table "courses", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "number"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 0
t.integer "department_id"
t.index ["department_id"], name: "index_courses_on_department_id"
end
create_table "departments", force: :cascade do |t|
t.string "name"
t.text "description"
t.text "main_image"
t.text "thumb_image"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "enrollments", force: :cascade do |t|
t.integer "section_id"
t.integer "student_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["section_id"], name: "index_enrollments_on_section_id"
t.index ["student_id"], name: "index_enrollments_on_student_id"
end
create_table "professors", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 0
t.integer "department_id"
t.text "bio"
t.index ["department_id"], name: "index_professors_on_department_id"
end
create_table "sections", force: :cascade do |t|
t.integer "number"
t.integer "max_enrollment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "professor_id"
t.integer "course_id"
t.string "room"
t.index ["course_id"], name: "index_sections_on_course_id"
t.index ["professor_id", "course_id"], name: "index_sections_on_professor_id_and_course_id", unique: true
t.index ["professor_id"], name: "index_sections_on_professor_id"
end
create_table "students", force: :cascade do |t|
t.string "name"
t.decimal "gpa"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "name"
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "roles"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
end
Another way to do this is to add some more associations to your Student model:
class Student < ApplicationRecord
has_many :enrollments
has_many :sections, through: :enrollments
has_many :courses, through: :sections
scope :enrolled_in_course, -> (course) { joins(:sections).where(course_id: course.id)
end
You can then find all students enrolled in a course with:
Student.enrolled_in_course(course)
You're over-applying .joins. Try starting from the inside out. First, find the course:
Course.find_by(id: course_id)
Then, find all the sections associated with the course. No need to do a joins here:
Section.where(course: Course.find_by(id: course_id))
Now you do your join:
Student.joins(:enrollments).where(enrollments: {section: Section.where(course: Course.find_by(id: course_id))})
I think that ought to do the trick for you. But, untested. So, give it a go and see if it works.
P.S.: Try posting only the most relevant code. It's not so much fun to sort through a bunch of extraneous stuff.

Create a 1:1 relation between User and a Profile

I am quite new on RoR.
I have two models, one User (generated by Devise) and one Profile.
I want to have one Profile per User.
Here are my User stories:
As a user I have to, create a Profile
As a user I can, edit my Profile
As a user I can, see all the Profiles
Below, you will see my two different models.
class Profile < ApplicationRecord
has_attachment :photo
belongs_to :user, class_name: 'User', foreign_key: :user_id
end
class User < ApplicationRecord
has_one :profile
devise :database_authenticatable, :registerable,
:rememberable, :trackable, :validatable
end
I don't know why, but today, a User can create many Profile and Edit another Profile.
Does anyone could help me to understand why ?
In order to prevent users to edit others profile you can do something like this in your Profile controller update action
if current_user == #profile.user
allow to edit
else
don't allow to edit
Here is my schema.rb
ActiveRecord::Schema.define(version: 20160510084050) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "attachinary_files", force: :cascade do |t|
t.string "attachinariable_type"
t.integer "attachinariable_id"
t.string "scope"
t.string "public_id"
t.string "version"
t.integer "width"
t.integer "height"
t.string "format"
t.string "resource_type"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "attachinary_files", ["attachinariable_type", "attachinariable_id", "scope"], name: "by_scoped_parent", using: :btree
create_table "bookings", force: :cascade do |t|
t.integer "user_id"
t.integer "profile_id"
t.boolean "status"
t.date "teetime"
t.text "message"
end
add_index "bookings", ["profile_id"], name: "index_bookings_on_profile_id", using: :btree
add_index "bookings", ["user_id"], name: "index_bookings_on_user_id", using: :btree
create_table "mailboxer_conversation_opt_outs", force: :cascade do |t|
t.string "unsubscriber_type"
t.integer "unsubscriber_id"
t.integer "conversation_id"
end
add_index "mailboxer_conversation_opt_outs", ["conversation_id"], name: "index_mailboxer_conversation_opt_outs_on_conversation_id", using: :btree
add_index "mailboxer_conversation_opt_outs", ["unsubscriber_id", "unsubscriber_type"], name: "index_mailboxer_conversation_opt_outs_on_unsubscriber_id_type", using: :btree
create_table "mailboxer_conversations", force: :cascade do |t|
t.string "subject", default: ""
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "mailboxer_notifications", force: :cascade do |t|
t.string "type"
t.text "body"
t.string "subject", default: ""
t.string "sender_type"
t.integer "sender_id"
t.integer "conversation_id"
t.boolean "draft", default: false
t.string "notification_code"
t.string "notified_object_type"
t.integer "notified_object_id"
t.string "attachment"
t.datetime "updated_at", null: false
t.datetime "created_at", null: false
t.boolean "global", default: false
t.datetime "expires"
end
add_index "mailboxer_notifications", ["conversation_id"], name: "index_mailboxer_notifications_on_conversation_id", using: :btree
add_index "mailboxer_notifications", ["notified_object_id", "notified_object_type"], name: "index_mailboxer_notifications_on_notified_object_id_and_type", using: :btree
add_index "mailboxer_notifications", ["sender_id", "sender_type"], name: "index_mailboxer_notifications_on_sender_id_and_sender_type", using: :btree
add_index "mailboxer_notifications", ["type"], name: "index_mailboxer_notifications_on_type", using: :btree
create_table "mailboxer_receipts", force: :cascade do |t|
t.string "receiver_type"
t.integer "receiver_id"
t.integer "notification_id", null: false
t.boolean "is_read", default: false
t.boolean "trashed", default: false
t.boolean "deleted", default: false
t.string "mailbox_type", limit: 25
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "is_delivered", default: false
t.string "delivery_method"
t.string "message_id"
end
add_index "mailboxer_receipts", ["notification_id"], name: "index_mailboxer_receipts_on_notification_id", using: :btree
add_index "mailboxer_receipts", ["receiver_id", "receiver_type"], name: "index_mailboxer_receipts_on_receiver_id_and_receiver_type", using: :btree
create_table "profiles", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "handicap"
t.string "postbox"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "tagline"
t.string "skills"
t.string "town"
t.integer "user_id"
t.float "latitude"
t.float "longitude"
t.string "street"
end
add_index "profiles", ["user_id"], name: "index_profiles_on_user_id", using: :btree
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "prenom"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_foreign_key "bookings", "profiles"
add_foreign_key "bookings", "users"
add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", column: "conversation_id", name: "mb_opt_outs_on_conversations_id"
add_foreign_key "mailboxer_notifications", "mailboxer_conversations", column: "conversation_id", name: "notifications_on_conversation_id"
add_foreign_key "mailboxer_receipts", "mailboxer_notifications", column: "notification_id", name: "receipts_on_notification_id"
add_foreign_key "profiles", "users"
end
And here is the profile controller
class ProfilesController < ApplicationController
skip_before_action :authenticate_user!, only: [ :index ]
before_action :find_profiles, only: [:show, :edit, :update, :destroy]
def index
# if params[:id]
# #profiles = Profile.where(handicap: params[:handicap])
# else
#profiles = Profile.all
#hash = Gmaps4rails.build_markers(#profiles) do |profile, marker|
marker.lat profile.latitude
marker.lng profile.longitude
marker.infowindow render_to_string(partial: "/profiles/map_box", locals: { profile: profile })
end
end
end
def show
#profile = Profile.find(params[:id])
end
def new
#profile = Profile.new
end
def create
owner = current_user
#profile = Profile.new(profile_params)
#profile.owner = owner
if #profile.save
redirect_to profiles_path
else
render :new
end
end
def edit
end
def update
if #profile.update(profile_params)
redirect_to profiles_path
else
render :edit
end
end
def destroy
end
private
def profile_params
params.require(:profile).permit(:last_name,:first_name, :address, :search, :handicap, :street, :postbox, :tagline, :skills, :town, :photo)
end
def find_profiles
#profile = Profile.find(params[:id])
end
end

Couldn't find Lesson with id=0 upon save on an object with has_and_belong_to_many relationship

i have two objects
- material
- lesson
each material can have and belong to lesson; each lesson can have and belong to material.
in material_controller when i try to create
#material = Material.new(params[:material])
class Material < ActiveRecord::Base
has_and_belongs_to_many :lessons
attr_accessible :content_type, :user_id, :lesson_ids
here is params
"material"=>{"content_type"=>"2",
"detail_content"=>"",
"user_id"=>"5",
"lesson_ids"=>"[]"},
create_table "lessons", :force => true do |t|
t.string "title"
t.string "description"
t.integer "course_id"
t.integer "sequence"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "lessons_materials", :force => true do |t|
t.integer "lesson_id"
t.integer "material_id"
end
create_table "materials", :force => true do |t|
t.integer "content_type"
t.text "detail_content"
t.text "embedded_content"
t.string "stored_file_name"
t.string "stored_content_type"
t.integer "stored_file_size"
t.datetime "stored_updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
end
I think your lesson_ids param should be nil when you have no lesson associated, instead of being an array.

Rails 3 Nested Form; UnknownAttributeError on New

Rails 3.1, Ruby 1.87 (don't hate me). I watched the Railscasts on Nested Forms; I only put that in so you can point out where I might have missed something in the Railscasts if you know them.
Note: I added #sample_data_set.build_sample_data_template but got "unknown attribute: sample_data_set_id" on the post instead [the code is also posted with the new below).
Using a Nested form on Create/New; hit Submit and get:
ActiveRecord::UnknownAttributeError (unknown attribute:
sample_data_templates):
app/controllers/sample_data_sets_controller.rb:50:in new'
app/controllers/sample_data_sets_controller.rb:50:increate'
Sample Data Set Model:
class SampleDataSet < ActiveRecord::Base
has_one :sample_data_template, :dependent => :destroy
accepts_nested_attributes_for :sample_data_template
end
Sample Data Template Model:
class SampleDataTemplate < ActiveRecord::Base
belongs_to :sample_data_set
#Random info generation
def self.name_gen(*prepend)
character_map = [('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten
name = (0..8).map{ character_map[rand(character_map.length)] }.join
if prepend[0].nil? || prepend[0] == ""
return name
else
return prepend[0].to_s + "_" + name
end
end
def self.ssn_gen
#broke this out as its own method in case someone wants some logic later one
ssn = ""
3.times do
ssn = ssn + (100..999).to_a.choice.to_s
end
return ssn
end
def self.row_gen(row_count)
#data_rows = Array.new
i = 0
until i > row_count do
#row = SampleDataSet.first
#row.officialFirstName = SampleDataTemplate.name_gen
#row.officialLastName = SampleDataTemplate.name_gen
#row.emailAddresses = #row.officialFirstName + #row.officialLastName + "#aaa.aaa.edu"
#row.ssn = SampleDataTemplate.ssn_gen
#data_rows << #row
i += 1
end
return #data_rows
end
end
Sample Data Controller#New
def new
#sample_data_set = SampleDataSet.new
#sample_data_set.build_sample_data_template #after adding this I get error:unknown attribute: sample_data_set_id
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #sample_data_set }
end
Sample Data Controller#Create
def create
#sample_data_set = SampleDataSet.new(params[:sample_data_set])
respond_to do |format|
if #sample_data_set.save
format.html { redirect_to #sample_data_set, :notice => 'Sample data set was successfully created.' }
format.json { render :json => #sample_data_set, :status => :created, :location => #sample_data_set }
else
format.html { render :action => "new" }
format.json { render :json => #sample_data_set.errors, :status => :unprocessable_entity }
end
end
end
end
Update, added form piece
<div class="sample_fields">
<%= f.fields_for :sample_data_templates do |builder| %>
<%= render "sample_data", :f => builder%>
<% end %>
</div>
Update, Schema:
ActiveRecord::Schema.define(:version => 20120103172936) do
create_table "sample_data_sets", :force => true do |t|
t.string "title"
t.text "description"
t.string "created_for"
t.string "created_by"
t.integer "number_of_records"
t.integer "sample_data_template_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "sample_data_templates", :force => true do |t|
t.integer "sample_data_set_id"
t.string "irn"
t.string "ssn"
t.string "officialLastName"
t.string "officialFirstName"
t.string "emailAddresses"
t.string "campusNum"
t.string "internationalId"
t.string "internationalIdCountry"
t.string "gender"
t.string "officialMiddleInitial"
t.string "previousLastName"
t.string "previousFirstName"
t.string "previousMiddleInitial"
t.string "addressLine1"
t.string "addressLine2"
t.string "addressLine3"
t.string "city"
t.string "state"
t.string "zipCode"
t.string "province"
t.string "homeAreaCode"
t.string "homePhoneNumber"
t.string "homePhoneExtenstion"
t.string "homePhoneCountryCode"
t.string "workAreaCode"
t.string "workPhoneNumber"
t.string "workExtenstion"
t.string "workPhoneCountryCode"
t.string "faxAreaCode"
t.string "faxPhoneNumber"
t.string "faxExtension"
t.string "faxCountryCode"
t.string "race"
t.string "previousDegree"
t.string "region"
t.string "foreignTranscript"
t.string "apolloEmployee"
t.string "nursingLicenseExpiration"
t.string "nursingInsuranceExpiration"
t.string "otherInsuranceExpiration"
t.string "program"
t.string "version"
t.string "groupId"
t.string "team"
t.string "enrollmentUserId"
t.string "admissionsUserId"
t.string "oldProgram"
t.string "oldVersion"
t.string "galaxyStudentOid"
t.string "suffixOne"
t.string "suffixTwo"
t.string "employeId"
t.string "promoCode"
t.string "revCampusOid"
t.string "FerpaNotes"
t.string "isWavierHigh"
t.string "executingUserId"
t.string "totalDeclaredExtCredits"
t.datetime "insuranceExpireDate"
t.datetime "acknowledgementDate"
t.datetime "scheduledReentryDate"
t.datetime "scheduledStartDate"
t.datetime "dateOfBirth"
t.datetime "enrollAgreeSignDate"
t.boolean "usCitizen"
t.boolean "financialAid"
t.boolean "overrideFlag"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Does sample_data_templates table have a sample_data_set_id column? Perhaps you didn't add it to the migration or did not run the migration?

Rails truncates hash on save:

I have a rails model with a hashed password field in it (surprise, surprise), which after some manipulation, is 40 characters long. I generate a user in script/console and it appears as follows:
#<User id: 1, firstname: "true", lastname: "false", username: "chaines51", hashed_password: "2Gr0GWvPunB3x5jomRTSTZJRIelC2RW103d7f3db">
I then run user_instance.save, which returns true, and the user then looks like this:
#<User id: 1, firstname: "true", lastname: "false", username: "chaines51", hashed_password: "103d7f3db">
Any idea what is happening to the other 30+ characters? I changed the field in the migration from string to text, but it still gets truncated
EDIT: The model code is:
require 'digest/sha1'
class User < ActiveRecord::Base
validates_presence_of :username, :password, :password_confirmation, :firstname, :lastname
validates_length_of :username, :within => 3..40
validates_length_of :password, :within => 5..40
validates_uniqueness_of :username
validates_confirmation_of :password
belongs_to :school
attr_protected :id, :salt
attr_accessor :password, :password_confirmation
def self.random_string(len)
#generate a random salt consisting of digits and letters.
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
salt = ""
1.upto(len) { |i| salt << chars[rand(chars.size-1)] }
return salt
end
def password=(pass)
#password=pass
#salt = User.random_string(40-pass.length)
self.hashed_password = User.encrypt(#password, #salt)
end
def self.encrypt(pass, salt)
hash = Digest::SHA1.hexdigest(pass+salt)
hash.slice!(0..(40-pass.length-1))
hash = salt+hash;
end
def self.checkhash(pass, hash)
salt = hash.slice!(0..40-pass.length-1)
rehash = User.encrypt(pass, salt)
return rehash == (salt+hash)
end
def self.authenticate(login, pass)
u = User.find_by_username(login)
return nil if u.nil?
return u if User.checkhash(pass, u.hashed_password)
nil
end
end
and the db/schema.rb is:
ActiveRecord::Schema.define(:version => 20100127034504) do
create_table "categories", :force => true do |t|
t.string "title"
end
create_table "questions", :force => true do |t|
t.string "question"
t.string "a"
t.string "b"
t.string "c"
t.string "d"
t.string "e"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "questions_quizzes", :id => false, :force => true do |t|
t.integer "app_id"
t.integer "category_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "quizzes", :force => true do |t|
t.string "title"
t.integer "category_id"
end
create_table "schools", :force => true do |t|
t.string "name"
t.integer "coach_id"
end
create_table "users", :force => true do |t|
t.string "firstname", :null => false
t.string "lastname", :null => false
t.string "username", :null => false
t.boolean "needs_pass", :default => false
t.integer "school_id"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "confirmed", :default => false
t.text "hashed_password"
end
end
Showing the model code, and the table info form db/schema.rb, would be really helpful. Right off, I can tell you that a string column will hold up to 255 characters without a problem, so there might be something else at fault. If something is restricting, it will most likely show itself in one of the two places I named above.

Resources