How to use custom version table instead of version table? - ruby-on-rails-5

For a project I'm currently working on I need to implement object versioning. Unfortunately I need to keep a full history of each object, so a single table solution like Papertrail would quickly become un-manageable. So I am trying to have custom version table for each object using papertrail. I followed the documentation but getting error on creating object
Model::UnknownAttributeError: unknown attribute 'event' for ArticleVersion.
Here is the implemented code :
class Article < ActiveRecord::Base
has_paper_trail class_name: 'ArticleVersion'
end
class ArticleVersion < PaperTrail::Version
self.table_name = :article_versions
end
module PaperTrail
class Version < ActiveRecord::Base
include PaperTrail::VersionConcern
self.abstract_class = true
end
end
Here is the migration for Article migrations:
class CreateArticleVersions < ActiveRecord::Migration[5.0]
def change
create_table :article_versions do |t|
t.string :title
t.text :text
t.timestamps
end
end
end
and When I am trying to create article by Article.create(text:'some text')
I am getting the above mentioned error.
Can anyone help me to figure out if I am missing anything.

create_table :article_versions do |t|
t.string :title
t.text :text
t.timestamps
end
Model::UnknownAttributeError: unknown attribute 'event' for ArticleVersion.
The ArticleVersion model lacks an event attribute because the article_versions table lacks an event column.

Related

How can Devise users create an invitation for others to accept and start and able to finish invitation

I'm creating an app in rails that has User's and that has Dogwalkers, these users are created on Devise. So, I wan't that a User is able to create a Dog walk for and set, date, time and add the dogs that are going to take for a walk.
I got my Dog's Database on Sqlite:
create_table :dogs do |t|
t.string :name
t.string :photo
t.string :race
t.references :user, foreign_key: true
t.timestamps
end
add_index :dogs, [:user_id, :created_at]
And I got my Walks model:
class CreateWalks < ActiveRecord::Migration[5.2]
def change
create_table :walks do |t|
t.integer :walk_id
t.date :walk_at
t.datetime :walk_start_at
t.datetime :walk_end_at
t.integer :status
t.references :dog, foreign_key: true
t.references :user, foreign_key: true
t.references :dogwalker, foreign_key: true
t.float :dogprice
t.integer :doglimit
t.timestamps
end
add_index :walks, [:user_id, :created_at]
end
end
So how can I make that the user is able to create a Walk, and let the Dog walker able to see it on it's own dashboard (which I already created). The Dog Walker will accept it and it will send a notification to the user that it has been accept it. Once the user has received there dog's the walk has finish and create a history of the walk.
What I been doing:
Created the databases that I show above.
Made the views
Made the forms for the user able to create a new Dog trip
Created the controllers for the walk
Hope this possible! Thanks for you help!!!
I think what you want to do is create a form for a new Walk. The user(dog owner) will fin the required fields, like date, walk_start_at and walk_end_at. Maybe some more, but that's up to you.
On the users dashboard(the dogwalker) you can list all walks that available by:
#walks = Walk.where(dogwalker: nil) This will give you all the walks that don't have a walker yet. For each of these walks you also add a form for walk that only needs a submit button. When the dogwalker hits the button it goes to the update action from the Walk. There you receive the params and you can set the dogwalker.
Now on the dogowner can see that the walk is accepted.

Adding attribute to already existing model

I am trying to add user:references onto my already existing model. This is what I originally wrote:
rails g model Post title:string description:text
I do this to add the user:references by running rails generate migration add_user_to_posts user:references, I am receiving this error upon running rake db:migrate:
-- create_table(:users)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: table "users" already exists
I am reading the error and I understand I already have a User model, however, I want to add this attribute to the Post model, not the User model.
Db file:
Posts:
class CreatePosts < ActiveRecord::Migration[5.0]
def change
create_table :posts do |t|
t.string :title
t.text :description
t.timestamps
end
end
end
Trying to add the user to posts:
class AddUserToPosts < ActiveRecord::Migration[5.0]
def change
add_reference :posts, :user, foreign_key: true
end
end
Users:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :name
t.string :uid
t.string :avatar_url
t.timestamps
end
add_index :users, :uid
end
end
However, rake db:migrate gives me the error above.

Rails associations has_many through ban/archive solution?

I'm new in Rails and am working on a problem. I have two tables:
Shoes and Socks
A Shoe can have many Socks, but only one active Sock. Other Socks are inactive. All Socks are also unique with unique patterns. I want to make sure I don't have socks with the same pattern. I think I can do this three ways
1) Using an additional column in table socks to represent the active sock
class Shoe < ActiveRecord::Base
has_many :socks
end
class Sock < ActiveRecord::Base
belongs_to :shoe
end
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :size
t.timestamps null: false
end
create_table :socks do |t|
t.belongs_to :shoe, index:true
t.string :pattern
t.boolean :active
t.timestamps null: false
end
end
end
This seems fairly simple, but cumbersome. I would search socks with shoe_id, and pull out the active_sock and return it's pattern. I think I would index [active_sock, shoe_id] in an array to speed it up.
2) Using an additional table to archive inactive socks
class Shoe < ActiveRecord::Base
has_many :socks
has_many :inactive_socks
end
class Sock < ActiveRecord::Base
belongs_to :Shoe
end
class Inactive_sock < ActiveRecord::Base
belongs_to :Shoe
end
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :name
t.timestamps null: false
end
create_table :socks do |t|
t.belongs_to :shoe, index:true
t.string :pattern
t.timestamps null: false
end
create_table :inactive_socks do |t|
t.belongs_to :shoe, index:true
t.string :pattern
t.timestamps null: false
end
end
end
This seems cumbersome as well, but when you are just dealing with active socks easy to use and fast. But when buying a new sock, I have to check the pattern with both tables.
3) Using a has_many :through relationship
class Shoe < ActiveRecord::Base
has_many :active_socks
has_many :socks, through: active_socks
end
class Active_Sock < ActiveRecord::Base
belongs_to :Shoe
belongs_to :Sock
end
class Sock < ActiveRecord::Base
has_many :active_socks
has_many :shoes, through: active_socks
end
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :name
t.timestamps null: false
end
create_table :socks do |t|
t.string :pattern
t.timestamps null: false
end
create_table :active_socks do |t|
t.belongs_to :shoe, index: true
t.belongs_to :sock, index: true
t.string :pattern
t.boolean :active
t.timestamps null: false
end
end
end
This seems like option 2, but I feel like I'm using Rails tools to make it less cumbersome. When I'm searching for patterns I'm just checking the socks table, when I'm searching for the one active_sock I'm just searching active_socks table.
I've read up on similar posts, and it seems options 1 and 2 are commonly used in closed_accounts, banning users, banning posts, archiving etc. Situations where you need to differentiate data that is only slightly different. The choice there seems to be look at what you need and choose the option 1 or 2 that best fits you.
My understanding for has_many through situations seems to be when you have a relationship and you need extra meta data you can use it. I think that fits this situation.
Did I set up option 1 correctly and am I right that indexing the array of [shoe_id and active] will give me a faster search? Is option 3 an appropriate use of has_many through? Would my explanation of option 3 work?
What are your usage patterns? I'm guessing you just want to be able to find the active Sock given a Shoe, and if a given Sock is active or inactive. To quickly find the active Sock of a given Shoe, you merely need to give the Sock a foreign key to its Shoe with the belongs_to association.
class Sock < ActiveRecord::Base
belongs_to :shoe
end
And to find out if a Sock is active or inactive, give its owner shoe a reference to its active sock like so:
class Shoe < ActiveRecord::Base
belongs_to :sock
end
Now, you can just go to its owner Shoe and check if the Shoe's active sock is the current Sock or not. E.g.
def is_active
owner_shoe.active_sock == self
Basically, associate them with foreign keys and you're good to go!
P.S. you pluralized Socks but the Rails convention is to use singular for model names.
EDIT: You asked for a migration so here's one for the code above. Caveat: I haven't done migrations in a long time in Rails so something might be off.
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.belongs_to :active_sock, foreign_key: "sock_id"
t.string :size
t.timestamps null: false
end
create_table :socks do |t|
t.belongs :owner_shoe, foreign_key: "shoe_id"
t.string :pattern
end
end
end

using activeuuid gem for existing database in rails

I need to implement activeuuid gem to have UUIDs instead of default Rails ids. we can implement it for creating new migration as:
class CreateStudents < ActiveRecord::Migration
def change
create_table :students, :id => false do |t|
t.uuid :id, :primary_key => true
t.string :name
t.string :email
t.timestamps
end
end
end
And in model we include ActiveUUID::UUID as:
class Student < ActiveRecord::Base
attr_accessible :email, :name
include ActiveUUID::UUID
end
Now I already have a database so how can I implement the activeuuid gem to have UUIDs instead of default Rails ids for existing DB?
Need to make changes in all migrations or what?
Need help in this regard. thanks
The UUID is stored as a binary field w/ 16 positions as I found here: https://github.com/jashmenn/activeuuid/blob/master/lib/activeuuid/patches.rb#L62
It worked for me (existing table without records):
def change
reversible do |dir|
change_table :payments do |t|
dir.up { t.change :id, :binary, limit: 16, :primary_key => true }
dir.down { t.change :id, :integer }
end
end
end
Don't forget to add those lines to your model as well:
include ActiveUUID::UUID
natural_key :at_least_one_field_here
More info in the github repo: https://github.com/jashmenn/activeuuid/

Is there a gem to manage settings per resource?

I need a gem that can abstract resource setting management. Basically I want something like
#person = Person.find(1)
#person.settings <- this gives a hash of key/value pairs associated with this resource
I also need a way to have "default" settings per Person as well as a way to override those for specific #person. The settings should be persisted in SQL db.
This is an old plugin but it's pretty full featured and I've used it in a number of different projects: has_easy
For Rails3 the generator won't work but you can just create the migration it needs by hand.
class CreateHasEasyThings < ActiveRecord::Migration
def self.up
create_table :has_easy_things do |t|
t.string :model_type, :null => false
t.integer :model_id, :null => false
t.string :context
t.string :name, :null => false
t.string :value
t.timestamps
end
end
def self.down
drop_table :has_easy_things
end
end
Basically the way it works is that you can associate any model you want with this object and it will store preferences, settings or really pretty much anything that can be serialized by Rails.
You define your settings or what have you on the model:
class User < ActiveRecord::Base
has_easy :settings do |p|
p.define :language
p.define :theme
end
has_easy :flags do |f|
f.define :is_admin
f.define :is_spammer
end
end
which dynamically creates a bunch of methods for accessing settings and flags.
u = User.new
u.settings.language = 'en/us'
u.flags.is_admin = true
If you have rails 2 or rails 3, check out Ledermann's rails-settings gem which has a syntax to get all key-value pairs just like you asked for:
son.settings.all
Easy to add settings:
son.settings.key = value
You also get activerecord scopes to search based on settings. And you can set default settings and global (application scope) settings.
For rails 2, you need to use version "~> 1.x" and follow docs: https://github.com/ledermann/rails-settings/blob/c5c34faf1bbe5742b58f6b3acff3874edc6e4bbc/README.md
If you need :before and :after event handling, check https://github.com/exceed/preferential/