Rails cannot update column value - mysql

I have created Rails(version 3.2) application with mysql database. I have table Message with column content. I can update the following data using rails console but I can't using run same code from seeds.rb.
data: "Join **** Audio / Video Meeting. This is an online meeting by ****, the community marketplace to find products and services in your neighbourhood. http://*****.dev:3000/conferences/80"
I have following code in my seeds.rb file
all_messages = Message.all
all_messages.each do |message|
message_content = message.content
if message_content.present? && message_content[/\/(.*)\/(.*)\/conferences/,2].present?
message_content.slice! (message_content[/\/(.*)\/(.*)\/conferences/,2]+'/')
if message.update_attributes!(content: message_content)
puts message.content
else
puts "nothing"
end
end
end
It does't show any errors, but data is not updated in db and not shown any errors.
This is my model file
class Message < ActiveRecord::Base
attr_accessible :content
after_save :update_conversation_read_status
belongs_to :sender, :class_name => "Person"
belongs_to :conversation
has_one :request
validates_presence_of :sender_id
validates_presence_of :content
def update_conversation_read_status
conversation.update_attribute(:last_message_at, created_at)
conversation.participations.each do |p|
last_at = p.person.eql?(sender) ? :last_sent_at : :last_received_at
p.update_attributes({ :is_read => p.person.eql?(sender), last_at => created_at})
end
end
end
Note: content is text type in db.

Related

Rails: how to join two models through two different relations?

I have two models: Saft (a magazine) and Keyword. Each "Saft" is defined by a series of keywords, but also has a title, which is always one of its keywords. The Saft and Keyword models are connected through a HABTM join table in order to pull all the keywords and now I am trying to pull the title from the keywords table onto the saft/show.html.erb, too. I am trying to use the class_name option in order to pull the title. Therefore I created the Edition model.
class Saft < ActiveRecord::Base
# attr_accessible :colour, :cover_alt, :description, :number, :short
has_and_belongs_to_many :keywords, :join_table => "safts_keywords"
has_one :title, :through => :edition, :class_name => "keyword"
has_one :edition
end
class Keyword < ActiveRecord::Base
# attr_accessible :word, :description
has_and_belongs_to_many :safts, :join_table => "safts_keywords"
belongs_to :issue, :through => :edition, :class_name => "saft"
belongs_to :edition
end
class Edition < ActiveRecord::Base
# attr_accessible :saft_id, :keyword_id
belongs_to :title
belongs_to :issue
end
class SaftsController < ApplicationController
def show
#saft = Saft.find(params[:id])
end
show.html.erb
<%= #saft.title.upcase %>
I get the following error:
Started GET "/safts/2" for 127.0.0.1 at Sat Feb 10 17:31:28 +0100 2018
Connecting to database specified by database.yml
Processing by SaftsController#show as HTML
Parameters: {"id"=>"2"}
Saft Load (1.8ms) SELECT `safts`.* FROM `safts` WHERE `safts`.`id` = ? LIMIT 1 [["id", "2"]]
Image Load (0.3ms) SELECT `images`.* FROM `images` WHERE `images`.`saft_id` = 2
Rendered safts/show.html.erb within layouts/public (35.0ms)
Completed 500 Internal Server Error in 103ms
ActionView::Template::Error (uninitialized constant Saft::keyword):
29: </div>
30: <div class="saft_box col-content">
31: <div class="saft_keyword">
32: <strong><%= #saft.title.upcase %></strong>
33: </div>
34: <div class="saft_description">
35: <p><%= #saft.description %></p>
app/views/safts/show.html.erb:32:in `_app_views_safts_show_html_erb___758994895_2167416580'
How can I get this working?
When uncommenting #saft.title.upcase this implementation also breaks the Saft Keyword association, which I get working again by uncommenting the belongs_to :issue section in the Keyword model.
Some changes in your models:
class Saft < ActiveRecord::Base
#You don't need attr_accessible for fields in safts table
has_and_belongs_to_many :keywords, :join_table => "safts_keywords"
#The specific keyword that acts as title.
#You need a new field in safts table named title_id which references to a Keyword.
belongs_to :title, class_name => "Keyword", :foreign_key => 'title_id'
end
class Keyword < ActiveRecord::Base
#You don't need attr_accessible for fields in keywords table
has_and_belongs_to_many :safts, :join_table => "safts_keywords"
end
To get the Saft title, you use #saft.title.word.upcase if #saft.title
I don't think you need anything else on your models for the use case in your OP.

Delete an element from a collection

I'm facing to a stupid problem. I have created a collection select which is creating elements into a join table "staffs_task" to reference an association between the model staff and task.
And now I would like two things: (1) a button delete this association (2) and a little bit of code for my model staffs_task to avoid duplication, so with the task_id and staff_id. And last info, task is a model built by ranch
my code:
(the collection in new_task)
<%= select_tag "staffs_task", options_from_collection_for_select(#staffs, 'id', 'name') , :multiple => true %>
(task_controller)
skip_before_action :configure_sign_up_params
before_action :set_ranch
before_action :set_task, except: [:create]
def create
#task = #ranch.tasks.create(task_params)
#staffs = Staff.where(:id => params[:staffs_task])
#task.staffs << #staffs
if #task.save
#task.update(done: false)
#task.update(star: false)
flash[:success] = "The task was created "
else
flash[:success] = "The task was not created "
end
redirect_to #ranch
end
private
def task_params
params.require(:task).permit(:content, :deadline, :row_order, :date, :assigned_to)
end
def set_ranch
#ranch = Ranch.find(params[:ranch_id])
end
def set_task
#task = #ranch.tasks.find(params[:id])
end
So if you have any idea about one of this two things, your help would be welcome
Thanks in advance !!
Lets say you have the following many to many setup with a join model:
class Staff
has_many :assignments
has_many :tasks, through: :assignments
end
class Task
has_many :assignments
has_many :staff, through: :assignments
end
class Assignment
belongs_to :task
belongs_to :staff
end
Note that the plural of staff is staff - unless you are talking about the sticks carried by wizards.
ActiveRecord creates "magical" _ids setters for all has_many relationships. When used with a has_many through: relationship rails is smart enough to just remove the rows from the join table.
You can use this with the collection_select and collection_checkboxes methods:
<%= form_for([#task.ranch, #task]) do |f| %>
<%= f.collection_select(:staff_ids, Staff.all, :id, :name, multiple: true) %>
<% end %>
You would then set your controller up like so:
def create
#task = #ranch.tasks.new(task_params) do |t|
# this should really be done by setting default values
# for the DB columns
t.done = false
t.star = false
end
if #task.save
redirect_to #ranch, success: "The task was created"
else
render :new, error: "The task was not created"
end
end
private
def task_params
params.require(:task)
.permit(:content, :deadline, :row_order, :date, :assigned_to, staff_ids: [])
end
staff_ids: [] will allow an array of scalar values. Also not that .new and .create are not the same thing! You where saving the record 4 times if it was valid so the user has to wait for 4 expensive write queries when one will do.

rails - association params selected, but params "changing" on persist

I really am not sure of how to describe this problem and I've never had an issue like this before. I am trying to set up a "has_many :through" association that handles membership requests to a group. The other actions (destroy, update) seem to be working fine. Whenever I initiate the create action in my controller, the object shows that it is being passed the correct params and the association is created. However, it is creating an association only to the group with the "1" id. I have no idea how to clearly explain this problem or solve it. I'll post my log and code below.
To clarify my question: why is the data "changing" when it persists to the database (on create)?
Cliqs = Groups
Log:
Started POST "/cliqs/2/cliq_requests" for ::1 at 2016-03-31 20:35:32 -0500
Processing by CliqRequestsController#create as HTML
Parameters: {"authenticity_token"=>"uaVHFgB7digMywl2a/n2GKMtwi691WA/dw2F2mzdkSCK69C46TZICiSp90xldj3hosFwSOPEi3fSOvOSkIVMjA==", "cliq_id"=>"2"}
Cliq Load (0.0ms) SELECT `cliqs`.* FROM `cliqs` WHERE (2) LIMIT 1
User Load (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
(0.0ms) BEGIN
SQL (1.0ms) INSERT INTO `cliq_requests` (`cliq_id`, `user_id`, `created_at`, `updated_at`) VALUES (1, 1, '2016-04-01 01:35:32', '2016-04-01 01:35:32')
(198.0ms) COMMIT
Redirected to http://localhost:3000/cliqs
Completed 302 Found in 237ms (ActiveRecord: 199.0ms)
Controller Action:
def create
#cliq = Cliq.find_by(params[:cliq_id])
#cliq_request = current_user.cliq_requests.new(cliq: #cliq)
if #cliq_request.save
redirect_to cliqs_path
else
redirect_to current_user
end
end
Other Actions (just in case):
def update
#cliq = Cliq.find_by(params[:cliq_id])
#cliq_request = CliqRequest.find(params[:id])
#cliq_request.accept
end
def destroy
#cliq = Cliq.find_by(params[:cliq_id])
#cliq_request = CliqRequest.find(params[:id])
#cliq_request.destroy
if #cliq_request.destroy
redirect_to cliqs_path
else
redirect_to current_user
end
end
And the Models:
class User < ActiveRecord::Base
has_one :owned_cliq, foreign_key: 'owner_id', class_name: 'Cliq', dependent: :destroy
has_many :cliq_memberships, dependent: :destroy
has_many :cliqs, through: :cliq_memberships
has_many :cliq_requests, dependent: :destroy
end
class Cliq < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :cliq_memberships, dependent: :destroy
has_many :members, through: :cliq_memberships, source: :user
has_many :cliq_requests, dependent: :destroy
has_many :pending_members, through: :cliq_requests, source: :user, foreign_key: 'user_id'
end
class CliqRequest < ActiveRecord::Base
#from
belongs_to :user
#to
belongs_to :cliq
def accept
cliq.members << cliq.pending_members.find(user_id)
destroy
end
end
Finally my View:
<h1><%= #cliq.name %></h1>
<%= link_to 'Request to join Cliq', cliq_cliq_requests_path(#cliq, #cliq_request), :method => :post %>
<% #cliq_members.each do |cliq_member| %>
<ul><%= link_to cliq_member.username, user_path(cliq_member) %></ul>
<% end %>
<h3>Cliq Requests:</h3>
<ul>
<% #cliq.pending_members.each do |pending_member| %>
<%= link_to pending_member.username, user_path(pending_member) %>
<% end %>
<% #cliq.cliq_requests.each do |cliq_request| %>
<%= link_to "Accept", cliq_cliq_request_path(#cliq, cliq_request), :method => :put %>
<%= link_to "Deny", cliq_cliq_request_path(#cliq, cliq_request), :method => :delete %>
</ul>
<% end %>
As you found out yourself, using #cliq = Cliq.find_by(id: params[:cliq_id]) works, and #cliq = Cliq.find_by(params[:cliq_id]) does not. So why is this the case?
The find_by method matches on conditions. Using find_by, you can match on any attribute. For example, this would also work:
#cliq = Cliq.find_by(some_attribute: "foo")
So using find_by, you must specify the id attribute in order for the query to return the correct record. Your find_by query was actually running SQL that looked something like this:
SELECT `cliqs`.* FROM `cliqs` WHERE (2) LIMIT 1
That select statement will return the whole table, and the LIMIT 1 just grabs the first record.
As a bonus, the preferred rails way to assign #cliq based on an params[:cliq_id] would be using just find, which searches for the record using its primary key:
#cliq = Cliq.find(params[:cliq_id])

Rails searches the mistaken has_and_belongs_to_many table

I want to show all types which are related to a specific organisation in a select box of my document form. Types are part of the Ar engine. Organisations are part of another existing engine.
module Ar
module OrganisationPatch
extend ActiveSupport::Concern
included do
attr_accessible :ar_document_id
has_many :ar_documents, :class_name => 'Ar::Document'
has_and_belongs_to_many :ar_types, :class_name => 'Ar::Type'
end
end
end
module Ar
class Type < ActiveRecord::Base
attr_accessible :name
has_many :documents
has_and_belongs_to_many :organisations
end
end
class CreateTypeOrganisations < ActiveRecord::Migration
def change
create_table :ar_type_organisations, id: false do |t|
t.uuid :type_id, index: true
t.uuid :organisation_id, index: true
end
end
end
In my documents_controller I load types for forms about the before filter. The superior returns the organisation object:
def load_form_objects
unless current_user.admin?
#types = current_user.superior.ar_types
else
#types = Type.all
end
end
Calling the page I get this error and ask me why he is looking for a table called organisations_types:
ActiveRecord::StatementInvalid in Ar/documents#new
Mysql2::Error: Table 'portal.organisations_types' doesn't exist:
SELECT ar_types.* FROM ar_types INNER JOIN organisations_types
ON ar_types.id = organisations_types.type_id WHERE
organisations_types.organisation_id =
x'891c3986b33845d08d3951645a4f27d5'
Someone knows what I am doing wrong here?
Your table name isn’t map with lexical order what has_and_belongs_to_many expect. ( Expected order is organisations_types )
So you have to add :join_table option in both model's association. Like this,
has_and_belongs_to_many :ar_types, :class_name => 'Ar::Type', join_table: "ar_type_organisations"
has_and_belongs_to_many :organisations, join_table: "ar_type_organisations"
Reference

Rails search a model based on multiple parameters using a form

So... I've been working on creating a search form for a rails application. I've gone through the railscast episodes 37, 111, and 112.
While the simple text search with a text input field works. I need to be able to define more parameters to refine the search.
I've found a few other methods, some using scopes...I keep running into issues getting any of these working in my application....
What I have right now is a simple form defined on my home index that points at my assets index:
<% form_tag assets_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= collection_select(:type_id, :type_id, Type.where("type_for = 'asset'"), :id, :name) %>
<%= submit_tag "Search", :search => nil %>
<% end %>
my asset.rb model:
class Asset < ActiveRecord::Base
has_many :children_assets, :class_name => "Asset"
has_and_belongs_to_many :groups, :join_table => "assets_groups"
belongs_to :parent_asset,
:class_name => "Asset",
:foreign_key => "parent_asset_id"
belongs_to :asset_type,
:class_name => "Type",
:conditions => "type_for = 'asset'"
belongs_to :asset_status,
:class_name => "Status",
:conditions => "status_for = 'asset'"
belongs_to :location
belongs_to :funding_source
has_many :transactions
def self.search(search)
if search
find(:all, :conditions => ['nmc_name LIKE ? AND type_id = ?', "%#{search}%", "%#{search}"])
else
find(:all)
end
end
end
in the asset_controller.rb
def index
unless params[:search].nil?
#title = "Assets"
#search = params[:search]
#assets = Asset.search(params[:search]).paginate(page: params[:page], per_page: 25)
else
#title = "Assets"
#assets = Asset.where('').paginate(page: params[:page], per_page: 25)
end
end
I just dont understand what it is that I'm not seeing here. I can run a similar mysql query and get the result I want. I just dont know how to format this in rails...
Any guidance on this would be amazing right now. Thanks!
It looks as though you're trying to search for a specific type of asset, but your search method in the Asset model is only using one of the user supplied parameters.
Judging by the form you're using, your controller will be receiving the params
params = {
search: 'Search Text',
type_id: 1
}
In your controller, you're only using search, so I'd change your method to include this:
#assets = Asset.search(params[:search], params[:type_id]).paginate(page: params[:page], per_page: 25)
Then amend the Assets model to use it
def self.search(search, type_id)
if search
find(:all, :conditions => ['nmc_name LIKE ? AND type_id = ?', "%#{search}%", "%#{type_id}"])
else
find(:all)
end
end