Following this guide here, I want to add a trigger, that updates more than one attribute of a model. Here is what I have now:
class AddTriggerToArguments < ActiveRecord::Migration[5.0]
def up
execute %{
CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON arguments FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(tsv_body, 'pg_catalog.simple', description);
}
end
def down
execute %{DROP TRIGGER tsvectorupdate ON arguments}
end
end
As you can see in the line
tsvector_update_trigger(tsv_body, 'pg_catalog.simple', description);
updates the description attribute. But what do I have to do, so that multiple attributes will be updated?
My model has title and description as attributes. I want to add title to the trigger. I tried this, but it didnt work:
def up
execute %{
CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON arguments FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(tsv_body, 'pg_catalog.simple', description)
tsvector_update_trigger(tsv_body, 'pg_catalog.simple', title);
}
end
But that didn't work. Can anyone help me?
tsvector_update_trigger(tsv_body, 'pg_catalog.simple', description, title)
Seems to work.
Related
I have a form with checkboxes that get passed as an array "list_person_ids" on form submit. My models are "Occurance" which has an n:m relationship with "ListPerson" through the Model "Person". "list_person_ids" are saved in Person with the Occurance id and the ListPerson id.
I want to append one or more values to the array before this gets saved. The reason I need to do this is because the user can also add a new value in ListPerson using a textbox with the name "person_name".
def create
#occurance = Occurance.new(occurance_params)
add_person_id(#occurance)
...
# save
end
def add_person_id(object)
if params[:person_check] == '1'
object.list_person_ids.push( ListPerson.find_or_create_by(person: params[:person_name]).id )
end
end
def occurance_params
params.require(:occurance).permit(:person_check, :person_name, dim_person_ids: [])
end
find_or_create_by is successful, but nothing gets pushed to the array "list_person_ids". There is also no error message. Do I have to give permission somewhere to append this array? Please let me know if some information is missing.
on your model you can do something like below:
....
before_create :create_lists
private
def create_lists
ListPerson.find_or_create_by(list_person_ids: person_name.id)
end
How do you insert a input name="title0" in the title column in the rails column?
plz using params.require().permit()
#bank = Bank.new(params.require(:bank).permit(:title))
this is POST title => DB column title
but I want is POST title0 => DB column title
Sorry, i am bad at english
First, refactor your code as described here. So, your code will become
def probably_create_action
#bank = Bank.new(bank_params)
end
...
private
def bank_params
params.require(:bank).permit(:param1, :param2, :param3, :title0)
end
Attributes not listed inside bank_params method will not be passed.
UPDATE
Fighting with conventions is not a good practice. But below snippet might save your day.
#app/models/bank.rb
def title0=(inp)
self.title = inp
end
So I have many items that can be part of many different pages. So here is the simplified models:
class Page
#we just need the id for this question
end
class Item
embeds_many :page_usages
end
class PageUsage
field :position, :default => 0
embedded_in :item
belongs_to :page
end
So the page_usage is holding the position of the items on every page. I want to put that into solr so it can pull up the right items and in the right order for me.
I've looked into dynamic fields and ended up with something like this but not really sure. I want the field to basically be the page id pointing to the position of the item:
searchable do
dynamic_integer :page_usages do
page_usages.inject({}) do |hash, page_usage|
hash.merge(page_usage.page_id => page_usage.position)
end
end
end
And in my controller I have something like this:
Item.search do
dynamic :page_usages do
#i have #page.id but not sure how to get all items with the #page.id
end
end
I need something that will check if the item exist on the page and find out how to use order_by with the position. Is this possible this way or do I have to find another solution?
Solved it after lots of trial and error.
searchable do
dynamic_integer :page_usages do
page_usages.inject({}) do |hash, page_usage|
hash.merge( ("page" + page_usage.page_id.to_s).to_sym => page_usage.position)
end
end
end
So I first had to store the key as a symbol which is important. But the problem I ran into was that the symbol couldn't have quotes in it. So if you call to_sym on the id, it would look something like :"123456789" which will give you a "wrong constant name" error later on. So I threw on a string before the id to create the new symbol which looks like :page123456789.
Next step was to create the search block:
Item.search do
dynamic :page_usages do
with ("page" + page.id.to_s).to_sym ).greater_than(-1)
order_by(("page" + page.id.to_s).to_sym, :asc)
end
end
By using that page id, I was able to pull up all the right items in the right order. I used greater than -1 because by default my positions start at 0 and goes up from there.
I am having problems with modifying a function in spree. The function is called copy_price
The original version is something like this:
def copy_price
if variant
self.price = variant.price if price.nil?
self.currency = variant.currency if currency.nil?
end
end
which if I understand right will update the line_item's unit price only if the price is null, which I believe it shouldn't be inside the orders page (after the order is completed).
I noticed that order changes if the master price is changed inside the admin section even after the order is complete.
So i thought that the copy_price function was to blame, but each time i try to modify it there is no change.
E.g.
def copy_price
#price_run = true
self.price = 30.00
end
def get_price_run
if #price_run == true
return "true"
else
return "false"
end
end
and call get_price_run inside my view to print out if the price run was actually run. and It keeps outputting false. Does anyone know why that would be.
I have figured out the problem. The function copy_price is only called when the line item is first created (e.g. when you put it into the cart). So when I was trying to find out if it was called while looking at the admin orders page it was never getting called.
I am trying to use PostgreSQL triggers in my rails app. So I tried using this migration where execution of triggers is supposedly easy:
-- class AddTriggersToProducts < ActiveRecord::Migration
def self.up
table :products
execute %q{
create trigger trig1 before insert on products for each row
begin
price = price + 5
end;
}
end
def self.down
execute 'DROP TRIGGER trig1'
end
end
But this didn't change anything. I don't know where to write the procedure or function if I am going to use one here ...
"Creating a trigger" consists of two steps in PostgreSQL:
1.) Create a trigger function - with special return value trigger:
CREATE FUNCTION trg_update_prod_price()
RETURNS trigger AS
$func$
BEGIN
NEW.price := NEW.price + 5;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Multiple triggers can use the same trigger function.
2.) Create a trigger calling an existing trigger function:
CREATE TRIGGER update_prod_price
BEFORE INSERT ON products
FOR EACH ROW EXECUTE PROCEDURE trg_update_prod_price();
To "drop the trigger" (meaning the trigger function), you have to first drop all triggers referencing it and then drop the trigger function itself.
DROP TRIGGER update_prod_price ON products;
DROP FUNCTION trg_update_prod_price();
If you drop a table, all attached triggers are dropped with it. No need to drop those separately.
Does something like this work? Creating a function and then executing the function for the trigger:
def self.up
execute %q{
create or replace function update_price() returns trigger as $$
begin
NEW.price := NEW.price + 5;
return NEW;
end;
$$ language plpgsql }
execute %{ create trigger trig1 before insert on products for each row execute function update_price()}
end
The hair_trigger gem is a nice way to manage the creation of triggers.
Here is an example from hair_trigger's docs:
class AccountUser < ActiveRecord::Base
trigger.after(:insert) do
"UPDATE accounts SET user_count = user_count + 1 WHERE id = NEW.account_id;"
end
trigger.after(:update).of(:name) do
"INSERT INTO user_changes(id, name) VALUES(NEW.id, NEW.name);"
end
end