I'm trying to create an "archive" feature in my Rails 3 application. I'm having trouble hiding child relations in my database when the parent is archived.
My project is set up such that the parent record has an attribute called archived_on. If the value is nil, then the record is not archived. How can I structure my query so that the child model so that it hides records with a parent that is archived?
The parent model has a scope:
scope :archived, where('archived_on != ?', nil)
which works fine for the parent model only.
I'm essentially looking for a way to do a Child.where('bla') that only returns things that are not archived.
Is there a way to do this without having to give each child its own archived_on attribute?
Here is what I did:
Create a models/concern/archivable.rb
module Archivable
extend ActiveSupport::Concern
included do
scope :archived, -> { where('archived_at != ?', nil) }
end
end
Then include it in your model classes you want to archive.
Generate a migration for each model, adding an 'archived_at' attribute.
Related
I have 2 tables, evenements and participants, represented by 2 models Evenement and Participant.
Those entities are belongsToMany related, so I have a third table evenement_participant following Laravel's naming conventions, and inside are foreign evenement_id and participant_id columns.
I'm able to retrieve the relationship and I can
dd($evenement->participants)
which gives me a collection of participants.
In my controller, I have this db call:
$evenements = Evenement::withCount(['participants' => function($query) {
$query->where('is_active', 1);
}])
This withCount generates a participants_count attribute for each evenement.
In my blade view, there is a for-each loop on the evenements collection, and somewhere I do this:
$evenement->participants_count
and I face this error:
Property [participants_count] does not exist on this collection
instance.
However, if instead I do the following in the same blade view
#dd($evenement->participants_count)
it dumps me the count.
I dropped all the evenements to keep just one for testing, and I still have the same error.
Sorry, made a typo in a condition inside my blade loop
In Rails 5, what is the difference between update and update_attributes methods. I'm seeing the following results for both the methods
Returns true/false
Checking for active record validation
Call backs are triggered
and also regarding update method a new thing was introduced in active record relation. I'm not able to understand it. What is the difference?
Moreover are we using update_attributes in Rails 5. It's not there in active record documentation.
I'm confused with all update methods. I need clarity
As of Rails 4.0.2, #update returns false if the update failed. Before Rails 4.0.2, #update returned the object that got updated. The main difference therefore was the return value. After this change, #update_attributes is just an alias of #update. It seems there are talks to deprecate #update_attributes in Rails 6 which is not released yet.
https://github.com/rails/rails/pull/31998
https://github.com/rails/rails/commit/5645149d3a27054450bd1130ff5715504638a5f5
From the rails 5 files it seems to me update can be used to update multiple objects(array of records) but update_attributes only work on single records otherwise both are same
From rails core files for update_attributes:
Updates a single attribute and saves the record.
This is especially useful for boolean flags on existing records. Also note that
Validation is skipped.
\Callbacks are invoked.
updated_at/updated_on column is updated if that column is available.
Updates all the attributes that are dirty in this object.
This method raises an ActiveRecord::ActiveRecordError if the
attribute is marked as readonly.
def update_attribute(name, value)
name = name.to_s
verify_readonly_attribute(name)
public_send("#{name}=", value)
save(validate: false)
end
For Update
Updates an object (or multiple objects) and saves it to the database, if validations pass.
The resulting object is returned whether the object was saved successfully to the database or not.
==== Parameters
+id+ - This should be the id or an array of ids to be updated.
+attributes+ - This should be a hash of attributes or an array of hashes.
==== Examples
# Updates one record
Person.update(15, user_name: "Samuel", group: "expert")
# Updates multiple records
people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
Person.update(people.keys, people.values)
# Updates multiple records from the result of a relation
people = Person.where(group: "expert")
people.update(group: "masters")
Note: Updating a large number of records will run an UPDATE
query for each record, which may cause a performance issue.
When running callbacks is not needed for each record update,
it is preferred to use {update_all}[rdoc-ref:Relation#update_all]
for updating all records in a single query.
def update(id, attributes)
if id.is_a?(Array)
id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
object.update(attributes[idx])
}
else
if ActiveRecord::Base === id
raise ArgumentError,
"You are passing an instance of ActiveRecord::Base to `update`. " \
"Please pass the id of the object by calling `.id`."
end
object = find(id)
object.update(attributes)
object
end
end
When we are working with update_column that time update is done on the database level there is no any contact with the rails ORM so whatever logic we have implemented like callbacks and validations all will be waste and wont be useful as this is going to be bypassed.
I found this article explained really well in just 30 seconds.
.update
Use update when you want to return false, for example in an if/else:
if record.update(params)
display_success
else
react_to_problem
end
.update!
Use update! when you want an error (for example: to avoid erroring silently, which could be very bad if an error was unexpected and you needed to know about it to fix it!):
record.update!(params) # raises is invalid
'update' respects the validation rules on model, while 'update_attributes' ignores validations.
I use in-memory database for testing. The schema is reloaded in every test.
Recently my rspec complains that a table is not found. The reason is that a scope is referencing another model at load time.
class Item
scope :public, where(:store_id => Store.public_store_ids())
class Store
def self.public_store_ids
self.public.pluck(:id)
The problem is that, during the initializing when item model is loaded in the memory, the schema for store table has not been loaded yet, but my scope will try to query the public store ids, which results in the "table not found" error.
How can I make my item scope to evaluate dynamically at runtime? I didn't want to use join because it can slow down my query, but would it be my only way?
I realized that I can just make it a class method so it is evaluated at run time
def self.public
store_ids = BeautyStreet::Store.public_store_ids()
where(:store_id => store_ids)
end
I'm wondering what the best design would be for persisteing a new child entity with NHibernate without accidentally overwriting the parent in the database.
The problem I have is that the child entity will look something like this:
class Child
{
Parent Parent;
// other fields
}
My problem is that the child has been supplied from the UI layer along with the ID of the parent, and that means that the Parent ref is basically uninitialized: It will have the ID populated but everything else null - because the only way to populate its fields would be an extra round trip to the database to read them.
Now if I call Session.SaveOrUpdate(child) on NHibernate, what's going to happen with the parent. I don't want NHibernate to cascade save the uninitialized parent since that would just destroy the data in the database. How would people approach this problem? Any best practices?
You must use the session.Load(parentid) to get the aggregate root. In contrast to the session.Get() method, this does not actually fetch any data from the database, it just instantiates a Parent proxy object used to add Child objects to the correct Parent in the DB (eg. get the foreign key correctly).
Your code would probably look something like:
// Set the Parent to a nhibernate proxy of the Parent using the ParentId supplied from the UI
childFromUI.Parent = Session.Load<Parent>(childFromUI.Parent.Id);
Session.Save(childFromUI);
This article explains Get/Load and the nhibernate caches really well
You should probably be working with the aggregate root (probably the Parent) when doing Saves (or SaveOrUpdates etc).
Why not just:
Fetch the parent object using the parent id you have in the child from the UI layer
Add the child to the parents 'children' collection
I think you have to overview your mapping configuration for nhibernate. If you have defined on the reference by the child to the parent that hi has to Cascade all, it will update it!
So if you say Cascade.None he will do nothing. All other are bad ideas. Because you allready has the information of this parent. So why read from db agane?!
If your models looks like this
class Parent
{
}
class Child
{
Parent myParent;
}
and you are trying to set the parent and save the child without having a full parent object, just the ID.
You could try this:
session.Lock(child.myParent, LockMode.None);
before saving, this should tell nhibernate that there are no changes to the parent object to persist and it should only look at the object for the Id to persist the association between Parent and Child
Ok this is a bit unusual, but I have a series of data collection forms that save data to their respective models. What I want to do is auto insert a common parent (activity/event log - separate model) record that will be common to each form. (All forms will save an implicit record in this model, before saving the child record). So the save sequence needs to be as follows:
1) On each detail form capture user input
2) Create a new parent record containing summary info (User ID, Record Type, Timestamp)
3) Capture the new Parent PK value for insertion (as a Foreign Key) into the detail record
4) Populate the detail record with user input data and the FK data, then save
5) Commit (or Rollback)
How can I do this - where are the hooks for something like this? Obviously I need to override some default bahaviour in Rails to do this - has anyone seen any examples that they can share?
TIA,
Brendan
P.S. Before you think this is a bass ackwards approach , I need to handle the use case where an activity/significant event occurs, but the underlying detail info is unavailable.
(This is likely to arise with externally imported data when only the parent will get created). Right now I'm primarily interested in exploring a Rails solution to this.
There are several ways to achieve this, depending on How you want it.
before_save filter in your child record model,
class YourModel < ActiveRecord::Base
before_save :create_parent
def create_parent
#do something here
end
end
Active Record Observers ( follows a observer pattern )
This goes in your environment.rb file
config.active_record.observers = :yourmodel_observer
create a yourmodel_observer.rb file
and code
class YourModelObserver < ActiveRecord::Observer
def after_save(object)
end
def after_update(object)
end
end