How to assign fixed data to database by ruby on rails - ruby-on-rails

In ruby on rails, we usually assign data in model by console.
like #model = Model.attribute (data). Like #user = User.create("John")
My question is, if I want to have the data fixed, can I do it through model or controller? SO that if I want to change the detail, I do not have to check and find in console.
For example, I need 5 users and 5 users only, so I set user_id = 1 is John user_id = 2 is David...etc in model. Can I do that? How?

You can create "fixed" data by seeding data via the seeds.rb file in your Rails application.
Let's suppose you want to create a user with specific data. Go into your app's db directory and open seeds.rb where you can add code that writes entries in your database.
User.create( email: 'patron#patron.com',
system_id: 2,
subdomain: 'foo',
external_id: '',
first_name: 'Joe',
last_name: 'Patron',
phone_number: '213 555 1212',
role: 'default',
user_status_id: 1,
password: 'password',
password_confirmation: 'password',
terms_accepted_at: datetime,
created_at: datetime,
updated_at: datetime)
You can see that you're calling the create method from whatever model you're working with and passing along all required parameters -- in other words, you're just using Ruby to build objects.
Once you have all your objects created, remember to run rake db:seed any time you reset your database in order to run the seeds.rb file to populate your database.

Related

Nil Associations with Rails Fixtures... how to fix?

I have a Rails 5.1 project using rspec/fixtures and I am having trouble getting fixtures to load objects associated with belongs_to/has_one/has_many: the object I requested the fixture for comes back with its _id columns filled with a seemingly-random number and ActiveRecord sees the association as nil. This occurs on large classes with many associations as well as small data classes with only a few fields.
If, in my test code, I assign those associations with normal Ruby code, objects behave as normal and my tests pass. However when loading the same data through fixtures, associated records are not available and tests that require data spanning across associations fail.
As an example, here are two affected classes:
#app/models/location.rb
class Location < ActiveRecord::Base
has_many :orders
has_many :end_user
belongs_to :retailer
belongs_to :depot
end
#app/models/retailer.rb
class Retailer < ActiveRecord::Base
has_many :locations
end
And here are two corresponding fixtures files:
#spec/fixtures/locations.yml
loc_paris:
retailer: ret_europe (Retailer)
name: "Paris"
nickname: "paris"
loc_washington:
retailer: ret_usa (Retailer)
name: "Washington"
nickname: "washington"
#spec/fixtures/retailers.yml
ret_europe:
name: "AcmeCo France"
nickname: "acmecofr"
currency_type: "EUR"
ret_usa:
name: "AcmeCo USA"
nickname: "acmecousa"
currency_type: "USD"
With the above data, running pp locations(:loc_paris) results in:
#<Location:0x0000000006eee1d8
id: 35456173,
name: "Paris",
nickname: "paris",
retailer_id: 399879241,
created_at: Wed, 23 May 2018 22:39:56 UTC +00:00,
updated_at: Wed, 23 May 2018 22:39:56 UTC +00:00>
Those id numbers are consistent through multiple calls, at least in the same RSpec context. (I put pp locations(:loc_paris) in a let block.) Yet pp locations(:loc_paris).retailer returns nil.
I tried using FactoryBot however we had to switch away from it. I am trying to give fixtures an honest shake but it seems like we are best off simply building data objects in the actual test code... because that solutions works without complaining :/
Am I doing something wrong here? Are we asking too much of fixtures?
Thank you!
Tom
Problem with fixtures
Looking at what you've done, locations(:loc_paris) will find the record described in locations.yml, but locations(:loc_paris).retailer won't.
Rails Associations work like this:
locations(:loc_paris).retailer will look for the retailer with retailer_id mentioned in locations(:loc_paris) record. In your case retailer_id: 399879241 and there is no reseller with this id that's why it returns Nil.
Solution:
Describe fixtures like this:
#spec/fixtures/locations.yml
loc_paris:
retailer_id: 1
name: "Paris"
nickname: "paris"
loc_washington:
retailer_id: 2
name: "Washington"
nickname: "washington"
#spec/fixtures/retailers.yml
ret_europe:
id: 1
name: "AcmeCo France"
nickname: "acmecofr"
currency_type: "EUR"
ret_usa:
id: 2
name: "AcmeCo USA"
nickname: "acmecousa"
currency_type: "USD"
Now, locations(:loc_paris).retailer will look for the retailer with retailer_id mentioned in locations(:loc_paris) record i.e. retailer_id: 1 and there is a reseller ret_europe with this id. Problem Solved
When you run rspec, at first rspec saves these fixtures into your database with some auto-generated id values (if id not provided explicitly), that's why id and reseller_id are some random values. If you don't want the id of locations.yml record to be some random value, you can provide it yourself like this:
loc_paris:
id: 1
retailer_id: 1
name: "Paris"
nickname: "paris"
Tips:
As rspec runs in test environment (mentioned in app/spec/rails_helper.rb) and as I mentioned earlier whenever you run rspec, at first it saves the fixtures into your database. If your local and test database are same, fixtures will replace the actual database records of your database. In your case, records in locations and resellers table record will be completely erased and replaced with these fixtures. So, make different database for test environment.
Hope this answer is helpful

Rails app not recognizing active record entries?

I am building a rails app and have create a basic and pro plan in database, here is output of Plan.all from rails console:
=> #<ActiveRecord::Relation [#<Plan id: 1, name: "basic", price: #<BigDecimal:7f9aad0bf578,'0.0',9(27)>, created_at: "2016-11-03 04:21:55", updated_at: "2016-11-03 04:21:55">, #<Plan id: 2, name: "pro", price: #<BigDecimal:7f9aad0be448,'0.1E2',9(27)>, created_at: "2016-11-03 04:22:21", updated_at: "2016-11-03 04:22:21">]>
When I create a user under either plan i get this error:
1 error prohibited this user from being saved: Plan must exist
Not sure why it is not picking up the plans.
The error "Plan must exist" when you create a user means that whatever plan_id you gave to the user does not match up with the id of an actual plan in the database. Check the plans you have created, look a their ids, and make sure the plan_id you give to your user matches the id of one of those plans.
Note: it is not enough to create database tables for each of the 2 types of plans, you must create actual instances of the plans.
Also: check to make sure you has_many / belongs_to relationship is set up correctly.

FactoryGirl rspec, while creating multiple factories at once

When I am creating multiple object of Factory using method create_list, the order and where method don't work on it because create_list creates the array of factory objects.
users = FactoryGirl.create_list(:user, 5)
users.order('name ASC')
It gives undefined method order for Array
So, what should I do to create the multiple factory objects inside the ActiveRecord Collection?
The order and where methods are not defined on Array but on ActiveRecord::Relation. It's the kind of thing that gets passed around by the ActiveRecord query interface. You simply cannot run a query on an array. To run a query you need to start from scratch:
create_list, :user, 5
users = User.where(...).order(name: :asc)
But you might as well directly pass your arguments to create_list so that the condition is satisfied without needing to re-select the users. I also often find myself writing arrays explicitly when I need to alter values in each row e. g.
users = [
create(:user, name: 'Alfred'),
create(:user, name: 'Bob'),
create(:user, name: 'Charlie'),
create(:user, name: 'David'),
create(:user, name: 'Egon')
]
The users are already ordered by name and you're good to go. If you have some condition in the where clause that for example separates the users in two groups, you can just go ahead and separate these users directly. For example imagine we have an admin flag in the users table and you want to create many users, some being admins and some not. Then you'd do
admins = [
create(:user, name: 'Alfred', admin: true),
create(:user, name: 'Charlie', admin: true),
create(:user, name: 'Egon', admin: true)
]
visitors = [
create(:user, name: 'Bob'),
create(:user, name: 'David')
]
No need to query at all. Of course you can also do that in let syntax if you like.

extract attributes values from an activerecord query object in rails 2.3

In my controller I have a #attach object and when I inspect it, it has values as
[#<MessageAddlAttachment id: 80, reminder_id: 112, msg_attachment_file_name: "24.png", msg_attachment_content_type: "image/png", msg_attachment_file_size: 272368, created_at: "2013-10-10 12:04:37", updated_at: "2013-10-10 12:04:37">, #<MessageAddlAttachment id: 81, reminder_id: 112, msg_attachment_file_name: "37.png", msg_attachment_content_type: "image/png", msg_attachment_file_size: 333986, created_at: "2013-10-10 12:04:37", updated_at: "2013-10-10 12:04:37">]
So now after some operation I need to create an entry in this MessageAddlAttachment table with different ids. How can I achieve it. I tried dup but it will have same ids. Please help
dup is your friend in rails 4. it will create a copy but removes the id value:
u = User.first
=> #<User id: 1, ...>
u.dup
=> #<User id: nil, ...>
u.dup.save
(0.2ms) begin transaction
...
Starting either rails 3.2 or 3.1, you want to use dup. Prior to that, you should use clone instead. That will give you new values for the id field; you might want to pay attention to what happens to your created_at and updated_at fields as well.
Another issue to watch out for is if you have any date fields with validations that say they must be after "today's date", they may have been valid when the original record was saved, but not when the new record is saved. How you resolve this will depend on your situation; you might want to disable validations completely while cloning, or adjust the values in the new records.

audited, Look up audits belonging to a user

I am using audited to track changes for a model called Page. I would like to be able to find all audits associated with a certain user (via user_id in the audits table).
How can I do that? So far, the only way I have found to access the Audit model is like this:
#audits = Audited::Adapters::ActiveRecord::Audit.all
Which just doesn't seem like it's the right way to do things.
Trying #audits = Audit.all gives an Uninitialized constant error.
Is there a more graceful way of interacting with models provided by gems?
Maybe something like
include Audited::Adapters::ActiveRecord::Audit
and then you can do
#audits = Audit.all
?
I think that should work... Or better yet:
include Audited
You can access all Audit records with
Audited::Audit.all
I got the result when I typed the
Audited.audit_class
DEPRECATION WARNING: audit_class is deprecated and will be removed
from Rails 5.0 (Audited.audit_class is now always Audited::Audit. This
method will be removed.).
I know this isn't an efficient way to do so, but this is how I do it.
In a Rails console I retrieve a record which I know is audited.
#page = Page.first
I then retrieve that record's first audit.
#audit = #page.audits.first
You can then call #class on #audit
#audit.class
Result:
Audited::Adapters::ActiveRecord::Audit(id: integer, created_at:
datetime, updated_at: datetime, auditable_id: integer, auditable_type:
string, user_id: integer, user_type: string, username: string, action:
string, audited_changes: text, version: integer, comment: string,
full_model: text, remote_address: string, associated_id: integer,
associated_type: string, request_uuid: string)
Audited::Adapters::ActiveRecord::Audit is the class name, which you can then use in your search.
audits = Audited::Adapters::ActiveRecord::Audit.where(:user_id => 8675309)

Resources