ROR Active Record not save data correcty - ruby-on-rails

Hi guys i have a problem and i dont' know how to solve it, i'm really new on the ROR's world.
preamble : each municiplaty has many itinerary, so :
1) i've created the itinerary table with this migration :
class CreateItineraries < ActiveRecord::Migration
def change
create_table :itineraries do |t|
t.string :title
t.string :json
t.integer :muncipality_id
t.text :description
t.boolean :published, :default => true, :null => false
t.timestamps null: false
end
end
end
2) i've added the municipality_id reference to the itineraries table, with this migration :
class AddMunicipalityIdToItineraries < ActiveRecord::Migration
def change
add_reference :itineraries, :municipality, index: true, foreign_key: true
end
end
3) i've created another table for the translations of itineraries :
class AddTranslationTablesForItineraries < ActiveRecord::Migration
def up
Itinerary.create_translation_table!({
:title => :string
}, {
:migrate_data => true
})
end
def down
add_column :itineraries, :title, :string
Itinerary.drop_translation_table! :migrate_data => true
end
end
now, the problem is when i try to save the data from the relative simple_form, it save the itinerary's title only in the translations table, why?!
here the code of the simple_form :
<%= simple_form_for [:admin, #municipality, #itinerary], url: #url, :html => {:class => ''} do |f| %>
<%= render 'application/translation_form_heading' %>
# ...
<%= f.input :title, required: true %>
<%= f.input :description, label: 'description', :as => :ckeditor, :input_html => {ckeditor: {toolbar: get_toolbar('default')},:rows => 15} %>
<%= f.input :json, required: true, label: 'GeoJSON', as: :text, :input_html => {:rows => 15} %>
# ...
<button type="submit" class="btn btn-primary pull-right">Save itinerary</button>
<% end %>
maybe it's a newbie question, but i don'r really know how to solve it, thank you!
edit : here the code of the itinerariesController :
class Admin::ItinerariesController < InheritedResources::Base
layout 'admin'
before_filter :authenticate_admin!
before_filter :set_page_title
load_and_authorize_resource
actions :all, :except => [:show]
belongs_to :municipality
def index
#itineraries = Itinerary.ordered
end
def new
#url = admin_municipality_itineraries_path(params[:municipality_id])
new!
end
def edit
#url = admin_municipality_itinerary_path(params[:municipality_id], params[:id])
edit!
end
def update
unless params[:translate_to].blank?
I18n.with_locale(params[:translate_to]) {
update!
}
else
update!
end
end
def set_page_title
#page_title = PointOfInterest.model_name.human(:count => 2).titleize
end
def create
create! {
admin_municipality_itineraries_path
}
end
private
def permitted_params
params.permit(:itinerary => [:id, :title, :json,:description, :municipality_id] )
end
end

Try to update this one in controller
private
def permitted_params
params.permit(:itinerary => [:id, :title, :description, :municipality_id, :json] )
end
You need to permit JSON value in params always at the end

Related

has_many through & Collection Select issues

I'm stumped. I'm getting an error of unknown attribute 'products_part' for Part. I'm starting with trying to create a new part that is associated with many different products through the products_parts table. Relevant code:
# schema.rb
create_table "products_parts", force: :cascade do |t|
t.integer "product_id"
t.integer "part_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Just in case it's relevant, there is a product_id column existing on the parts table from my existing setup that only allowed one part per product. I don't think this would interfere though?
# part.rb
class Part < ApplicationRecord
has_many :products_parts
has_many :products, through: :products_parts
accepts_nested_attributes_for :products_parts, :allow_destroy => true
end
# products_part.rb
class ProductsPart < ApplicationRecord
belongs_to :product
belongs_to :part
end
# product.rb
class Product < ApplicationRecord
has_many :products_parts
has_many :parts, through: :products_parts
accepts_nested_attributes_for :parts, :allow_destroy => true
end
--
# parts_controller.html.erb
class PartsController < ApplicationController
before_action :set_part, only: [:show, :edit, :update, :destroy]
def new
#part = Part.new
#part.uploads.build
#products_parts = #part.products_parts.build
#product = Product.order(brand_name: :asc).order(manufacturer_model_number: :asc)
end
def create
#part = Part.new(part_params)
if #part.save
redirect_to part_path(#part), notice: '// Part was successfully created.'
else
render :new
end
end
private
def part_params
params.require(:part).permit!
end
end
Parameters being passed on submit:
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"f+ObKsfs2QNP6l1MEDGSj6EZERMpHT/7vVKjAumC1aQmeTKdlPJNeSv2IZwNgsVPnKt2Siqi9x5oMmD2Ti8kMQ==",
"part"=>
{"products_part"=>{"product_ids"=>["", "191", "7"]},
"manufacturer_model_number"=>"Screws-HB",
"notes"=>""},
"commit"=>"Create Part"}
-
# _form.html.erb
<%= bootstrap_form_for #part, url: parts_path, method: :post, :html => { :multipart => true } do |f| %>
<%= f.fields_for(#products_parts) do |ff| %>
<%= ff.collection_select(:product_ids, #product, :id, :product_select_with_model,
{:placeholder => "Select Product...", hide_label: true, :selected => #part.products.map(&:id)},
{:multiple => true, :class => 'newPartProductSearch', :style => "width:100%;"}) %>
<% end %>
<%= f.submit "Create Part", :style => "float:right;" %>
<% end %>
I am basing a lot of what I did here off of help from this post.
If anybody has any ideas on what direction I can go to start fixing this, it would be appreciated!
Replace the _form with the following code:
# _form.html.erb
<%= bootstrap_form_for #part, url: parts_path, method: :post, :html => { :multipart => true } do |f| %>
<%= f.collection_select(:product_ids, Product.all, :id, :name,
{include_blank: false, :include_hidden => false, :selected => #part.products.map(&:id)},
{:multiple => true}) %>
<%= f.submit "Create Part", :style => "float:right;" %>
<% end %>
It is not tested. But hope it'll work.

Couldn't find Student with 'student_id'= RUBY ON RAILS

I am trying to pull up an edit page for my simple system.
Here's my controller for student look like:
class StudentsController < ApplicationController
def index
#students = Student.newest_first
end
def show
#student = Student.find(params[:student_id])
end
def new
#student = Student.new
end
def create
#student = Student.new(student_params_create)
if #student.save
flash[:notice] = "Student record created successfully"
redirect_to(students_path)
else
render('new')
end
end
def edit
#student = Student.find(params[:student_id])
end
def update
#student = Student.find(params[:student_id])
if #student.update_attributes(student_params_update)
flash[:notice] = "Students updated"
redirect_to(students_path)
else
render('edit')
end
end
def delete
#student = Student.find(params[:student_id])
end
def destroy
#student = Student.find(params[:student_id])
#student.destroy
end
private
def student_params_create
params.require(:student).permit(:first_name, :last_name, :birthday, :email, :subjects, :username, :password)
end
def student_params_update
params.require(:student).permit(:first_name, :last_name, :birthday, :email, :subjects)
end
end
And I am trying to here's my index page where I can click edit on my student.
<% #students.each do |student|%>
<%= student.first_name %>
<%= student.student_id %>
<%= link_to("Show", student_path(student), :class => 'action show') %>
<%= link_to("Edit", edit_student_path(student), :class => 'action edit') %>
<%= link_to("Delete", delete_student_path(student), :class => 'action delete') %>
<% end %>
For my form edit, I got the ff:
<h2>Update Subject</h2>
<%= form_for(#student) do |f| %>
<%= f.text_field(:first_name) %>
<%= f.datetime_select(:created_at, :order => [:month, :day, :year]) %><
<%= f.submit("Update Subject") %>
<% end %>
When I tried to go to my resource for students: http://localhost:3000/students/
And click on one of my students I got the ff: error:
Any idea what am I doing wrong????
EDIT:
I set the 'id' to false during migration.
def up
create_table :students, :id => false do |t|
t.integer "student_id",:primary_key => true
t.string "first_name", :limit => 25
t.string "last_name", :limit => 50
t.string "email", :default => ' ', :null => false
t.string "birthday"
t.string "subjects"
t.string "teachers"
t.string "username", :limit => 25
t.string "password_digest"
t.timestamps
end
reversible do |dir|
dir.up { execute "ALTER TABLE students AUTO_INCREMENT = 1000" }
end
# execute "CREATE SEQUENCE students_student_id_seq OWNED BY students.student_id INCREMENT BY 1 START WITH 1001"
end
def down
drop_table :students
# execute "DELETE SEQUENCE students_student_id_seq"
end
Routes:
resources :students do
member do
get :delete
end
end
UPDATE
You could need to update your routes.rb with
resources :students, param: :student_id
And your Student model with
self.primary_key = :student_id
NOTE that you're having the ActiveRecord::RecordNotFound exception because find method throws exception when it can't actually find the record needed. Try to use find_by_id method instead. It will just return nil in that situation. You'll be able to handle it easily and your app will not crash here. So you could edit your show action like this
def show
#student = Student.find_by_id(params[:student_id])
end

How to block users from getting messages?

I am beginner in rails. I am building a forum application. It has a messaging facility where users can privately message(not real time. it is like a notification.) to other users. I already achived this. But I want to add blocking feature where user can block other users to avoid getting messages from those particular users. How can i do this? I appreciate your answers. Thanks in advance.
Here is my code.
Notifications Controller
class NotificationsController < ApplicationController
layout "posts"
after_action :read_message, only: [:index]
def index
#notifications = Notification.where(:recipient_id => session[:registered_id]).order("created_at DESC")
end
def new
#user = User.find(session[:user_id])
#notification = #user.notifications.new
end
def create
#user = User.find(session[:user_id])
#notification = #user.notifications.new notification_params
if #notification.save
redirect_to(:controller => "posts", :action => "index")
else
render "new"
end
end
def sent_messages
#notifications = Notification.where(:user_id => session[:user_id]).order("created_at DESC")
end
private
def notification_params
params.require(:notification).permit(:message, :user_id, :recipient_id, :status)
end
def read_message
#notifications = Notification.where(:recipient_id => session[:registered_id]).order("created_at DESC")
#notifications.read_all
end
end
Notification model
class Notification < ActiveRecord::Base
belongs_to :user
validates :message, :presence => true
validates :recipient_id, :presence => true
def self.read_all
Notification.all.update_all(status: true)
end
end
Notification migration
class CreateNotifications < ActiveRecord::Migration
def change
create_table :notifications do |t|
t.text :message
t.integer :user_id
t.string :recipient_id
t.boolean :read, default: false
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
** Notifications#index**
<div id = "messages_wrapper">
<% #notifications.each do |notification| %>
<div class="<%= notification.status ? 'message_wrapper_read' : 'message_wrapper_unread' %>">
<p><%= notification.message %></p>
<% if notification.user_id %>
<p class = "message_details">from <span><%= notification.user.registered_id %></span></p>
<% end %>
</div>
<% end %>
</div>
For the blocked users concept, you can add a custom attribute in user model called as blocked_users which is stored as an array in the db.
For postgresql you can use array datatypes.
In you notification.rb file,
#Validations,
validate :is_not_blocked_by_recipient
def is_not_blocked_by_recipient
#Check if the user is blocked or no, and write the logic
#self.errors.add()
end
It should work

No route matches {:action=>"show", :controller=>"items"} missing required keys: [:id]

Update: I've been trying to debug my files, so most of the files have changed recently
I am getting a strange error when trying to use a "new" action to my items_controller. Essentially, a wishlist has_many items and an item belongs_to wishlist. The error message is as follows:
Code
Here is my items_controller:
class ItemsController < ApplicationController
def show
#item = Item.find(params[:id])
end
def new
#item = Item.new
end
def create
#item = Item.new(item_params)
if #item.save
redirect_to "/wishlist", :notice => "Success!"
else
redirect_to "/wishlist", :notice => "Failure, try again later!"
end
end
def edit
#item = Item.find(params[:id])
end
def update
#item = Item.find(params[:id])
if #item.update_attributes(item_params)
redirect_to(:action => 'show', :id => #item.id)
else
render 'edit'
end
end
private
def item_params
params.require(:item).permit(:name,:size,:qty,:priority)
end
private
def create_params
params.require(:item).permit(:name,:size,:qty,:priority,:wishlist_id)
end
end
And my routes.rb:
Rails.application.routes.draw do
get '/wishlist' => 'wishlists#index', as: :wishlists
get '/wishlist/:id' => 'wishlists#show', as: :wishlist
get '/wishlist_items/new' => 'items#new'
get '/wishlist_items/:id' => 'items#show', as: :items
get '/wishlist_items/:id/edit' => 'items#edit', as: :edit_items
patch '/wishlist_items/:id' => 'items#update'
resources :items
And finally, my new.html.erb for the items model:
<h1>New Item</h1>
<div class="wishlist-new">
<% if true %>
<%= form_for(#item) do |f| %>
<%= f.text_field :name, :placeholder => "Name" %>
<%= f.text_field :size, :placeholder => "Specifications" %>
<%= f.text_field :qty, :placeholder => "Quantity" %>
<%= f.text_field :priority, :placeholder => "Priority" %>
<%= f.text_field :id, :placeholder => "Wishlist ID" %> # changing :id to :wishlist_id doesn't seem to do anything
<%= f.submit "Create Item", class: "btn-submit" %>
<% end %>
<% end %>
</div>
My migration files (so you know how my databases are structured:
# Migration file for items
class CreateItems < ActiveRecord::Migration
def change
drop_table :items
create_table :items do |t|
t.string :name
t.string :size
t.string :qty
t.integer :priority
t.references :wishlist
t.timestamps
end
end
end
# Migration File for Wishlists
class CreateWishlists < ActiveRecord::Migration
def change
drop_table :wishlists
create_table :wishlists do |t|
t.string :title
t.timestamps
end
end
end
Attempts to Debug
It seems like the routes.rb is sending requests to different methods in the items_controller because the error seems to say that /wishlist_items/new is accessing a show method even though its new method takes priority. To support this, the page loads properly when I comment out get '/wishlist_items/:id' => 'items#show', as: :items in the routes file. What happens is the page loads properly, and the Item is created properly (when I fill out the form) except that when I go into the console, it says that the Item created has a property of wishlist_id: nil even though I specified for it to be 1 in the form.
The method mentioned above has two problems: (1) it doesn't work entirely correctly, and (2) it becomes impossible to show a specific Item in the wishlist.
The error occurs before the inner section of the form_for is loaded, so the problem either is (a) a weird routing thing (as mentioned above) or (b) something weird happening to the #item variable.
Thanks in advance!

Rails sunspot price range facet

I'm trying to set up price faceting on one of my models but I can't seem to get it to work properly. No matter which facet I select it only returns listings that's price equals $0. I'm not sure what I'm missing here. Any help would be much appreciated. Here's my code:
Migration
class CreateListings < ActiveRecord::Migration
def change
create_table :listings do |t|
t.references :member
t.text :title
t.text :link
t.text :category
t.text :description
t.decimal :price, :precision => 8, :scale => 2
t.timestamps
end
add_index :listings, :member_id
add_attachment :listings, :feature
end
end
Model
class Listing < ActiveRecord::Base
searchable :auto_index => true, :auto_remove => true do
text :title, :boost => 5
text :marker_list, :boost => 2
text :category
string :marker_list, :multiple => true, :stored => true
float :price
end
end
Controller
class ListingsController < ApplicationController
def index
#listings = Listing.order('created_at desc').page(params[:page]).per_page(60)
#search = Listing.search do
fulltext params[:search]
facet(:marker_list, :limit => 48, :sort => :count)
with(:marker_list, params[:tag]) if params[:tag].present?
facet(:price) do
row("$0 - $25") do
with(:price, 0.00..25.00)
end
row("$25 - $75") do
with(:price, 25.01..75.00)
end
row("$75 - $250") do
with(:price, 75.01..250.00)
end
row("$250+") do
with(:price).greater_than(250.00)
end
end
with(:price, params[:price]) if params[:price].present?
end
#query = params[:search]
#facet = params[:tag]
#price_facet = params[:price]
#results = #search.results
respond_to do |format|
format.html # index.html.erb
format.json { render json: #listings }
end
end
end
View
<% for row in #search.facet(:price).rows %>
<span class="eloc"><%= link_to row.value, :price => row.value %></span>
<% end %>
You might have already found a way around this, one of the workarounds i could find for this was to use the range facet instead of the query facet. SO it would be something like :
facet :price, :range => 0..300, :range_interval => 50
with(:price, Range.new(*params[:price].first.split("..").map(&:to_i))) if params[:price].present?
Hope it helps!

Resources